Initial public release (FW 0.64)

This commit is contained in:
marqs 2016-02-23 01:03:50 +02:00
commit 388c464f63
264 changed files with 66416 additions and 0 deletions

674
LICENSE Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or 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 your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

4
README.md Normal file
View File

@ -0,0 +1,4 @@
Open Source Scan Converter
==============
Documentation coming soon...

View File

@ -0,0 +1,126 @@
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* *
******************************************************************************/
#ifndef __ALT_EPCQ_CONTROLLER_H__
#define __ALT_EPCQ_CONTROLLER_H__
#include "alt_types.h"
#include "sys/alt_flash_dev.h"
#include "sys/alt_llist.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/**
* Description of the EPCQ controller
*/
typedef struct alt_epcq_controller_dev
{
alt_flash_dev dev;
alt_u32 data_base; /** base address of data slave */
alt_u32 data_end; /** end address of data slave (not inclusive) */
alt_u32 csr_base; /** base address of CSR slave */
alt_u32 size_in_bytes; /** size of memory in bytes */
alt_u32 is_epcs; /** 1 if device is an EPCS device */
alt_u32 number_of_sectors; /** number of flash sectors */
alt_u32 sector_size; /** size of each flash sector */
alt_u32 page_size; /** page size */
alt_u32 silicon_id; /** ID of silicon used with EPCQ IP */
} alt_epcq_controller_dev;
/**
* Macros used by alt_sys_init.c to create data storage for driver instance
*/
#define ALTERA_EPCQ_CONTROLLER_MOD_AVL_MEM_AVL_CSR_INSTANCE(epcq_name, avl_mem, avl_csr, epcq_dev) \
alt_epcq_controller_dev epcq_dev = \
{ \
.dev = { \
.llist = ALT_LLIST_ENTRY, \
.name = avl_mem##_NAME, \
.write = alt_epcq_controller_write, \
.read = alt_epcq_controller_read, \
.get_info = alt_epcq_controller_get_info, \
.erase_block = alt_epcq_controller_erase_block, \
.write_block = alt_epcq_controller_write_block, \
.base_addr = ((void*)(avl_mem##_BASE)), \
.length = ((int)(avl_mem##_SPAN)), \
.lock = alt_epcq_controller_lock , \
}, \
.data_base = ((alt_u32)(avl_mem##_BASE)), \
.data_end = ((alt_u32)(avl_mem##_BASE) + (alt_u32)(avl_mem##_SPAN)), \
.csr_base = ((alt_u32)(avl_csr##_BASE)), \
.size_in_bytes = ((alt_u32)(avl_mem##_SPAN)), \
.is_epcs = ((alt_u32)(avl_mem##_IS_EPCS)), \
.number_of_sectors = ((alt_u32)(avl_mem##_NUMBER_OF_SECTORS)), \
.sector_size = ((alt_u32)(avl_mem##_SECTOR_SIZE)), \
.page_size = ((alt_u32)(avl_mem##_PAGE_SIZE)) , \
}
/*
Public API
Refer to Using Flash Devices in the
Developing Programs Using the Hardware Abstraction Layer chapter
of the Nios II Software Developer's Handbook.
*/
int alt_epcq_controller_read(alt_flash_dev *flash_info, int offset, void *dest_addr, int length);
int alt_epcq_controller_get_info(alt_flash_fd *fd, flash_region **info, int *number_of_regions);
int alt_epcq_controller_erase_block(alt_flash_dev *flash_info, int block_offset);
int alt_epcq_controller_write_block(alt_flash_dev *flash_info, int block_offset, int data_offset, const void *data, int length);
int alt_epcq_controller_write(alt_flash_dev *flash_info, int offset, const void *src_addr, int length);
int alt_epcq_controller_lock(alt_flash_dev *flash_info, alt_u32 sectors_to_lock);
/*
* Initialization function
*/
extern alt_32 altera_epcq_controller_init(alt_epcq_controller_dev *dev);
/*
* alt_sys_init.c will call this macro automatically initialize the driver instance
*/
#define ALTERA_EPCQ_CONTROLLER_MOD_INIT(name, dev) \
altera_epcq_controller_init(&dev);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __ALT_EPCQ_CONTROLLER_H__ */

View File

@ -0,0 +1,797 @@
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* *
******************************************************************************/
#include <errno.h>
#include <io.h>
#include <string.h>
#include <stddef.h>
#include "sys/param.h"
#include "alt_types.h"
#include "altera_epcq_controller_mod_regs.h"
#include "altera_epcq_controller_mod.h"
#include "priv/alt_busy_sleep.h"
#include "sys/alt_debug.h"
#include "sys/alt_cache.h"
ALT_INLINE alt_32 static alt_epcq_validate_read_write_arguments(alt_epcq_controller_dev *flash_info,alt_u32 offset, alt_u32 length);
alt_32 static alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev* epcq_flash_info);
/*
* Public API
*
* Refer to Using Flash Devices in the
* Developing Programs Using the Hardware Abstraction Layer chapter
* of the Nios II Software Developers Handbook.
*/
/**
* alt_epcq_controller_lock
*
* Locks the range of the memory sectors, which
* protected from write and erase.
*
* Arguments:
* - *flash_info: Pointer to general flash device structure.
* - sectors_to_lock: Block protection bits in EPCQ ==> Bit4 | Bit3 | Bit2 | Bit1 | Bit0
* TB | BP3 | BP2 | BP1 | BP0
* For details of setting sectors protection, please refer to EPCQ datasheet.
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments
* -ETIME -> Time out and skipping the looping after 0.7 sec.
* -ENOLCK -> Sectors lock failed.
**/
int alt_epcq_controller_lock(alt_flash_dev *flash_info, alt_u32 sectors_to_lock)
{
alt_u32 mem_op_value = 0; /* value to write to EPCQ_MEM_OP register */
alt_epcq_controller_dev* epcq_flash_info = NULL;
alt_u32 result = 0;
alt_32 status = 0;
/* return -EINVAL if flash_info is NULL */
if(NULL == flash_info || 0 > sectors_to_lock)
{
return -EINVAL;
}
epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
/* sector value should occupy bits 17:8 */
mem_op_value = sectors_to_lock << 8;
/* sector protect commands 0b11 occupies lower 2 bits */
mem_op_value |= ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_PROTECT_CMD;
/* write sector protect command to EPCQ_MEM_OP register to protect sectors */
IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(epcq_flash_info->csr_base, mem_op_value);
/* poll write in progress to make sure no operation is in progress */
status = alt_epcq_poll_for_write_in_progress(epcq_flash_info);
if(status != 0)
{
return status;
}
status = IORD_ALTERA_EPCQ_CONTROLLER_STATUS(epcq_flash_info->csr_base);
result |= (status >> 2) & 0x07; /* extract out BP3 - BP0 */
result |= (status >> 3) & 0x08; /* extract out BP4 */
result |= (status >> 1) & 0x10; /* extract out TOP/BOTTOM bit */
if(result != sectors_to_lock)
{
return -ENOLCK;
}
return 0;
}
/**
* alt_epcq_controller_get_info
*
* Pass the table of erase blocks to the user. This flash will return a single
* flash_region that gives the number and size of sectors for the device used.
*
* Arguments:
* - *fd: Pointer to general flash device structure.
* - **info: Pointer to flash region
* - *number_of_regions: Pointer to number of regions
*
* For details of setting sectors protection, please refer to EPCQ datasheet.
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments
* -EIO -> Could be hardware problem.
**/
int alt_epcq_controller_get_info
(
alt_flash_fd *fd, /** flash device descriptor */
flash_region **info, /** pointer to flash_region will be stored here */
int *number_of_regions /** number of regions will be stored here */
)
{
alt_flash_dev* flash = NULL;
/* return -EINVAL if fd,info and number_of_regions are NULL */
if(NULL == fd || NULL == info || NULL == number_of_regions)
{
return -EINVAL;
}
flash = (alt_flash_dev*)fd;
*number_of_regions = flash->number_of_regions;
if (!flash->number_of_regions)
{
return -EIO;
}
else
{
*info = &flash->region_info[0];
}
return 0;
}
/**
* alt_epcq_controller_erase_block
*
* This function erases a single flash sector.
*
* Arguments:
* - *flash_info: Pointer to EPCQ flash device structure.
* - block_offset: byte-addressed offset, from start of flash, of the sector to be erased
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments
* -EIO -> write failed, sector might be protected
**/
int alt_epcq_controller_erase_block(alt_flash_dev *flash_info, int block_offset)
{
alt_32 ret_code = 0;
alt_u32 mem_op_value = 0; /* value to write to EPCQ_MEM_OP register */
alt_epcq_controller_dev* epcq_flash_info = NULL;
alt_u32 sector_number = 0;
/* return -EINVAL if flash_info is NULL */
if(NULL == flash_info)
{
return -EINVAL;
}
epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
/*
* Sanity checks that block_offset is within the flash memory span and that the
* block offset is sector aligned.
*
*/
if((block_offset < 0)
|| (block_offset >= epcq_flash_info->size_in_bytes)
|| (block_offset & (epcq_flash_info->sector_size - 1)) != 0)
{
return -EINVAL;
}
/* calculate current sector/block number */
sector_number = (block_offset/(epcq_flash_info->sector_size));
/* sector value should occupy bits 23:8 */
mem_op_value = (sector_number << 8) & ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_VALUE_MASK;
/* sector erase commands 0b10 occupies lower 2 bits */
mem_op_value |= ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_ERASE_CMD;
/* write sector erase command to EPCQ_MEM_OP register to erase sector "sector_number" */
IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(epcq_flash_info->csr_base, mem_op_value);
/* check whether erase triggered a illegal erase interrupt */
if((IORD_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base) &
ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK) ==
ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_ACTIVE)
{
/* clear register */
/* EPCQ_ISR access is write one to clear (W1C) */
IOWR_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base,
ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK );
return -EIO; /* erase failed, sector might be protected */
}
return ret_code;
}
/**
* alt_epcq_controller_write_block
*
* This function writes one block/sector of data to flash. The length of the write can NOT
* spill into the adjacent sector.
*
* It assumes that someone has already erased the appropriate sector(s).
*
* Arguments:
* - *flash_info: Pointer to EPCQ flash device structure.
* - block_offset: byte-addressed offset, from the start of flash, of the sector to written to
* - data-offset: Byte offset (unaligned access) of write into flash memory.
* For best performance, word(32 bits - aligned access) offset of write is recommended.
* - *src_addr: source buffer
* - length: size of writing
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments
* -EIO -> write failed, sector might be protected
**/
int alt_epcq_controller_write_block
(
alt_flash_dev *flash_info, /** flash device info */
int block_offset, /** sector/block offset in byte addressing */
int data_offset, /** offset of write from base address */
const void *data, /** data to be written */
int length /** bytes of data to be written, >0 */
)
{
alt_u32 buffer_offset = 0; /** offset into data buffer to get write data */
alt_u32 remaining_length = length; /** length left to write */
alt_u32 write_offset = data_offset; /** offset into flash to write too */
alt_epcq_controller_dev *epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
/*
* Sanity checks that data offset is not larger then a sector, that block offset is
* sector aligned and within the valid flash memory range and a write doesn't spill into
* the adjacent flash sector.
*/
if(block_offset < 0
|| data_offset < 0
|| NULL == flash_info
|| NULL == data
|| data_offset >= epcq_flash_info->size_in_bytes
|| block_offset >= epcq_flash_info->size_in_bytes
|| length > (epcq_flash_info->sector_size - (data_offset - block_offset))
|| length < 0
|| (block_offset & (epcq_flash_info->sector_size - 1)) != 0)
{
return -EINVAL;
}
/*
* Do writes one 32-bit word at a time.
* We need to make sure that we pad the first few bytes so they're word aligned if they are
* not already.
*/
while (remaining_length > 0)
{
alt_u32 word_to_write = 0xFFFFFFFF; /** initialize word to write to blank word */
alt_u32 padding = 0; /** bytes to pad the next word that is written */
alt_u32 bytes_to_copy = sizeof(alt_u32); /** number of bytes from source to copy */
/*
* we need to make sure the write is word aligned
* this should only be true at most 1 time
*/
if (0 != (write_offset & (sizeof(alt_u32) - 1)))
{
/*
* data is not word aligned
* calculate padding bytes need to add before start of a data offset
*/
padding = write_offset & (sizeof(alt_u32) - 1);
/* update variables to account for padding being added */
bytes_to_copy -= padding;
if(bytes_to_copy > remaining_length)
{
bytes_to_copy = remaining_length;
}
write_offset = write_offset - padding;
if(0 != (write_offset & (sizeof(alt_u32) - 1)))
{
return -EINVAL;
}
}
else
{
if(bytes_to_copy > remaining_length)
{
bytes_to_copy = remaining_length;
}
}
/* prepare the word to be written */
memcpy((((void*)&word_to_write)) + padding, ((void*)data) + buffer_offset, bytes_to_copy);
/* update offset and length variables */
buffer_offset += bytes_to_copy;
remaining_length -= bytes_to_copy;
/* write to flash 32 bits at a time */
IOWR_32DIRECT(epcq_flash_info->data_base, write_offset, word_to_write);
/* check whether write triggered a illegal write interrupt */
if((IORD_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base) &
ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK) ==
ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_ACTIVE)
{
/* clear register */
IOWR_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base,
ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK );
return -EIO; /** write failed, sector might be protected */
}
/* update current offset */
write_offset = write_offset + sizeof(alt_u32);
}
return 0;
}
/**
* alt_epcq_controller_write
*
* Program the data into the flash at the selected address.
*
* The different between this function and alt_epcq_controller_write_block function
* is that this function (alt_epcq_controller_write) will automatically erase a block as needed
* Arguments:
* - *flash_info: Pointer to EPCQ flash device structure.
* - offset: Byte offset (unaligned access) of write to flash memory. For best performance,
* word(32 bits - aligned access) offset of write is recommended.
* - *src_addr: source buffer
* - length: size of writing
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments
* -EIO -> write failed, sector might be protected
*
**/
int alt_epcq_controller_write(
alt_flash_dev *flash_info, /** device info */
int offset, /** offset of write from base address */
const void *src_addr, /** source buffer */
int length /** size of writing */
)
{
alt_32 ret_code = 0;
alt_epcq_controller_dev *epcq_flash_info = NULL;
alt_u32 write_offset = offset; /** address of next byte to write */
alt_u32 remaining_length = length; /** length of write data left to be written */
alt_u32 buffer_offset = 0; /** offset into source buffer to get write data */
alt_u32 i = 0;
/* return -EINVAL if flash_info and src_addr are NULL */
if(NULL == flash_info || NULL == src_addr)
{
return -EINVAL;
}
epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
/* make sure the write parameters are within the bounds of the flash */
ret_code = alt_epcq_validate_read_write_arguments(epcq_flash_info, offset, length);
if(0 != ret_code)
{
return ret_code;
}
/*
* This loop erases and writes data one sector at a time. We check for write completion
* before starting the next sector.
*/
for(i = offset/epcq_flash_info->sector_size ; i < epcq_flash_info->number_of_sectors; i++)
{
alt_u32 block_offset = 0; /** block offset in byte addressing */
alt_u32 offset_within_current_sector = 0; /** offset into current sector to write */
alt_u32 length_to_write = 0; /** length to write to current sector */
if(0 >= remaining_length)
{
break; /* out of data to write */
}
/* calculate current sector/block offset in byte addressing */
block_offset = write_offset & ~(epcq_flash_info->sector_size - 1);
/* calculate offset into sector/block if there is one */
if(block_offset != write_offset)
{
offset_within_current_sector = write_offset - block_offset;
}
/* erase sector */
ret_code = alt_epcq_controller_erase_block(flash_info, block_offset);
if(0 != ret_code)
{
return ret_code;
}
/* calculate the byte size of data to be written in a sector */
length_to_write = MIN(epcq_flash_info->sector_size - offset_within_current_sector,
remaining_length);
/* write data to erased block */
ret_code = alt_epcq_controller_write_block(flash_info, block_offset, write_offset,
src_addr + buffer_offset, length_to_write);
if(0 != ret_code)
{
return ret_code;
}
/* update remaining length and buffer_offset pointer */
remaining_length -= length_to_write;
buffer_offset += length_to_write;
write_offset += length_to_write;
}
return ret_code;
}
/**
* alt_epcq_controller_read
*
* There's no real need to use this function as opposed to using memcpy directly. It does
* do some sanity checks on the bounds of the read.
*
* Arguments:
* - *flash_info: Pointer to general flash device structure.
* - offset: offset read from flash memory.
* - *dest_addr: destination buffer
* - length: size of reading
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments
**/
int alt_epcq_controller_read
(
alt_flash_dev *flash_info, /** device info */
int offset, /** offset of read from base address */
void *dest_addr, /** destination buffer */
int length /** size of read */
)
{
alt_32 ret_code = 0;
alt_epcq_controller_dev *epcq_flash_info = NULL;
/* return -EINVAL if flash_info and dest_addr are NULL */
if(NULL == flash_info || NULL == dest_addr)
{
return -EINVAL;
}
epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
/* validate arguments */
ret_code = alt_epcq_validate_read_write_arguments(epcq_flash_info, offset, length);
/* copy data from flash to destination address */
if(0 == ret_code)
{
memcpy(dest_addr, (alt_u8*)epcq_flash_info->data_base + offset, length);
}
return ret_code;
}
/**
* altera_epcq_controller_init
*
* alt_sys_init.c will call this function automatically through macro
*
* Information in system.h is checked against expected values that are determined by the silicon_id.
* If the information doesn't match then this system is configured incorrectly. Most likely the wrong
* type of EPCS or EPCQ device was selected when instantiating the soft IP.
*
* Arguments:
* - *flash: Pointer to EPCQ flash device structure.
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments.
* -ENODEV -> System is configured incorrectly.
**/
alt_32 altera_epcq_controller_init(alt_epcq_controller_dev *flash)
{
alt_u32 silicon_id = 0;
alt_u32 size_in_bytes = 0;
alt_u32 number_of_sectors = 0;
/* return -EINVAL if flash is NULL */
if(NULL == flash)
{
return -EINVAL;
}
/* return -ENODEV if CSR slave is not attached */
if(NULL == (void *)flash->csr_base)
{
return -ENODEV;
}
/*
* If flash is an EPCQ device, we read the EPCQ_RD_RDID register for the ID
* If flash is an EPCS device, we read the EPCQ_RD_SID register for the ID
*
* Whether or not the flash is a EPCQ or EPCS is indicated in the system.h. The system.h gets
* this value from the hw.tcl of the IP. If this value is set incorrectly, then things will go
* badly.
*
* In both cases, we can determine the number of sectors, which we can use
* to calculate a size. We compare that size to the system.h value to make sure
* the EPCQ soft IP was configured correctly.
*/
if(0 == flash->is_epcs)
{
/* If we're an EPCQ, we read EPCQ_RD_RDID for the silicon ID */
silicon_id = IORD_ALTERA_EPCQ_CONTROLLER_RDID(flash->csr_base);
silicon_id &= ALTERA_EPCQ_CONTROLLER_RDID_MASK;
/* Determine which EPCQ device so we can figure out the number of sectors */
/* EPCQ share the same ID for the same capacity*/
switch(silicon_id)
{
case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ16:
{
number_of_sectors = 32;
break;
}
case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ32:
{
number_of_sectors = 64;
break;
}
case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ64:
{
number_of_sectors = 128;
break;
}
case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ128:
{
number_of_sectors = 256;
break;
}
case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ256:
{
number_of_sectors = 512;
break;
}
case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ512:
{
number_of_sectors = 1024;
break;
}
case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ1024:
{
number_of_sectors = 2048;
break;
}
default:
{
return -ENODEV;
}
}
}
else {
/* If we're an EPCS, we read EPCQ_RD_SID for the silicon ID */
silicon_id = IORD_ALTERA_EPCQ_CONTROLLER_SID(flash->csr_base);
silicon_id &= ALTERA_EPCQ_CONTROLLER_SID_MASK;
/* Determine which EPCS device so we can figure out various properties */
switch(silicon_id)
{
case ALTERA_EPCQ_CONTROLLER_SID_EPCS16:
{
number_of_sectors = 32;
break;
}
case ALTERA_EPCQ_CONTROLLER_SID_EPCS64:
{
number_of_sectors = 128;
break;
}
case ALTERA_EPCQ_CONTROLLER_SID_EPCS128:
{
number_of_sectors = 256;
break;
}
default:
{
return -ENODEV;
}
}
}
/* Calculate size of flash based on number of sectors */
size_in_bytes = number_of_sectors * flash->sector_size;
/*
* Make sure calculated size is the same size given in system.h
* Also check number of sectors is the same number given in system.h
* Otherwise the EPCQ IP was not configured correctly
*/
if( size_in_bytes != flash->size_in_bytes ||
number_of_sectors != flash->number_of_sectors)
{
flash->dev.number_of_regions = 0;
return -ENODEV;
}
else
{
flash->silicon_id = silicon_id;
flash->number_of_sectors = number_of_sectors;
/*
* populate fields of region_info required to conform to HAL API
* create 1 region that composed of "number_of_sectors" blocks
*/
flash->dev.number_of_regions = 1;
flash->dev.region_info[0].offset = 0;
flash->dev.region_info[0].region_size = size_in_bytes;
flash->dev.region_info[0].number_of_blocks = number_of_sectors;
flash->dev.region_info[0].block_size = flash->sector_size;
}
/*
* Register this device as a valid flash device type
*
* Only register the device if it's configured correctly.
*/
alt_flash_device_register(&(flash->dev));
return 0;
}
/*
* Private API
*
* Helper functions used by Public API functions.
*
* Arguments:
* - *flash_info: Pointer to EPCQ flash device structure.
* - offset: Offset of read/write from base address.
* - length: Length of read/write in bytes.
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments
*/
/**
* Used to check that arguments to a read or write are valid
*/
ALT_INLINE alt_32 static alt_epcq_validate_read_write_arguments
(
alt_epcq_controller_dev *flash_info, /** device info */
alt_u32 offset, /** offset of read/write */
alt_u32 length /** length of read/write */
)
{
alt_epcq_controller_dev *epcq_flash_info = NULL;
alt_u32 start_address = 0;
alt_32 end_address = 0;
/* return -EINVAL if flash_info is NULL */
if(NULL == flash_info)
{
return -EINVAL;
}
epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
start_address = epcq_flash_info->data_base + offset; /** first address of read or write */
end_address = start_address + length; /** last address of read or write (not inclusive) */
/* make sure start and end address is less then the end address of the flash */
if(
start_address >= epcq_flash_info->data_end ||
end_address >= epcq_flash_info->data_end ||
offset < 0 ||
length < 0
)
{
return -EINVAL;
}
return 0;
}
/*
* Private function that polls write in progress bit EPCQ_RD_STATUS.
*
* Write in progress will be set if any of the following operations are in progress:
* -WRITE STATUS REGISTER
* -WRITE NONVOLATILE CONFIGURATION REGISTER
* -PROGRAM
* -ERASE
*
* Assumes EPCQ was configured correctly.
*
* If ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE is set, the function will time out after
* a period of time determined by that value.
*
* Arguments:
* - *epcq_flash_info: Pointer to EPCQ flash device structure.
*
* Returns:
* 0 -> success
* -EINVAL -> Invalid arguments
* -ETIME -> Time out and skipping the looping after 0.7 sec.
*/
alt_32 static alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev* epcq_flash_info)
{
/* we'll want to implement timeout if a timeout value is specified */
#if ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE > 0
alt_u32 timeout = ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE;
alt_u16 counter = 0;
#endif
/* return -EINVAL if epcq_flash_info is NULL */
if(NULL == epcq_flash_info)
{
return -EINVAL;
}
/* while Write in Progress bit is set, we wait */
while((IORD_ALTERA_EPCQ_CONTROLLER_STATUS(epcq_flash_info->csr_base) &
ALTERA_EPCQ_CONTROLLER_STATUS_WIP_MASK) ==
ALTERA_EPCQ_CONTROLLER_STATUS_WIP_BUSY)
{
alt_busy_sleep(1); /* delay 1us */
#if ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE > 0
if(timeout <= counter )
{
return -ETIME;
}
counter++;
#endif
}
return 0;
}

View File

@ -0,0 +1,611 @@
// (C) 2001-2015 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
// (C) 2001-2015 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
`timescale 1ps / 1ps
module altera_epcq_controller #(
parameter CS_WIDTH = 1,
parameter ENABLE_4BYTE_ADDR = 1,
parameter ADDR_WIDTH = 22,
parameter ASI_WIDTH = 1,
parameter DEVICE_FAMILY = "CYCLONE V",
parameter ASMI_ADDR_WIDTH = 22,
parameter CHIP_SELS = 1
)(
input wire clk,
input wire reset_n,
// ports to access csr
input wire avl_csr_write,
input wire avl_csr_read,
input wire [2:0] avl_csr_addr,
input wire [31:0] avl_csr_wrdata,
output reg [31:0] avl_csr_rddata,
output reg avl_csr_rddata_valid,
output reg avl_csr_waitrequest,
// ports to access memory
input wire avl_mem_write,
input wire avl_mem_read,
input wire [ADDR_WIDTH-1:0] avl_mem_addr,
input wire [31:0] avl_mem_wrdata,
input wire [3:0] avl_mem_byteenable,
input wire [6:0] avl_mem_burstcount,
output wire [31:0] avl_mem_rddata,
output reg avl_mem_rddata_valid,
output reg avl_mem_waitrequest,
// interrupt signal
output reg irq,
// Disable dedicated active serial interface
input wire [ASI_WIDTH-1:0] epcq_dataout,
output reg epcq_dclk,
output reg [CS_WIDTH-1:0] epcq_scein,
output reg [ASI_WIDTH-1:0] epcq_sdoin,
output reg [ASI_WIDTH-1:0] epcq_dataoe,
// ASMI PARALLEL interface
input wire [ASI_WIDTH-1:0] ddasi_dataoe,
output reg [ASI_WIDTH-1:0] ddasi_dataout,
input wire ddasi_dclk,
input wire [CS_WIDTH-1:0] ddasi_scein,
input reg [ASI_WIDTH-1:0] ddasi_sdoin,
input wire asmi_busy,
input wire asmi_data_valid,
input wire [7:0] asmi_dataout,
output reg asmi_clkin,
output reg asmi_reset,
output reg [CS_WIDTH-1:0] asmi_sce,
output reg [ASMI_ADDR_WIDTH-1:0] asmi_addr,
output reg [7:0] asmi_datain,
output reg asmi_fast_read,
output wire asmi_rden,
output reg asmi_shift_bytes,
output reg asmi_en4b_addr,
output wire asmi_wren,
output reg asmi_write,
input wire asmi_illegal_erase,
input wire asmi_illegal_write,
input wire [7:0] asmi_rdid_out,
input wire [7:0] asmi_status_out,
input wire [7:0] asmi_epcs_id,
output reg asmi_read_rdid,
output reg asmi_read_status,
output reg asmi_read_sid,
output reg asmi_bulk_erase,
output reg asmi_sector_erase,
output reg asmi_sector_protect
);
localparam LOCAL_ADDR_WIDTH = ADDR_WIDTH+2;
localparam CSR_DATA_WIDTH = 32;
localparam LAST_ADDR_BIT = (ASMI_ADDR_WIDTH == 24) ? 15 :
(ASMI_ADDR_WIDTH == 32) ? 23 : 15;
reg [8:0] wr_burstcount_cnt, rd_burstcount_cnt;
reg [8:0] rd_mem_burstcount, wr_mem_burstcount;
wire last_wr_byte;
wire access_csr_status, access_csr_sid, access_csr_rdid, access_csr_mem_op, access_isr, access_imr, access_sce;
wire read_status_combi, read_sid_combi, read_rdid_combi, read_isr_combi, read_imr_combi, write_isr_combi, write_imr_combi, write_sce_combi;
wire bulk_erase_combi, sector_erase_combi, sector_protect_combi;
wire wren_combi, illegal_write_combi, illegal_erase_combi;
wire m_illegal_write_combi, m_illegal_erase_combi;
wire read_mem_combi, write_mem_combi;
wire data_valid_combi, pending_wr_data;
wire detect_addroffset;
wire [8:0] wfifo_data_in_0, wfifo_data_in_1, wfifo_data_in_2, wfifo_data_in_3;
wire [ADDR_WIDTH-1:0] temp_mem_addr;
reg reset_n_reg;
reg wr_mem_waitrequest, local_waitrequest;
reg illegal_write_reg, illegal_erase_reg, m_illegal_write_reg, m_illegal_erase_reg;
reg read_status_valid, read_sid_valid, read_rdid_valid, read_isr_valid, read_imr_valid;
reg read_status_en, read_sid_en, read_rdid_en;
reg wren_internal;
reg [LOCAL_ADDR_WIDTH-1:0] wr_mem_addr;
reg [7:0] rd_data_reg [4];
reg [3:0][8:0] wr_data_reg;
reg [1:0] rd_cnt;
reg [1:0] wr_cnt;
reg [3:0] wr_data_reg_full;
reg detect_addroffset_reg, asmi_busy_reg;
reg [2:0] temp_sce;
// Direct connection
assign asmi_clkin = clk;
assign asmi_reset = ~reset_n;
assign ddasi_dataout = epcq_dataout;
assign epcq_dclk = ddasi_dclk;
assign epcq_scein = ddasi_scein;
assign epcq_sdoin = ddasi_sdoin;
assign epcq_dataoe = ddasi_dataoe;
// chip select
generate if (DEVICE_FAMILY == "Arria 10") begin
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
asmi_sce <= {CS_WIDTH{1'b0}};
end
// to pack the address space this is needed
else if (write_mem_combi || read_mem_combi) begin
if (CHIP_SELS == 1 )
asmi_sce <= 3'b001;
else if (CHIP_SELS == 2 && avl_mem_addr[ADDR_WIDTH-1] == 0)
asmi_sce <= 3'b001;
else if (CHIP_SELS == 2 && avl_mem_addr[ADDR_WIDTH-1] == 1)
asmi_sce <= 3'b010;
else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1] == 1)
asmi_sce <= 3'b100;
else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1:ADDR_WIDTH-2] == 0)
asmi_sce <= 3'b001;
else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1:ADDR_WIDTH-2] == 1)
asmi_sce <= 3'b010;
else
asmi_sce <= {CS_WIDTH{1'b0}};
end
else if (write_sce_combi) begin
asmi_sce <= avl_csr_wrdata[2:0];
end
else if (asmi_en4b_addr) begin
asmi_sce <= temp_sce;
end
end
// decoder ring if the CHIP_SEL is only 1 then avalon address is the temp address
// if the chipsele is 2 then need to remove top address bit
// if the chipelect is 3 then remove the top 2 address bits.
assign temp_mem_addr = CHIP_SELS == 1 ? avl_mem_addr:( CHIP_SELS == 2 ? {1'b0,avl_mem_addr[ADDR_WIDTH-2:0]}:{2'b00,avl_mem_addr[ADDR_WIDTH-3:0]});
end
else begin
always @(posedge clk) begin
asmi_sce <= {CS_WIDTH{1'b0}};
end
assign temp_mem_addr = avl_mem_addr;
end
endgenerate
// wait_request generation logic
assign avl_mem_waitrequest = (asmi_busy || asmi_busy_reg) ? 1'b1 : (local_waitrequest || wr_mem_waitrequest);
assign avl_csr_waitrequest = (asmi_busy || asmi_busy_reg) ? 1'b1 : (local_waitrequest || wr_mem_waitrequest);
// access CSR decoding logic
assign access_csr_status = (avl_csr_addr == 3'b000);
assign access_csr_sid = (avl_csr_addr == 3'b001);
assign access_csr_rdid = (avl_csr_addr == 3'b010);
assign access_csr_mem_op = (avl_csr_addr == 3'b011);
assign access_isr = (avl_csr_addr == 3'b100);
assign access_imr = (avl_csr_addr == 3'b101);
assign access_sce = (avl_csr_addr == 3'b110);
// read/write memory combi logic
assign read_mem_combi = (avl_mem_read && ~avl_mem_waitrequest);
assign write_mem_combi = (avl_mem_write && ~avl_mem_waitrequest);
// read csr logic
assign read_status_combi = (avl_csr_read && access_csr_status && ~avl_csr_waitrequest);
assign read_sid_combi = (avl_csr_read && access_csr_sid && ~avl_csr_waitrequest);
assign read_rdid_combi = (avl_csr_read && access_csr_rdid && ~avl_csr_waitrequest);
assign read_isr_combi = (avl_csr_read && access_isr && ~avl_csr_waitrequest);
assign read_imr_combi = (avl_csr_read && access_imr && ~avl_csr_waitrequest);
assign write_isr_combi = (avl_csr_write && access_isr && ~avl_csr_waitrequest);
assign write_imr_combi = (avl_csr_write && access_imr && ~avl_csr_waitrequest);
assign write_sce_combi = (avl_csr_write && access_sce && ~avl_csr_waitrequest);
// write csr logic
assign bulk_erase_combi = (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b01);
assign sector_erase_combi = (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b10);
assign sector_protect_combi = (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b11);
assign illegal_write_combi = (asmi_illegal_write) ? 1'b1 :
(write_isr_combi && avl_csr_wrdata[1]) ? 1'b0 :
illegal_write_reg;
assign illegal_erase_combi = (asmi_illegal_erase) ? 1'b1 :
(write_isr_combi && avl_csr_wrdata[0]) ? 1'b0 :
illegal_erase_reg;
assign m_illegal_write_combi= (write_imr_combi) ? avl_csr_wrdata[1] : m_illegal_write_reg;
assign m_illegal_erase_combi= (write_imr_combi) ? avl_csr_wrdata[0] : m_illegal_erase_reg;
assign wren_combi = (sector_protect_combi || sector_erase_combi || bulk_erase_combi);
assign asmi_rden = (rd_burstcount_cnt > 9'd0); // deasserted at the last 2 byte - refer to ASMI_PARALLEL UG
// interrupt signal
assign irq = (illegal_write_reg && m_illegal_write_reg) || (illegal_erase_reg && m_illegal_erase_reg);
assign last_wr_byte = (wr_burstcount_cnt == wr_mem_burstcount - 9'd1) ? 1'b1 : 1'b0;
assign asmi_wren = wren_internal || asmi_en4b_addr || asmi_shift_bytes || asmi_write;
assign data_valid_combi = (rd_burstcount_cnt[1:0] == 2'b00) ? asmi_data_valid : 1'b0;
assign wfifo_data_in_0 = {avl_mem_byteenable[0], avl_mem_wrdata[7:0] };
assign wfifo_data_in_1 = {avl_mem_byteenable[1], avl_mem_wrdata[15:8] };
assign wfifo_data_in_2 = {avl_mem_byteenable[2], avl_mem_wrdata[23:16] };
assign wfifo_data_in_3 = {avl_mem_byteenable[3], avl_mem_wrdata[31:24] };
assign avl_mem_rddata = {rd_data_reg[3], rd_data_reg[2], rd_data_reg[1], rd_data_reg[0]};
assign pending_wr_data = (|wr_data_reg_full) ? 1'b1 : 1'b0;
assign detect_addroffset = (pending_wr_data && wr_data_reg[wr_cnt][8]) ? 1'b1 :
(wr_burstcount_cnt == {9{1'b0}}) ? 1'b0 : detect_addroffset_reg;
//-------------------------------- array to store write data -------------------------------------
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
wr_data_reg <= '{{9{1'b0}}, {9{1'b0}}, {9{1'b0}}, {9{1'b0}}};
wr_data_reg_full <= {4{1'b0}};
end
else if (write_mem_combi) begin
wr_data_reg <= {wfifo_data_in_3, wfifo_data_in_2, wfifo_data_in_1, wfifo_data_in_0};
wr_data_reg_full <= {4{1'b1}};
end
else if (wr_data_reg_full > 4'b0000) begin
wr_data_reg_full <= wr_data_reg_full << 1;
end
end
//-------------------------------- array to store read data -------------------------------------
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
rd_data_reg <= '{{8{1'b0}}, {8{1'b0}}, {8{1'b0}}, {8{1'b0}}};
rd_cnt <= {2{1'b0}};
end
else if (asmi_data_valid) begin
rd_data_reg[rd_cnt] <= asmi_dataout;
rd_cnt <= rd_cnt + 2'b01;
end
end
//------------------------------- Enable 4-byte addressing out of reset ----------------------
generate
if (ENABLE_4BYTE_ADDR) begin
typedef enum logic[1:0] {EN4B_CHIP1, EN4B_CHIP2, EN4B_CHIP3, IDLE} state_t;
state_t state;
always @(posedge clk or negedge reset_n_reg) begin // use reset_n_reg because user is allow to send cmd to ASMI_PARALLEL 2 clock cycles after reset
if (~reset_n_reg) begin
state <= EN4B_CHIP1;
asmi_en4b_addr <= 1'b1;
temp_sce <= 3'b001;
end
else begin
case (state)
EN4B_CHIP1 : begin
asmi_en4b_addr <= 1'b1;
if (~asmi_busy) begin
if (CHIP_SELS > 1) begin
state <= EN4B_CHIP2;
temp_sce <= 3'b010;
end
else begin
state <= IDLE;
temp_sce <= 3'b000;
end
end
end
EN4B_CHIP2 : begin
asmi_en4b_addr <= 1'b1;
if (~asmi_busy) begin
if (CHIP_SELS > 2) begin
state <= EN4B_CHIP3;
temp_sce <= 3'b100;
end
else begin
state <= IDLE;
temp_sce <= 3'b000;
end
end
end
EN4B_CHIP3 : begin
asmi_en4b_addr <= 1'b1;
if (~asmi_busy) begin
state <= IDLE;
temp_sce <= 3'b000;
end
end
IDLE : begin
asmi_en4b_addr <= 1'b0;
state <= IDLE;
temp_sce <= 3'b000;
end
default : begin
asmi_en4b_addr <= 1'b0;
state <= IDLE;
temp_sce <= 3'b000;
end
endcase
end
end
end
else begin
always @(posedge clk) begin
asmi_en4b_addr <= 1'b0;
temp_sce <= 3'b000;
end
end
endgenerate
//--------------------------------------- Waitrequest logic ----------------------------------
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
wr_mem_waitrequest <= 1'b0;
local_waitrequest <= 1'b0;
end
else begin
if (read_mem_combi || read_status_combi || read_sid_combi || read_rdid_combi || bulk_erase_combi || sector_erase_combi || sector_protect_combi || asmi_en4b_addr) begin // no back pressure during imr & isr access
local_waitrequest <= 1'b1;
end
else if (asmi_busy_reg && ~asmi_busy) begin
local_waitrequest <= 1'b0;
end
if (write_mem_combi) begin
wr_mem_waitrequest <= 1'b1;
end
else if ((~pending_wr_data && ~asmi_write) || asmi_busy_reg && ~asmi_busy) begin
wr_mem_waitrequest <= 1'b0;
end
end
end
// -------------------------------------- MEM ACCESS -----------------------------------------
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
rd_mem_burstcount <= {9{1'b0}};
wr_mem_burstcount <= {9{1'b0}};
wr_mem_addr <= {LOCAL_ADDR_WIDTH{1'b0}};
end
else begin
if (read_mem_combi) begin
rd_mem_burstcount <= {avl_mem_burstcount, 2'b00};
end
if (write_mem_combi && (wr_burstcount_cnt == {9{1'b0}})) begin
wr_mem_addr <= {temp_mem_addr, 2'b00};
wr_mem_burstcount <= {avl_mem_burstcount, 2'b00};
end
end
end
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
wr_burstcount_cnt <= {9{1'b0}};
end
else begin
if (pending_wr_data) begin
wr_burstcount_cnt <= wr_burstcount_cnt + 9'd1;
end
else if (wr_burstcount_cnt == wr_mem_burstcount) begin
wr_burstcount_cnt <= {9{1'b0}};
end
end
end
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
rd_burstcount_cnt <= {9{1'b0}};
end
else begin
if (read_mem_combi) begin
rd_burstcount_cnt <= 9'd1;
end
else if (rd_burstcount_cnt == rd_mem_burstcount) begin // each rd 4 burst
rd_burstcount_cnt <= {9{1'b0}};
end
else if (asmi_data_valid && rd_burstcount_cnt > 0) begin
rd_burstcount_cnt <= rd_burstcount_cnt + 9'd1;
end
end
end
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
asmi_addr <= {ASMI_ADDR_WIDTH{1'b0}};
end
else begin
if (sector_erase_combi) begin // set lower 16 bits to zero so that erase at starting address of each sector
asmi_addr <= {avl_csr_wrdata[LAST_ADDR_BIT : 8], {16{1'b0}}};
end
if (read_mem_combi) begin
asmi_addr <= {temp_mem_addr, 2'b00};
end
if (detect_addroffset && ~detect_addroffset_reg) begin
asmi_addr <= wr_mem_addr + {{LOCAL_ADDR_WIDTH-9{1'b0}}, wr_burstcount_cnt};
end
end
end
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
asmi_datain <= {8{1'b0}};
wr_cnt <= {2{1'b0}};
asmi_shift_bytes <= 1'b0;
end
else begin
if (sector_protect_combi) begin
asmi_datain <= {{1{1'b0}}, avl_csr_wrdata[11], avl_csr_wrdata[12], avl_csr_wrdata[10:8], {2{1'b0}}}; // BP3, TB, BP2, BP1, BP0
end
if (pending_wr_data) begin
asmi_datain <= wr_data_reg[wr_cnt][7:0];
wr_cnt <= wr_cnt + 2'd1;
end
if (pending_wr_data && wr_data_reg[wr_cnt][8]) begin
asmi_shift_bytes <= 1'b1;
end
else begin
asmi_shift_bytes <= 1'b0;
end
end
end
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
asmi_read_status <= 1'b0;
asmi_read_sid <= 1'b0;
asmi_read_rdid <= 1'b0;
asmi_bulk_erase <= 1'b0;
asmi_sector_erase <= 1'b0;
asmi_sector_protect <= 1'b0;
wren_internal <= 1'b0;
asmi_write <= 1'b0;
asmi_fast_read <= 1'b0;
asmi_busy_reg <= 1'b0;
avl_mem_rddata_valid <= 1'b0;
detect_addroffset_reg <= 1'b0;
reset_n_reg <= 1'b0;
end
else begin
asmi_read_status <= read_status_combi;
asmi_read_sid <= read_sid_combi;
asmi_read_rdid <= read_rdid_combi;
asmi_bulk_erase <= bulk_erase_combi;
asmi_sector_erase <= sector_erase_combi;
asmi_sector_protect <= sector_protect_combi;
wren_internal <= wren_combi;
asmi_write <= last_wr_byte;
asmi_fast_read <= read_mem_combi;
asmi_busy_reg <= asmi_busy;
avl_mem_rddata_valid <= data_valid_combi;
detect_addroffset_reg <= detect_addroffset;
reset_n_reg <= 1'b1;
end
end
// --------------------------------------------- CSR ACCESS -------------------------------------
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
illegal_write_reg <= 1'b0;
illegal_erase_reg <= 1'b0;
m_illegal_write_reg <= 1'b0;
m_illegal_erase_reg <= 1'b0;
end
else begin
illegal_write_reg <= illegal_write_combi;
illegal_erase_reg <= illegal_erase_combi;
m_illegal_write_reg <= m_illegal_write_combi;
m_illegal_erase_reg <= m_illegal_erase_combi;
end
end
// csr read only registers enable logic
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
read_status_en <= 1'b0;
read_sid_en <= 1'b0;
read_rdid_en <= 1'b0;
end
else if (asmi_read_status) begin
read_status_en <= 1'b1;
end
else if (asmi_read_sid) begin
read_sid_en <= 1'b1;
end
else if (asmi_read_rdid) begin
read_rdid_en <= 1'b1;
end
else if (asmi_busy == 0) begin
read_status_en <= 1'b0;
read_sid_en <= 1'b0;
read_rdid_en <= 1'b0;
end
end
// generation logic for avl csr read data valid
assign avl_csr_rddata_valid = read_status_valid || read_sid_valid || read_rdid_valid || read_isr_valid || read_imr_valid;
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
read_status_valid <= 1'b0;
read_sid_valid <= 1'b0;
read_rdid_valid <= 1'b0;
read_isr_valid <= 1'b0;
read_imr_valid <= 1'b0;
end
else begin
if (read_status_en && asmi_busy == 0) begin
read_status_valid <= 1'b1;
end
else begin
read_status_valid <= 1'b0;
end
if (read_sid_en && asmi_busy == 0) begin
read_sid_valid <= 1'b1;
end
else begin
read_sid_valid <= 1'b0;
end
if (read_rdid_en && asmi_busy == 0) begin
read_rdid_valid <= 1'b1;
end
else begin
read_rdid_valid <= 1'b0;
end
if (read_isr_combi) begin
read_isr_valid <= 1'b1;
end
else begin
read_isr_valid <= 1'b0;
end
if (read_imr_combi) begin
read_imr_valid <= 1'b1;
end
else begin
read_imr_valid <= 1'b0;
end
end
end
// generation logic for avl csr read data
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
avl_csr_rddata <= {CSR_DATA_WIDTH{1'b0}};
end
else begin
if (read_status_en && asmi_busy == 0) begin
avl_csr_rddata <= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_status_out};
end
if (read_sid_en && asmi_busy == 0) begin
avl_csr_rddata <= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_epcs_id};
end
if (read_rdid_en && asmi_busy == 0) begin
avl_csr_rddata <= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_rdid_out};
end
if (read_isr_combi) begin
avl_csr_rddata <= {{CSR_DATA_WIDTH-2{1'b0}}, illegal_write_reg, illegal_erase_reg};
end
if (read_imr_combi) begin
avl_csr_rddata <= {{CSR_DATA_WIDTH-2{1'b0}}, m_illegal_write_reg, m_illegal_erase_reg};
end
end
end
endmodule

View File

@ -0,0 +1,230 @@
// (C) 2001-2015 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
// (C) 2001-2014 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
`timescale 1ps / 1ps
module altera_epcq_controller_arb #(
parameter CS_WIDTH = 1,
parameter ENABLE_4BYTE_ADDR = 1,
parameter ADDR_WIDTH = 22,
parameter ASI_WIDTH = 1,
parameter DEVICE_FAMILY = "CYCLONE V",
parameter ASMI_ADDR_WIDTH = 22,
parameter CHIP_SELS = 1
)(
input wire clk,
input wire reset_n,
// ports to access csr
input wire avl_csr_write,
input wire avl_csr_read,
input wire [2:0] avl_csr_addr,
input wire [31:0] avl_csr_wrdata,
output reg [31:0] avl_csr_rddata,
output reg avl_csr_rddata_valid,
output reg avl_csr_waitrequest,
// ports to access memory
input wire avl_mem_write,
input wire avl_mem_read,
input wire [ADDR_WIDTH-1:0] avl_mem_addr,
input wire [31:0] avl_mem_wrdata,
input wire [3:0] avl_mem_byteenable,
input wire [6:0] avl_mem_burstcount,
output wire [31:0] avl_mem_rddata,
output reg avl_mem_rddata_valid,
output reg avl_mem_waitrequest,
// interrupt signal
output reg irq,
// Disable dedicated active serial interface
input wire [ASI_WIDTH-1:0] epcq_dataout,
output reg epcq_dclk,
output reg [CS_WIDTH-1:0] epcq_scein,
output reg [ASI_WIDTH-1:0] epcq_sdoin,
output reg [ASI_WIDTH-1:0] epcq_dataoe,
// ASMI PARALLEL interface
input wire [ASI_WIDTH-1:0] ddasi_dataoe,
output reg [ASI_WIDTH-1:0] ddasi_dataout,
input wire ddasi_dclk,
input wire [CS_WIDTH-1:0] ddasi_scein,
input reg [ASI_WIDTH-1:0] ddasi_sdoin,
input wire asmi_busy,
input wire asmi_data_valid,
input wire [7:0] asmi_dataout,
output reg asmi_clkin,
output reg asmi_reset,
output reg [CS_WIDTH-1:0] asmi_sce,
output reg [ASMI_ADDR_WIDTH-1:0] asmi_addr,
output reg [7:0] asmi_datain,
output reg asmi_fast_read,
output wire asmi_rden,
output reg asmi_shift_bytes,
output reg asmi_en4b_addr,
output wire asmi_wren,
output reg asmi_write,
input wire asmi_illegal_erase,
input wire asmi_illegal_write,
input wire [7:0] asmi_rdid_out,
input wire [7:0] asmi_status_out,
input wire [7:0] asmi_epcs_id,
output reg asmi_read_rdid,
output reg asmi_read_status,
output reg asmi_read_sid,
output reg asmi_bulk_erase,
output reg asmi_sector_erase,
output reg asmi_sector_protect
);
reg temp_mem_write, temp_mem_read, mem_write, mem_read, back_pressured_ctrl;
reg [ADDR_WIDTH-1:0] temp_mem_addr, mem_addr;
reg [31:0] temp_mem_wrdata, mem_wrdata;
reg [3:0] temp_mem_byteenable, mem_byteenable;
reg [6:0] temp_mem_burstcount, mem_burstcount;
wire back_pressured, temp_csr_waitrequest, temp_mem_waitrequest;
//-------------------- Arbitration logic between avalon csr and mem interface -----------
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
back_pressured_ctrl <= 1'b0;
end
else if (back_pressured) begin
back_pressured_ctrl <= 1'b1;
end
else if (~temp_csr_waitrequest) begin
back_pressured_ctrl <= 1'b0;
end
end
always @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
mem_write <= 1'b0;
mem_read <= 1'b0;
mem_addr <= {ADDR_WIDTH{1'b0}};
mem_wrdata <= {32{1'b0}};
mem_byteenable <= {4{1'b0}};
mem_burstcount <= {7{1'b0}};
end
else if ((avl_csr_write || avl_csr_read) && ~avl_csr_waitrequest && (avl_mem_write || avl_mem_read) && ~avl_mem_waitrequest) begin
// to back pressure master
mem_write <= avl_mem_write;
mem_read <= avl_mem_read;
mem_addr <= avl_mem_addr;
mem_wrdata <= avl_mem_wrdata;
mem_byteenable <= avl_mem_byteenable;
mem_burstcount <= avl_mem_burstcount;
end
end
assign back_pressured = ((avl_csr_write || avl_csr_read) && ~temp_csr_waitrequest && (avl_mem_write || avl_mem_read)) ? 1'b1 : 1'b0; // to back pressure controller
assign avl_csr_waitrequest = (~avl_csr_write && ~avl_csr_read && back_pressured_ctrl) ? 1'b1 : temp_csr_waitrequest;
assign avl_mem_waitrequest = (back_pressured_ctrl) ? 1'b1 : temp_mem_waitrequest;
assign temp_mem_write = (back_pressured) ? 1'b0 :
(back_pressured_ctrl) ? mem_write : avl_mem_write;
assign temp_mem_read = (back_pressured) ? 1'b0 :
(back_pressured_ctrl) ? mem_read : avl_mem_read;
assign temp_mem_addr = (back_pressured) ? {ADDR_WIDTH{1'b0}} :
(back_pressured_ctrl) ? mem_addr : avl_mem_addr;
assign temp_mem_wrdata = (back_pressured) ? {32{1'b0}} :
(back_pressured_ctrl) ? mem_wrdata : avl_mem_wrdata;
assign temp_mem_byteenable = (back_pressured) ? {4{1'b0}} :
(back_pressured_ctrl) ? mem_byteenable : avl_mem_byteenable;
assign temp_mem_burstcount = (back_pressured) ? {7{1'b0}} :
(back_pressured_ctrl) ? mem_burstcount : avl_mem_burstcount;
//---------------------------------------------------------------------------------------//
altera_epcq_controller #(
.CS_WIDTH (CS_WIDTH),
.DEVICE_FAMILY (DEVICE_FAMILY),
.ADDR_WIDTH (ADDR_WIDTH),
.ASMI_ADDR_WIDTH (ASMI_ADDR_WIDTH),
.ASI_WIDTH (ASI_WIDTH),
.CHIP_SELS (CHIP_SELS),
.ENABLE_4BYTE_ADDR (ENABLE_4BYTE_ADDR)
) controller (
.clk (clk),
.reset_n (reset_n),
.avl_csr_read (avl_csr_read),
.avl_csr_waitrequest (temp_csr_waitrequest),
.avl_csr_write (avl_csr_write),
.avl_csr_addr (avl_csr_addr),
.avl_csr_wrdata (avl_csr_wrdata),
.avl_csr_rddata (avl_csr_rddata),
.avl_csr_rddata_valid (avl_csr_rddata_valid),
.avl_mem_write (temp_mem_write),
.avl_mem_burstcount (temp_mem_burstcount),
.avl_mem_waitrequest (temp_mem_waitrequest),
.avl_mem_read (temp_mem_read),
.avl_mem_addr (temp_mem_addr),
.avl_mem_wrdata (temp_mem_wrdata),
.avl_mem_byteenable (temp_mem_byteenable),
.avl_mem_rddata (avl_mem_rddata),
.avl_mem_rddata_valid (avl_mem_rddata_valid),
.asmi_status_out (asmi_status_out),
.asmi_epcs_id (asmi_epcs_id),
.asmi_illegal_erase (asmi_illegal_erase),
.asmi_illegal_write (asmi_illegal_write),
.ddasi_dataoe (ddasi_dataoe),
.ddasi_dclk (ddasi_dclk),
.ddasi_scein (ddasi_scein),
.ddasi_sdoin (ddasi_sdoin),
.asmi_busy (asmi_busy),
.asmi_data_valid (asmi_data_valid),
.asmi_dataout (asmi_dataout),
.epcq_dataout (epcq_dataout),
.ddasi_dataout (ddasi_dataout),
.asmi_read_rdid (asmi_read_rdid),
.asmi_read_status (asmi_read_status),
.asmi_read_sid (asmi_read_sid),
.asmi_bulk_erase (asmi_bulk_erase),
.asmi_sector_erase (asmi_sector_erase),
.asmi_sector_protect (asmi_sector_protect),
.epcq_dclk (epcq_dclk),
.epcq_scein (epcq_scein),
.epcq_sdoin (epcq_sdoin),
.epcq_dataoe (epcq_dataoe),
.asmi_clkin (asmi_clkin),
.asmi_reset (asmi_reset),
.asmi_sce (asmi_sce),
.asmi_addr (asmi_addr),
.asmi_datain (asmi_datain),
.asmi_fast_read (asmi_fast_read),
.asmi_rden (asmi_rden),
.asmi_shift_bytes (asmi_shift_bytes),
.asmi_wren (asmi_wren),
.asmi_write (asmi_write),
.asmi_rdid_out (asmi_rdid_out),
.asmi_en4b_addr (asmi_en4b_addr),
.irq (irq)
);
endmodule

View File

@ -0,0 +1,176 @@
// (C) 2001-2015 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
// megafunction wizard: %FIFO%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: scfifo
// ============================================================
// File Name: altera_epcq_controller_fifo.v
// Megafunction Name(s):
// scfifo
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 14.1.0 Internal Build 64 05/14/2014 PN Full Version
// ************************************************************
//Copyright (C) 1991-2014 Altera Corporation. All rights reserved.
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, the Altera Quartus II License Agreement,
//the Altera MegaCore Function License Agreement, or other
//applicable license agreement, including, without limitation,
//that your use is for the sole purpose of programming logic
//devices manufactured by Altera and sold by Altera or its
//authorized distributors. Please refer to the applicable
//agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module altera_epcq_controller_fifo #(
parameter DEVICE_FAMILY = "CYCLONE V",
parameter MEMORY_TYPE = "RAM_BLOCK_TYPE=MLAB"
)(
clock,
data,
rdreq,
wrreq,
empty,
full,
q);
input clock;
input [35:0] data;
input rdreq;
input wrreq;
output empty;
output full;
output [35:0] q;
wire sub_wire0;
wire sub_wire1;
wire [35:0] sub_wire2;
wire empty = sub_wire0;
wire full = sub_wire1;
wire [35:0] q = sub_wire2[35:0];
scfifo scfifo_component (
.clock (clock),
.data (data),
.rdreq (rdreq),
.wrreq (wrreq),
.empty (sub_wire0),
.full (sub_wire1),
.q (sub_wire2),
.aclr (),
.almost_empty (),
.almost_full (),
.sclr (),
.usedw ());
defparam
scfifo_component.add_ram_output_register = "OFF",
scfifo_component.intended_device_family = DEVICE_FAMILY,
scfifo_component.lpm_hint = MEMORY_TYPE,
scfifo_component.lpm_numwords = 1024,
scfifo_component.lpm_showahead = "ON",
scfifo_component.lpm_type = "scfifo",
scfifo_component.lpm_width = 36,
scfifo_component.lpm_widthu = 10,
scfifo_component.overflow_checking = "ON",
scfifo_component.underflow_checking = "ON",
scfifo_component.use_eab = "ON";
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
// Retrieval info: PRIVATE: Clock NUMERIC "0"
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
// Retrieval info: PRIVATE: Empty NUMERIC "1"
// Retrieval info: PRIVATE: Full NUMERIC "1"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV GX"
// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
// Retrieval info: PRIVATE: Optimize NUMERIC "0"
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
// Retrieval info: PRIVATE: UsedW NUMERIC "0"
// Retrieval info: PRIVATE: Width NUMERIC "8"
// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
// Retrieval info: PRIVATE: output_width NUMERIC "8"
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV GX"
// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M9K"
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10"
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full"
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
// Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@ -0,0 +1,453 @@
# (C) 2001-2015 Altera Corporation. All rights reserved.
# Your use of Altera Corporation's design tools, logic functions and other
# software and tools, and its AMPP partner logic functions, and any output
# files any of the foregoing (including device programming or simulation
# files), and any associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License Subscription
# Agreement, Altera MegaCore Function License Agreement, or other applicable
# license agreement, including, without limitation, that your use is for the
# sole purpose of programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the applicable
# agreement for further details.
# TCL File Generated by Component Editor 14.1
# Fri May 09 18:08:10 MYT 2014
# DO NOT MODIFY
#
# altera_epcq_controller_core "Altera EPCQ Serial Flash controller core" v14.1
# Altera Coorperation 2014.05.23.15:01:29
# This component is a serial flash controller which allows user to access Altera EPCQ devices
#
#
# request TCL package from ACDS 14.1
#
package require -exact qsys 14.1
#
# module altera_epcq_controller
#
set_module_property DESCRIPTION "This component is a serial flash controller which allows user to access Altera EPCQ devices"
set_module_property NAME altera_epcq_controller_core
set_module_property VERSION 15.1
set_module_property INTERNAL true
set_module_property OPAQUE_ADDRESS_MAP true
set_module_property AUTHOR "Altera Corporation"
set_module_property DISPLAY_NAME "Altera EPCQ Serial Flash controller core"
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property HIDE_FROM_QUARTUS true
set_module_property EDITABLE true
set_module_property REPORT_TO_TALKBACK false
set_module_property ALLOW_GREYBOX_GENERATION false
set_module_property REPORT_HIERARCHY false
set_module_property VALIDATION_CALLBACK "validate"
#
# file sets
#
add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" ""
set_fileset_property QUARTUS_SYNTH TOP_LEVEL altera_epcq_controller_arb
set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false
add_fileset_file altera_epcq_controller_arb.sv SYSTEM_VERILOG PATH altera_epcq_controller_arb.sv TOP_LEVEL_FILE
add_fileset_file altera_epcq_controller.sv SYSTEM_VERILOG PATH altera_epcq_controller.sv
add_fileset SIM_VERILOG SIM_VERILOG "" ""
set_fileset_property SIM_VERILOG TOP_LEVEL altera_epcq_controller_arb
set_fileset_property SIM_VERILOG ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property SIM_VERILOG ENABLE_FILE_OVERWRITE_MODE true
add_fileset_file altera_epcq_controller_arb.sv SYSTEM_VERILOG PATH altera_epcq_controller_arb.sv TOP_LEVEL_FILE
add_fileset_file altera_epcq_controller.sv SYSTEM_VERILOG PATH altera_epcq_controller.sv
#
# add system info parameter
add_parameter deviceFeaturesSystemInfo STRING "None"
set_parameter_property deviceFeaturesSystemInfo system_info "DEVICE_FEATURES"
set_parameter_property deviceFeaturesSystemInfo VISIBLE false
#
# parameters
#
add_parameter DEVICE_FAMILY STRING ""
set_parameter_property DEVICE_FAMILY SYSTEM_INFO "DEVICE_FAMILY"
set_parameter_property DEVICE_FAMILY HDL_PARAMETER true
set_parameter_property DEVICE_FAMILY VISIBLE false
add_parameter ADDR_WIDTH INTEGER 19
set_parameter_property ADDR_WIDTH DEFAULT_VALUE 19
set_parameter_property ADDR_WIDTH DISPLAY_NAME ADDR_WIDTH
set_parameter_property ADDR_WIDTH DERIVED true
set_parameter_property ADDR_WIDTH TYPE INTEGER
set_parameter_property ADDR_WIDTH VISIBLE false
set_parameter_property ADDR_WIDTH UNITS None
set_parameter_property ADDR_WIDTH ALLOWED_RANGES {19, 20, 21, 22, 23, 24, 25, 26, 27, 28}
set_parameter_property ADDR_WIDTH HDL_PARAMETER true
add_parameter ASMI_ADDR_WIDTH INTEGER 24
set_parameter_property ASMI_ADDR_WIDTH DEFAULT_VALUE 24
set_parameter_property ASMI_ADDR_WIDTH DISPLAY_NAME ASMI_ADDR_WIDTH
set_parameter_property ASMI_ADDR_WIDTH DERIVED true
set_parameter_property ASMI_ADDR_WIDTH TYPE INTEGER
set_parameter_property ASMI_ADDR_WIDTH VISIBLE false
set_parameter_property ASMI_ADDR_WIDTH UNITS None
set_parameter_property ASMI_ADDR_WIDTH ALLOWED_RANGES {24, 32}
set_parameter_property ASMI_ADDR_WIDTH HDL_PARAMETER true
add_parameter ASI_WIDTH INTEGER 1
set_parameter_property ASI_WIDTH DEFAULT_VALUE 1
set_parameter_property ASI_WIDTH DISPLAY_NAME ASI_WIDTH
set_parameter_property ASI_WIDTH DERIVED true
set_parameter_property ASI_WIDTH TYPE INTEGER
set_parameter_property ASI_WIDTH VISIBLE false
set_parameter_property ASI_WIDTH UNITS None
set_parameter_property ASI_WIDTH ALLOWED_RANGES {1, 4}
set_parameter_property ASI_WIDTH HDL_PARAMETER true
add_parameter CS_WIDTH INTEGER 1
set_parameter_property CS_WIDTH DEFAULT_VALUE 1
set_parameter_property CS_WIDTH DISPLAY_NAME CS_WIDTH
set_parameter_property CS_WIDTH DERIVED true
set_parameter_property CS_WIDTH TYPE INTEGER
set_parameter_property CS_WIDTH VISIBLE false
set_parameter_property CS_WIDTH UNITS None
set_parameter_property CS_WIDTH ALLOWED_RANGES {1, 3}
set_parameter_property CS_WIDTH HDL_PARAMETER true
add_parameter CHIP_SELS INTEGER "1"
set_parameter_property CHIP_SELS DISPLAY_NAME "Number of Chip Selects used"
set_parameter_property CHIP_SELS ALLOWED_RANGES {1 2 3}
set_parameter_property CHIP_SELS DESCRIPTION "Number of EPCQ(L) devices that are attached and need a CHIPSEL"
set_parameter_property CHIP_SELS HDL_PARAMETER true
set_parameter_property CHIP_SELS AFFECTS_GENERATION true
add_parameter DDASI INTEGER "0"
set_parameter_property DDASI DISPLAY_NAME "Disable dedicated Active Serial interface"
set_parameter_property DDASI DESCRIPTION "Check to route ASMIBLOCK signals to top level of design"
set_parameter_property DDASI AFFECTS_GENERATION true
set_parameter_property DDASI VISIBLE false
set_parameter_property DDASI DERIVED false
add_parameter ENABLE_4BYTE_ADDR INTEGER "0"
set_parameter_property ENABLE_4BYTE_ADDR DISPLAY_NAME "Enable 4-byte addressing mode"
set_parameter_property ENABLE_4BYTE_ADDR DESCRIPTION "Check to enable 4-byte addressing mode for device larger than 128Mbyte"
set_parameter_property ENABLE_4BYTE_ADDR AFFECTS_GENERATION true
set_parameter_property ENABLE_4BYTE_ADDR VISIBLE false
set_parameter_property ENABLE_4BYTE_ADDR HDL_PARAMETER true
set_parameter_property ENABLE_4BYTE_ADDR DERIVED true
# SPI device selection
add_parameter FLASH_TYPE STRING "EPCQ16"
set_parameter_property FLASH_TYPE DISPLAY_NAME "Configuration device type"
set_parameter_property FLASH_TYPE DESCRIPTION "Select targeted EPCS/EPCQ devices"
set_parameter_property FLASH_TYPE AFFECTS_GENERATION true
set_parameter_property FLASH_TYPE VISIBLE true
set_parameter_property FLASH_TYPE DERIVED false
add_parameter IO_MODE STRING "STANDARD"
set_parameter_property IO_MODE DISPLAY_NAME "Choose I/O mode"
set_parameter_property IO_MODE ALLOWED_RANGES {"STANDARD" "QUAD"}
set_parameter_property IO_MODE DESCRIPTION "Select extended data width when Fast Read operation is enabled"
#
# display items
#
#
# connection point clock_sink
#
add_interface clock_sink clock end
set_interface_property clock_sink clockRate 0
set_interface_property clock_sink ENABLED true
set_interface_property clock_sink EXPORT_OF ""
set_interface_property clock_sink PORT_NAME_MAP ""
set_interface_property clock_sink CMSIS_SVD_VARIABLES ""
set_interface_property clock_sink SVD_ADDRESS_GROUP ""
add_interface_port clock_sink clk clk Input 1
#
# connection point reset
#
add_interface reset reset end
set_interface_property reset associatedClock clock_sink
set_interface_property reset synchronousEdges DEASSERT
set_interface_property reset ENABLED true
set_interface_property reset EXPORT_OF ""
set_interface_property reset PORT_NAME_MAP ""
set_interface_property reset CMSIS_SVD_VARIABLES ""
set_interface_property reset SVD_ADDRESS_GROUP ""
add_interface_port reset reset_n reset_n Input 1
#
# connection point avl_csr
#
add_interface avl_csr avalon end
set_interface_property avl_csr addressUnits WORDS
set_interface_property avl_csr associatedClock clock_sink
set_interface_property avl_csr associatedReset reset
set_interface_property avl_csr bitsPerSymbol 8
set_interface_property avl_csr burstOnBurstBoundariesOnly false
set_interface_property avl_csr burstcountUnits WORDS
set_interface_property avl_csr explicitAddressSpan 0
set_interface_property avl_csr holdTime 0
set_interface_property avl_csr linewrapBursts false
set_interface_property avl_csr maximumPendingReadTransactions 1
set_interface_property avl_csr maximumPendingWriteTransactions 0
set_interface_property avl_csr readLatency 0
set_interface_property avl_csr readWaitTime 0
set_interface_property avl_csr setupTime 0
set_interface_property avl_csr timingUnits Cycles
set_interface_property avl_csr writeWaitTime 0
set_interface_property avl_csr ENABLED true
set_interface_property avl_csr EXPORT_OF ""
set_interface_property avl_csr PORT_NAME_MAP ""
set_interface_property avl_csr CMSIS_SVD_VARIABLES ""
set_interface_property avl_csr SVD_ADDRESS_GROUP ""
add_interface_port avl_csr avl_csr_read read Input 1
add_interface_port avl_csr avl_csr_waitrequest waitrequest Output 1
add_interface_port avl_csr avl_csr_write write Input 1
add_interface_port avl_csr avl_csr_addr address Input 3
add_interface_port avl_csr avl_csr_wrdata writedata Input 32
add_interface_port avl_csr avl_csr_rddata readdata Output 32
add_interface_port avl_csr avl_csr_rddata_valid readdatavalid Output 1
#
# connection point avl_mem
#
add_interface avl_mem avalon end
set_interface_property avl_mem addressUnits WORDS
set_interface_property avl_mem associatedClock clock_sink
set_interface_property avl_mem associatedReset reset
set_interface_property avl_mem bitsPerSymbol 8
set_interface_property avl_mem burstOnBurstBoundariesOnly false
set_interface_property avl_mem burstcountUnits WORDS
set_interface_property avl_mem explicitAddressSpan 0
set_interface_property avl_mem holdTime 0
set_interface_property avl_mem linewrapBursts true
set_interface_property avl_mem maximumPendingReadTransactions 1
set_interface_property avl_mem maximumPendingWriteTransactions 0
set_interface_property avl_mem constantBurstBehavior true
set_interface_property avl_mem readLatency 0
set_interface_property avl_mem readWaitTime 0
set_interface_property avl_mem setupTime 0
set_interface_property avl_mem timingUnits Cycles
set_interface_property avl_mem writeWaitTime 0
set_interface_property avl_mem ENABLED true
set_interface_property avl_mem EXPORT_OF ""
set_interface_property avl_mem PORT_NAME_MAP ""
set_interface_property avl_mem CMSIS_SVD_VARIABLES ""
set_interface_property avl_mem SVD_ADDRESS_GROUP ""
add_interface_port avl_mem avl_mem_write write Input 1
add_interface_port avl_mem avl_mem_burstcount burstcount Input 7
add_interface_port avl_mem avl_mem_waitrequest waitrequest Output 1
add_interface_port avl_mem avl_mem_read read Input 1
add_interface_port avl_mem avl_mem_addr address Input ADDR_WIDTH
add_interface_port avl_mem avl_mem_wrdata writedata Input 32
add_interface_port avl_mem avl_mem_rddata readdata Output 32
add_interface_port avl_mem avl_mem_rddata_valid readdatavalid Output 1
add_interface_port avl_mem avl_mem_byteenable byteenable Input 4
#
# connection point conduit_out
#
add_interface asmi_status_out conduit end
add_interface_port asmi_status_out asmi_status_out conduit_status_out Input 8
add_interface asmi_epcs_id conduit end
add_interface_port asmi_epcs_id asmi_epcs_id conduit_epcs_id Input 8
add_interface asmi_illegal_erase conduit end
add_interface_port asmi_illegal_erase asmi_illegal_erase conduit_illegal_erase Input 1
add_interface asmi_illegal_write conduit end
add_interface_port asmi_illegal_write asmi_illegal_write conduit_illegal_write Input 1
add_interface ddasi_dataoe conduit end
add_interface_port ddasi_dataoe ddasi_dataoe conduit_ddasi_dataoe Input ASI_WIDTH
add_interface ddasi_dclk conduit end
add_interface_port ddasi_dclk ddasi_dclk conduit_ddasi_dclk Input 1
add_interface ddasi_scein conduit end
add_interface_port ddasi_scein ddasi_scein conduit_ddasi_scein Input CS_WIDTH
add_interface ddasi_sdoin conduit end
add_interface_port ddasi_sdoin ddasi_sdoin conduit_ddasi_sdoin Input ASI_WIDTH
add_interface asmi_busy conduit end
add_interface_port asmi_busy asmi_busy conduit_busy Input 1
add_interface asmi_data_valid conduit end
add_interface_port asmi_data_valid asmi_data_valid conduit_data_valid Input 1
add_interface asmi_dataout conduit end
add_interface_port asmi_dataout asmi_dataout conduit_dataout Input 8
add_interface epcq_dataout conduit end
add_interface_port epcq_dataout epcq_dataout conduit_epcq_dataout Input ASI_WIDTH
add_interface ddasi_dataout conduit end
add_interface_port ddasi_dataout ddasi_dataout conduit_ddasi_dataout Output ASI_WIDTH
add_interface asmi_read_rdid conduit end
add_interface_port asmi_read_rdid asmi_read_rdid conduit_read_rdid Output 1
add_interface asmi_read_status conduit end
add_interface_port asmi_read_status asmi_read_status conduit_read_status Output 1
add_interface asmi_read_sid conduit end
add_interface_port asmi_read_sid asmi_read_sid conduit_read_sid Output 1
add_interface asmi_bulk_erase conduit end
add_interface_port asmi_bulk_erase asmi_bulk_erase conduit_bulk_erase Output 1
add_interface asmi_sector_erase conduit end
add_interface_port asmi_sector_erase asmi_sector_erase conduit_sector_erase Output 1
add_interface asmi_sector_protect conduit end
add_interface_port asmi_sector_protect asmi_sector_protect conduit_sector_protect Output 1
add_interface epcq_dclk conduit end
add_interface_port epcq_dclk epcq_dclk conduit_epcq_dclk Output 1
add_interface epcq_scein conduit end
add_interface_port epcq_scein epcq_scein conduit_epcq_scein Output CS_WIDTH
add_interface epcq_sdoin conduit end
add_interface_port epcq_sdoin epcq_sdoin conduit_epcq_sdoin Output ASI_WIDTH
add_interface epcq_dataoe conduit end
add_interface_port epcq_dataoe epcq_dataoe conduit_epcq_dataoe Output ASI_WIDTH
add_interface asmi_clkin conduit end
add_interface_port asmi_clkin asmi_clkin conduit_clkin Output 1
add_interface asmi_reset conduit end
add_interface_port asmi_reset asmi_reset conduit_reset Output 1
add_interface asmi_sce conduit end
add_interface_port asmi_sce asmi_sce conduit_asmi_sce Output CS_WIDTH
add_interface asmi_addr conduit end
add_interface_port asmi_addr asmi_addr conduit_addr Output ASMI_ADDR_WIDTH
add_interface asmi_datain conduit end
add_interface_port asmi_datain asmi_datain conduit_datain Output 8
add_interface asmi_fast_read conduit end
add_interface_port asmi_fast_read asmi_fast_read conduit_fast_read Output 1
add_interface asmi_rden conduit end
add_interface_port asmi_rden asmi_rden conduit_rden Output 1
add_interface asmi_shift_bytes conduit end
add_interface_port asmi_shift_bytes asmi_shift_bytes conduit_shift_bytes Output 1
add_interface asmi_wren conduit end
add_interface_port asmi_wren asmi_wren conduit_wren Output 1
add_interface asmi_write conduit end
add_interface_port asmi_write asmi_write conduit_write Output 1
add_interface asmi_rdid_out conduit end
add_interface_port asmi_rdid_out asmi_rdid_out conduit_rdid_out Input 8
add_interface asmi_en4b_addr conduit end
add_interface_port asmi_en4b_addr asmi_en4b_addr conduit_en4b_addr Output 1
#
# connection point interrupt_sender
#
add_interface interrupt_sender interrupt end
set_interface_property interrupt_sender associatedAddressablePoint avl_csr
set_interface_property interrupt_sender associatedClock clock_sink
set_interface_property interrupt_sender associatedReset reset
set_interface_property interrupt_sender bridgedReceiverOffset ""
set_interface_property interrupt_sender bridgesToReceiver ""
set_interface_property interrupt_sender ENABLED true
set_interface_property interrupt_sender EXPORT_OF ""
set_interface_property interrupt_sender PORT_NAME_MAP ""
set_interface_property interrupt_sender CMSIS_SVD_VARIABLES ""
set_interface_property interrupt_sender SVD_ADDRESS_GROUP ""
add_interface_port interrupt_sender irq irq Output 1
proc validate {} {
set all_supported_SPI_list {"EPCS16" "EPCS64" "EPCS128" "EPCQ16" "EPCQ32" "EPCQ64" "EPCQ128" "EPCQ256" \
"EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024"}
set_parameter_property FLASH_TYPE "ALLOWED_RANGES" $all_supported_SPI_list
set DEVICE_FAMILY [ get_parameter_value DEVICE_FAMILY ]
set CHIP_SELS [ get_parameter_value CHIP_SELS]
set temp_addr_width [ proc_get_derive_addr_width [ get_parameter_value FLASH_TYPE ] ]
set_parameter_value ENABLE_4BYTE_ADDR [ proc_get_derive_enable_2byte_addr [ get_parameter_value FLASH_TYPE ] ]
if { [ get_parameter_value ENABLE_4BYTE_ADDR ] } {
set_parameter_value ASMI_ADDR_WIDTH 32
} else {
set_parameter_value ASMI_ADDR_WIDTH 24
}
# check whether devices supporting multiple flash - only for Arria 10
if {[check_device_family_equivalence $DEVICE_FAMILY "Arria 10"]} {
set is_multi_flash_support "true"
if {$CHIP_SELS eq 3 } {set_parameter_value ADDR_WIDTH [ expr $temp_addr_width + 2]}
if {$CHIP_SELS eq 2 } {set_parameter_value ADDR_WIDTH [ expr $temp_addr_width + 1]}
if {$CHIP_SELS eq 1 } {set_parameter_value ADDR_WIDTH $temp_addr_width }
} else {
set is_multi_flash_support "false"
set_parameter_value ADDR_WIDTH $temp_addr_width
}
}
proc proc_get_derive_enable_2byte_addr {flash_type} {
if { [ string match "*256*" "$flash_type" ] || [ string match "*512*" "$flash_type" ] || [ string match "*1024*" "$flash_type" ]} {
return true
} else {
return false
}
}
proc proc_get_derive_addr_width {flash_type} {
switch $flash_type {
"EPCS16" - "EPCQ16" {
return 19
}
"EPCS64" - "EPCQ64" {
return 21
}
"EPCS128" - "EPCQ128" {
return 22
}
"EPCQ32" {
return 20
}
"EPCQ256" - "EPCQL256" {
return 23
}
"EPCQ512" - "EPCQL512" {
return 24
}
"EPCQL1024" {
return 25
}
default {
# Should never enter this function
send_message error "$flash_type is not a valid flash type"
}
}
}

View File

@ -0,0 +1,58 @@
# (C) 2001-2015 Altera Corporation. All rights reserved.
# Your use of Altera Corporation's design tools, logic functions and other
# software and tools, and its AMPP partner logic functions, and any output
# files any of the foregoing (including device programming or simulation
# files), and any associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License Subscription
# Agreement, Altera MegaCore Function License Agreement, or other applicable
# license agreement, including, without limitation, that your use is for the
# sole purpose of programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the applicable
# agreement for further details.
#
# altera_epcq_controller_sw.tcl
#
# Create a new driver
create_driver altera_epcq_controller_mod_driver
# Associate it with some hardware known as "altera_epcq_controller"
set_sw_property hw_class_name altera_epcq_controller_mod
# The version of this driver
set_sw_property version 15.1
# This driver may be incompatible with versions of hardware less
# than specified below. Updates to hardware and device drivers
# rendering the driver incompatible with older versions of
# hardware are noted with this property assignment.
set_sw_property min_compatible_hw_version 14.1
# Initialize the driver in alt_sys_init()
set_sw_property auto_initialize true
# This driver only works when the following combinations of interfaces
# are enabled and connected as a group of CSR interfaces.
set_sw_property csr_interfaces "avl_mem,avl_csr"
# The EPCQ interrupt has an interrupt but it is not used in the driver.
# These assignments are still required by the Nios II SBT
set_sw_property isr_preemption_supported true
set_sw_property supported_interrupt_apis "legacy_interrupt_api enhanced_interrupt_api"
# Location in generated BSP that above sources will be copied into
set_sw_property bsp_subdirectory drivers
# Header files
add_sw_property include_source HAL/inc/altera_epcq_controller_mod.h
add_sw_property include_source inc/altera_epcq_controller_mod_regs.h
# C/C++ source files
add_sw_property c_source HAL/src/altera_epcq_controller_mod.c
# This driver supports HAL & UCOSII BSP (OS) types
add_sw_property supported_bsp_type HAL
add_sw_property supported_bsp_type UCOSII

View File

@ -0,0 +1,248 @@
// (C) 2001-2015 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
`timescale 1ps / 1ps
${MULTICHIP}
${DDASI_ON}
${SID_EN}
${BULK_ERASE_EN}
${4BYTE_ADDR_EN}
module altera_epcq_controller_wrapper #(
parameter CS_WIDTH = 1,
parameter DEVICE_FAMILY = "Arria V",
parameter ADDR_WIDTH = 24,
parameter ASI_WIDTH = 1,
parameter ENABLE_4BYTE_ADDR = 1,
parameter ASMI_ADDR_WIDTH = 22,
parameter CHIP_SELS = 1
)(
input wire clk,
input wire reset_n,
// ports to access csr
input wire avl_csr_write,
input wire avl_csr_read,
input wire [2:0] avl_csr_addr,
input wire [31:0] avl_csr_wrdata,
output wire [31:0] avl_csr_rddata,
output wire avl_csr_rddata_valid,
output wire avl_csr_waitrequest,
// ports to access memory
input wire avl_mem_write,
input wire avl_mem_read,
input wire [ADDR_WIDTH-1:0] avl_mem_addr,
input wire [31:0] avl_mem_wrdata,
input wire [6:0] avl_mem_burstcount,
input wire [3:0] avl_mem_byteenable,
output wire [31:0] avl_mem_rddata,
output wire avl_mem_rddata_valid,
output wire avl_mem_waitrequest,
`ifdef DDASI_ON
output wire [ASI_WIDTH-1:0] epcq_dataout,
output wire epcq_dclk,
output wire [CS_WIDTH-1:0] epcq_scein,
output wire [ASI_WIDTH-1:0] epcq_sdoin,
output wire [ASI_WIDTH-1:0] epcq_dataoe,
`endif
// interrupt signal
output reg irq
);
`ifdef DDASI_ON
wire [ASI_WIDTH-1:0] ddasi_dataoe;
wire [ASI_WIDTH-1:0] ddasi_dataout;
wire ddasi_dclk;
wire [CS_WIDTH-1:0] ddasi_scein;
wire [ASI_WIDTH-1:0] ddasi_sdoin;
`endif
wire asmi_busy;
wire asmi_data_valid;
wire [7:0] asmi_dataout;
wire asmi_clkin;
wire asmi_reset;
`ifdef MULTICHIP
wire [CS_WIDTH-1:0] asmi_sce;
`endif
wire [ASMI_ADDR_WIDTH-1:0] asmi_addr;
wire [7:0] asmi_datain;
wire asmi_fast_read;
wire asmi_rden;
wire asmi_shift_bytes;
wire asmi_wren;
wire asmi_write;
wire asmi_illegal_erase;
wire asmi_illegal_write;
wire [7:0] asmi_rdid_out;
wire [7:0] asmi_status_out;
`ifdef ENABLE_SID
wire [7:0] asmi_epcs_id;
`endif
wire asmi_read_rdid;
wire asmi_read_status;
wire asmi_read_sid;
`ifdef ENABLE_4BYTE_ADDR_CODE
wire asmi_en4b_addr;
`endif
`ifdef ENABLE_BULK_ERASE
wire asmi_bulk_erase;
`endif
wire asmi_sector_erase;
wire asmi_sector_protect;
altera_epcq_controller_core #(
.DEVICE_FAMILY (DEVICE_FAMILY),
.ADDR_WIDTH (ADDR_WIDTH),
.ASI_WIDTH (ASI_WIDTH),
.ASMI_ADDR_WIDTH (ASMI_ADDR_WIDTH),
.CS_WIDTH (CS_WIDTH),
.ENABLE_4BYTE_ADDR (ENABLE_4BYTE_ADDR),
.CHIP_SELS (CHIP_SELS)
) epcq_controller_inst (
.clk (clk ),
.reset_n (reset_n ),
.avl_csr_write (avl_csr_write ),
.avl_csr_read (avl_csr_read ),
.avl_csr_addr (avl_csr_addr ),
.avl_csr_wrdata (avl_csr_wrdata ),
.avl_csr_rddata (avl_csr_rddata ),
.avl_csr_rddata_valid (avl_csr_rddata_valid ),
.avl_csr_waitrequest (avl_csr_waitrequest ),
.avl_mem_write (avl_mem_write ),
.avl_mem_read (avl_mem_read ),
.avl_mem_addr (avl_mem_addr ),
.avl_mem_wrdata (avl_mem_wrdata ),
.avl_mem_burstcount (avl_mem_burstcount ),
.avl_mem_byteenable (avl_mem_byteenable ),
.avl_mem_rddata (avl_mem_rddata ),
.avl_mem_rddata_valid (avl_mem_rddata_valid ),
.avl_mem_waitrequest (avl_mem_waitrequest ),
.irq (irq ),
`ifdef DDASI_ON
.epcq_dataout (epcq_dataout ),
.epcq_dclk (epcq_dclk ),
.epcq_scein (epcq_scein ),
.epcq_sdoin (epcq_sdoin ),
.epcq_dataoe (epcq_dataoe ),
.ddasi_dataoe (ddasi_dataoe ),
.ddasi_dataout (ddasi_dataout ),
.ddasi_dclk (ddasi_dclk ),
.ddasi_scein (ddasi_scein ),
.ddasi_sdoin (ddasi_sdoin ),
`else
.epcq_dataout ({ASI_WIDTH{1'b0}} ),
.epcq_dclk ( ),
.epcq_scein ( ),
.epcq_sdoin ( ),
.epcq_dataoe ( ),
.ddasi_dataoe ({ASI_WIDTH{1'b0}} ),
.ddasi_dataout ( ),
.ddasi_dclk (1'b0 ),
.ddasi_scein ({CS_WIDTH{1'b0}} ),
.ddasi_sdoin ({ASI_WIDTH{1'b0}} ),
`endif
.asmi_busy (asmi_busy ),
.asmi_data_valid (asmi_data_valid ),
.asmi_dataout (asmi_dataout ),
.asmi_clkin (asmi_clkin ),
.asmi_reset (asmi_reset ),
`ifdef MULTICHIP
.asmi_sce (asmi_sce ),
`else
.asmi_sce ( ),
`endif
.asmi_addr (asmi_addr ),
.asmi_datain (asmi_datain ),
.asmi_fast_read (asmi_fast_read ),
.asmi_rden (asmi_rden ),
.asmi_shift_bytes (asmi_shift_bytes ),
.asmi_wren (asmi_wren ),
.asmi_write (asmi_write ),
.asmi_illegal_erase (asmi_illegal_erase ),
.asmi_illegal_write (asmi_illegal_write ),
.asmi_rdid_out (asmi_rdid_out ),
.asmi_status_out (asmi_status_out ),
`ifdef ENABLE_SID
.asmi_epcs_id (asmi_epcs_id ),
.asmi_read_sid (asmi_read_sid ),
`else
.asmi_epcs_id ({8{1'b0}} ),
.asmi_read_sid ( ),
`endif
.asmi_read_rdid (asmi_read_rdid ),
.asmi_read_status (asmi_read_status ),
`ifdef ENABLE_4BYTE_ADDR_CODE
.asmi_en4b_addr (asmi_en4b_addr ),
`else
.asmi_en4b_addr ( ),
`endif
`ifdef ENABLE_BULK_ERASE
.asmi_bulk_erase (asmi_bulk_erase ),
`else
.asmi_bulk_erase ( ),
`endif
.asmi_sector_erase (asmi_sector_erase ),
.asmi_sector_protect (asmi_sector_protect )
);
altera_asmi_parallel asmi_parallel_inst (
.busy (asmi_busy ),
.data_valid (asmi_data_valid ),
.dataout (asmi_dataout ),
.clkin (asmi_clkin ),
.reset (asmi_reset ),
`ifdef MULTICHIP
.sce (asmi_sce ),
`endif
.addr (asmi_addr ),
.datain (asmi_datain ),
.fast_read (asmi_fast_read ),
.rden (asmi_rden ),
.shift_bytes (asmi_shift_bytes ),
.wren (asmi_wren ),
.write (asmi_write ),
.illegal_erase (asmi_illegal_erase ),
.illegal_write (asmi_illegal_write ),
.rdid_out (asmi_rdid_out ),
.status_out (asmi_status_out ),
.read_dummyclk (1'b0),
`ifdef ENABLE_SID
.epcs_id (asmi_epcs_id ),
.read_sid (asmi_read_sid ),
`endif
.read_rdid (asmi_read_rdid ),
.read_status (asmi_read_status ),
`ifdef ENABLE_4BYTE_ADDR_CODE
.en4b_addr (asmi_en4b_addr ),
`endif
`ifdef ENABLE_BULK_ERASE
.bulk_erase (asmi_bulk_erase ),
`endif
`ifdef DDASI_ON
.asmi_dataoe (ddasi_dataoe ),
.asmi_dataout (ddasi_dataout ),
.asmi_dclk (ddasi_dclk ),
.asmi_scein (ddasi_scein ),
.asmi_sdoin (ddasi_sdoin )
`endif
.sector_erase (asmi_sector_erase ),
.sector_protect (asmi_sector_protect )
);
endmodule

View File

@ -0,0 +1,648 @@
# (C) 2001-2015 Altera Corporation. All rights reserved.
# Your use of Altera Corporation's design tools, logic functions and other
# software and tools, and its AMPP partner logic functions, and any output
# files any of the foregoing (including device programming or simulation
# files), and any associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License Subscription
# Agreement, Altera MegaCore Function License Agreement, or other applicable
# license agreement, including, without limitation, that your use is for the
# sole purpose of programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the applicable
# agreement for further details.
package require -exact qsys 14.1
package require -exact altera_terp 1.0
#
# module altera_trace_wrapper
#
set_module_property DESCRIPTION "This component is a serial flash controller which allows user to access Altera EPCQ devices"
set_module_property NAME altera_epcq_controller_mod
set_module_property VERSION 15.1
set_module_property INTERNAL false
set_module_property OPAQUE_ADDRESS_MAP true
set_module_property GROUP "Basic Functions/Configuration and Programming"
set_module_property AUTHOR "Altera Corporation"
set_module_property DISPLAY_NAME "Altera Serial Flash Controller"
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property HIDE_FROM_QUARTUS true
set_module_property EDITABLE true
set_module_property ALLOW_GREYBOX_GENERATION false
set_module_property REPORT_HIERARCHY false
set_module_property ELABORATION_CALLBACK elaboration
add_fileset QUARTUS_SYNTH QUARTUS_SYNTH add_topwrapper_fileset_proc
set_fileset_property QUARTUS_SYNTH TOP_LEVEL altera_epcq_controller_wrapper
set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false
add_fileset SIM_VERILOG SIM_VERILOG add_topwrapper_fileset_proc
set_fileset_property SIM_VERILOG TOP_LEVEL altera_epcq_controller_wrapper
set_fileset_property SIM_VERILOG ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property SIM_VERILOG ENABLE_FILE_OVERWRITE_MODE true
#
# parameters
#
# +-----------------------------------
# | device family info
# +-----------------------------------
set all_supported_device_families_list {"Arria 10" "Cyclone V" "Arria V GZ" "Arria V" "Stratix V" "Stratix IV" \
"Cyclone IV GX" "Cyclone IV E" "Cyclone III GL" "Arria II GZ" "Arria II GX"}
proc check_device_ini {device_families_list} {
set enable_max10 [get_quartus_ini enable_max10_active_serial ENABLED]
if {$enable_max10 == 1} {
lappend device_families_list "MAX 10 FPGA"
}
return $device_families_list
}
set device_list [check_device_ini $all_supported_device_families_list]
set_module_property SUPPORTED_DEVICE_FAMILIES $device_list
add_parameter DEVICE_FAMILY STRING
set_parameter_property DEVICE_FAMILY SYSTEM_INFO {DEVICE_FAMILY}
set_parameter_property DEVICE_FAMILY VISIBLE false
set_parameter_property DEVICE_FAMILY HDL_PARAMETER true
add_parameter ASI_WIDTH INTEGER 1
set_parameter_property ASI_WIDTH DEFAULT_VALUE 1
set_parameter_property ASI_WIDTH DISPLAY_NAME ASI_WIDTH
set_parameter_property ASI_WIDTH DERIVED true
set_parameter_property ASI_WIDTH TYPE INTEGER
set_parameter_property ASI_WIDTH VISIBLE false
set_parameter_property ASI_WIDTH UNITS None
set_parameter_property ASI_WIDTH ALLOWED_RANGES {1, 4}
set_parameter_property ASI_WIDTH HDL_PARAMETER true
add_parameter CS_WIDTH INTEGER 1
set_parameter_property CS_WIDTH DEFAULT_VALUE 1
set_parameter_property CS_WIDTH DISPLAY_NAME CS_WIDTH
set_parameter_property CS_WIDTH DERIVED true
set_parameter_property CS_WIDTH TYPE INTEGER
set_parameter_property CS_WIDTH VISIBLE false
set_parameter_property CS_WIDTH UNITS None
set_parameter_property CS_WIDTH ALLOWED_RANGES {1, 3}
set_parameter_property CS_WIDTH HDL_PARAMETER true
add_parameter ADDR_WIDTH INTEGER 19
set_parameter_property ADDR_WIDTH DEFAULT_VALUE 19
set_parameter_property ADDR_WIDTH DISPLAY_NAME ADDR_WIDTH
set_parameter_property ADDR_WIDTH DERIVED true
set_parameter_property ADDR_WIDTH TYPE INTEGER
set_parameter_property ADDR_WIDTH VISIBLE false
set_parameter_property ADDR_WIDTH UNITS None
# 16M-19bit, 32M-20bit, 64M-21bit, 128M-22bit, 256M-23bit, 512M-24bit, 1024M-25bit, 2048M-26bit...
set_parameter_property ADDR_WIDTH ALLOWED_RANGES {19, 20, 21, 22, 23, 24, 25, 26, 27, 28}
set_parameter_property ADDR_WIDTH HDL_PARAMETER true
add_parameter ASMI_ADDR_WIDTH INTEGER 24
set_parameter_property ASMI_ADDR_WIDTH DEFAULT_VALUE 24
set_parameter_property ASMI_ADDR_WIDTH DISPLAY_NAME ASMI_ADDR_WIDTH
set_parameter_property ASMI_ADDR_WIDTH DERIVED true
set_parameter_property ASMI_ADDR_WIDTH TYPE INTEGER
set_parameter_property ASMI_ADDR_WIDTH VISIBLE false
set_parameter_property ASMI_ADDR_WIDTH UNITS None
set_parameter_property ASMI_ADDR_WIDTH ALLOWED_RANGES {24, 32}
set_parameter_property ASMI_ADDR_WIDTH HDL_PARAMETER true
add_parameter ENABLE_4BYTE_ADDR INTEGER "0"
set_parameter_property ENABLE_4BYTE_ADDR DISPLAY_NAME "Enable 4-byte addressing mode"
set_parameter_property ENABLE_4BYTE_ADDR DESCRIPTION "Check to enable 4-byte addressing mode for device larger than 128Mbyte"
set_parameter_property ENABLE_4BYTE_ADDR AFFECTS_GENERATION true
set_parameter_property ENABLE_4BYTE_ADDR VISIBLE false
set_parameter_property ENABLE_4BYTE_ADDR HDL_PARAMETER true
set_parameter_property ENABLE_4BYTE_ADDR DERIVED true
# +-----------------------------------
# add system info parameter
add_parameter deviceFeaturesSystemInfo STRING "None"
set_parameter_property deviceFeaturesSystemInfo system_info "DEVICE_FEATURES"
set_parameter_property deviceFeaturesSystemInfo VISIBLE false
add_parameter DDASI INTEGER "0"
set_parameter_property DDASI DISPLAY_NAME "Disable dedicated Active Serial interface"
set_parameter_property DDASI DESCRIPTION "Check to route ASMIBLOCK signals to top level of design"
set_parameter_property DDASI AFFECTS_GENERATION true
set_parameter_property DDASI VISIBLE false
set_parameter_property DDASI DERIVED false
add_parameter clkFreq LONG
set_parameter_property clkFreq DEFAULT_VALUE {0}
set_parameter_property clkFreq DISPLAY_NAME {clkFreq}
set_parameter_property clkFreq VISIBLE {0}
set_parameter_property clkFreq AFFECTS_GENERATION {1}
set_parameter_property clkFreq HDL_PARAMETER {0}
set_parameter_property clkFreq SYSTEM_INFO {clock_rate clk}
set_parameter_property clkFreq SYSTEM_INFO_TYPE {CLOCK_RATE}
set_parameter_property clkFreq SYSTEM_INFO_ARG {clock_sink}
#
# connection point clock_sink
#
add_interface clock_sink clock end
set_interface_property clock_sink clockRate 0
set_interface_property clock_sink ENABLED true
set_interface_property clock_sink EXPORT_OF ""
set_interface_property clock_sink PORT_NAME_MAP ""
set_interface_property clock_sink CMSIS_SVD_VARIABLES ""
set_interface_property clock_sink SVD_ADDRESS_GROUP ""
add_interface_port clock_sink clk clk Input 1
#
# connection point reset
#
add_interface reset reset end
set_interface_property reset associatedClock clock_sink
set_interface_property reset synchronousEdges DEASSERT
set_interface_property reset ENABLED true
set_interface_property reset EXPORT_OF ""
set_interface_property reset PORT_NAME_MAP ""
set_interface_property reset CMSIS_SVD_VARIABLES ""
set_interface_property reset SVD_ADDRESS_GROUP ""
add_interface_port reset reset_n reset_n Input 1
#
# connection point avl_csr
#
add_interface avl_csr avalon end
set_interface_property avl_csr addressUnits WORDS
set_interface_property avl_csr associatedClock clock_sink
set_interface_property avl_csr associatedReset reset
set_interface_property avl_csr bitsPerSymbol 8
set_interface_property avl_csr burstOnBurstBoundariesOnly false
set_interface_property avl_csr burstcountUnits WORDS
set_interface_property avl_csr explicitAddressSpan 0
set_interface_property avl_csr holdTime 0
set_interface_property avl_csr linewrapBursts false
set_interface_property avl_csr maximumPendingReadTransactions 1
set_interface_property avl_csr maximumPendingWriteTransactions 0
set_interface_property avl_csr readLatency 0
set_interface_property avl_csr readWaitTime 0
set_interface_property avl_csr setupTime 0
set_interface_property avl_csr timingUnits Cycles
set_interface_property avl_csr writeWaitTime 0
set_interface_property avl_csr ENABLED true
set_interface_property avl_csr EXPORT_OF ""
set_interface_property avl_csr PORT_NAME_MAP ""
set_interface_property avl_csr CMSIS_SVD_VARIABLES ""
set_interface_property avl_csr SVD_ADDRESS_GROUP ""
add_interface_port avl_csr avl_csr_read read Input 1
add_interface_port avl_csr avl_csr_waitrequest waitrequest Output 1
add_interface_port avl_csr avl_csr_write write Input 1
add_interface_port avl_csr avl_csr_addr address Input 3
add_interface_port avl_csr avl_csr_wrdata writedata Input 32
add_interface_port avl_csr avl_csr_rddata readdata Output 32
add_interface_port avl_csr avl_csr_rddata_valid readdatavalid Output 1
#
# connection point avl_mem
#
add_interface avl_mem avalon end
set_interface_property avl_mem addressUnits WORDS
set_interface_property avl_mem associatedClock clock_sink
set_interface_property avl_mem associatedReset reset
set_interface_property avl_mem bitsPerSymbol 8
set_interface_property avl_mem burstOnBurstBoundariesOnly false
set_interface_property avl_mem burstcountUnits WORDS
set_interface_property avl_mem explicitAddressSpan 0
set_interface_property avl_mem holdTime 0
set_interface_property avl_mem linewrapBursts true
set_interface_property avl_mem maximumPendingReadTransactions 1
set_interface_property avl_mem maximumPendingWriteTransactions 0
set_interface_property avl_mem constantBurstBehavior true
set_interface_property avl_mem readLatency 0
set_interface_property avl_mem readWaitTime 0
set_interface_property avl_mem setupTime 0
set_interface_property avl_mem timingUnits Cycles
set_interface_property avl_mem writeWaitTime 0
set_interface_property avl_mem ENABLED true
set_interface_property avl_mem EXPORT_OF ""
set_interface_property avl_mem PORT_NAME_MAP ""
set_interface_property avl_mem CMSIS_SVD_VARIABLES ""
set_interface_property avl_mem SVD_ADDRESS_GROUP ""
add_interface_port avl_mem avl_mem_write write Input 1
add_interface_port avl_mem avl_mem_burstcount burstcount Input 7
add_interface_port avl_mem avl_mem_waitrequest waitrequest Output 1
add_interface_port avl_mem avl_mem_read read Input 1
add_interface_port avl_mem avl_mem_addr address Input ADDR_WIDTH
add_interface_port avl_mem avl_mem_wrdata writedata Input 32
add_interface_port avl_mem avl_mem_rddata readdata Output 32
add_interface_port avl_mem avl_mem_rddata_valid readdatavalid Output 1
add_interface_port avl_mem avl_mem_byteenable byteenable Input 4
#
# connection point interrupt_sender
#
add_interface interrupt_sender interrupt end
set_interface_property interrupt_sender associatedAddressablePoint avl_csr
set_interface_property interrupt_sender associatedClock clock_sink
set_interface_property interrupt_sender associatedReset reset
set_interface_property interrupt_sender bridgedReceiverOffset ""
set_interface_property interrupt_sender bridgesToReceiver ""
set_interface_property interrupt_sender ENABLED true
set_interface_property interrupt_sender EXPORT_OF ""
set_interface_property interrupt_sender PORT_NAME_MAP ""
set_interface_property interrupt_sender CMSIS_SVD_VARIABLES ""
set_interface_property interrupt_sender SVD_ADDRESS_GROUP ""
add_interface_port interrupt_sender irq irq Output 1
proc proc_get_derive_addr_width {flash_type} {
switch $flash_type {
"EPCS16" - "EPCQ16" {
return 19
}
"EPCS64" - "EPCQ64" {
return 21
}
"EPCS128" - "EPCQ128" {
return 22
}
"EPCQ32" {
return 20
}
"EPCQ256" - "EPCQL256" {
return 23
}
"EPCQ512" - "EPCQL512" {
return 24
}
"EPCQL1024" {
return 25
}
default {
# Should never enter this function
send_message error "$flash_type is not a valid flash type"
}
}
}
set all_supported_SPI_list {"EPCS16" "EPCS64" "EPCS128" "EPCQ16" "EPCQ32" "EPCQ64" "EPCQ128" "EPCQ256" \
"EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024"}
# SPI device selection
add_parameter FLASH_TYPE STRING "EPCQ16"
set_parameter_property FLASH_TYPE DISPLAY_NAME "Configuration device type"
set_parameter_property FLASH_TYPE ALLOWED_RANGES $all_supported_SPI_list
set_parameter_property FLASH_TYPE DESCRIPTION "Select targeted EPCS/EPCQ devices"
set_parameter_property FLASH_TYPE AFFECTS_GENERATION true
set_parameter_property FLASH_TYPE VISIBLE true
set_parameter_property FLASH_TYPE DERIVED false
add_parameter IO_MODE STRING "STANDARD"
set_parameter_property IO_MODE DISPLAY_NAME "Choose I/O mode"
set_parameter_property IO_MODE ALLOWED_RANGES {"STANDARD" "QUAD"}
set_parameter_property IO_MODE DESCRIPTION "Select extended data width when Fast Read operation is enabled"
add_parameter CHIP_SELS INTEGER "1"
set_parameter_property CHIP_SELS DISPLAY_NAME "Number of Chip Selects used"
set_parameter_property CHIP_SELS ALLOWED_RANGES {1 2 3}
set_parameter_property CHIP_SELS DESCRIPTION "Number of EPCQ(L) devices that are attached and need a CHIPSEL"
set_parameter_property CHIP_SELS HDL_PARAMETER true
set_parameter_property CHIP_SELS AFFECTS_GENERATION true
#
# Add instance
#
proc add_topwrapper_fileset_proc {altera_epcq_controller} {
# QSPI that supported for 4-byte addressing - en4b_addr, ex4b_addr
set supported_4byte_addr {"EPCQ256" "EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024" "N25Q512"}
set DDASI [ get_parameter_value DDASI ]
set DEVICE_FAMILY [ get_parameter_value DEVICE_FAMILY ]
set FLASH_TYPE [ get_parameter_value FLASH_TYPE ]
set ADDR_WIDTH [ get_parameter_value ADDR_WIDTH ]
set is_4byte_addr_support "false"
# check whether devices supporting multiple flash - only for Arria 10
if {[check_device_family_equivalence $DEVICE_FAMILY "Arria 10"]} {
set MULTICHIP 1
} else {
set MULTICHIP 0
}
if { $DDASI eq "1" } {
set DDASI_ON 1
} else {
set DDASI_ON 0
}
if { $FLASH_TYPE eq "EPCS16" || $FLASH_TYPE eq "EPCS64" } {
set ENABLE_SID 1
} else {
set ENABLE_SID 0
}
if { $FLASH_TYPE eq "EPCQL512" || $FLASH_TYPE eq "EPCQL1024" } {
set ENABLE_BULK_ERASE 0
} else {
set ENABLE_BULK_ERASE 1
}
# check whether SPI device support 4-byte addressing
foreach re_spi_1 $supported_4byte_addr {
if {$re_spi_1 eq $FLASH_TYPE} {
set is_4byte_addr_support "true"
break;
}
}
if {$is_4byte_addr_support eq "true"} {
set ENABLE_4BYTE_ADDR_CODE 1
} else {
set ENABLE_4BYTE_ADDR_CODE 0
}
# ---------------------------------
# Terp for top level wrapper
# ---------------------------------
#Do Terp
set template_file [ file join "./" "altera_epcq_controller_wrapper.sv.terp" ]
set template [ read [ open $template_file r ] ]
if {$DDASI_ON} {
set params(DDASI_ON) "`define DDASI_ON"
} else {
set params(DDASI_ON) ""
}
if {$MULTICHIP} {
set params(MULTICHIP) "`define MULTICHIP"
} else {
set params(MULTICHIP) ""
}
if {$ENABLE_SID} {
set params(SID_EN) "`define ENABLE_SID"
} else {
set params(SID_EN) ""
}
if {$ENABLE_BULK_ERASE} {
set params(BULK_ERASE_EN) "`define ENABLE_BULK_ERASE"
} else {
set params(BULK_ERASE_EN) ""
}
if {$ENABLE_4BYTE_ADDR_CODE} {
set params(4BYTE_ADDR_EN) "`define ENABLE_4BYTE_ADDR_CODE"
} else {
set params(4BYTE_ADDR_EN) ""
}
set result [ altera_terp $template params ]
#Add top wrapper file
add_fileset_file ./altera_epcq_controller_wrapper.sv SYSTEM_VERILOG TEXT $result
}
# This proc is called by elaboration proc to set embeddedsw C Macros assignments
# used by downstream tools
proc set_cmacros {is_qspi flash_type} {
if {$is_qspi eq "true"} {
set_module_assignment embeddedsw.CMacro.IS_EPCS 0
} else {
set_module_assignment embeddedsw.CMacro.IS_EPCS 1
}
#string name of flash
set_module_assignment embeddedsw.CMacro.FLASH_TYPE $flash_type
#page size in bytes
set_module_assignment embeddedsw.CMacro.PAGE_SIZE 256
#sector and subsector size in bytes
set_module_assignment embeddedsw.CMacro.SUBSECTOR_SIZE 4096
set_module_assignment embeddedsw.CMacro.SECTOR_SIZE 65536
#set number of sectors
switch $flash_type {
"EPCS16" - "EPCQ16" {
set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 32
}
"EPCQ32" {
set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 64
}
"EPCS64" - "EPCQ64" {
set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 128
}
"EPCS128" - "EPCQ128" {
set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 256
}
"EPCQ256" - "EPCQL256" {
set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 512
}
"EPCQ512" - "EPCQL512" {
set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 1024
}
"EPCQL1024" {
set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 2048
}
default {
# Should never enter this function
send_message error "$flash_type is not a valid flash type"
}
}
}
proc elaboration {} {
# QSPI that supported for 4-byte addressing - en4b_addr, ex4b_addr
set supported_4byte_addr {"EPCQ256" "EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024" "N25Q512"}
set DDASI_ON [ get_parameter_value DDASI ]
set FLASH_TYPE [ get_parameter_value FLASH_TYPE ]
set IO_MODE [ get_parameter_value IO_MODE ]
set DEVICE_FAMILY [ get_parameter_value DEVICE_FAMILY ]
set ASI_WIDTH [ get_parameter_value ASI_WIDTH ]
set CS_WIDTH [ get_parameter_value CS_WIDTH ]
set ASMI_ADDR_WIDTH [ get_parameter_value ASMI_ADDR_WIDTH ]
set CHIP_SELS [ get_parameter_value CHIP_SELS]
set temp_addr_width [ proc_get_derive_addr_width [ get_parameter_value FLASH_TYPE ] ]
set clkFreq [ get_parameter_value clkFreq ]
set is_4byte_addr_support "false"
set is_qspi "false"
# we're not using slow and expensive EPCS flash, thus higher frequency allowed
if { $clkFreq > 50000000 } {
send_message error "The maximum input clock frequency for Altera Serial Flash controller is 25Mhz."
}
# check whether SPI device support 4-byte addressing
foreach re_spi_1 $supported_4byte_addr {
if {$re_spi_1 eq $FLASH_TYPE} {
set is_4byte_addr_support "true"
break;
}
}
if {$is_4byte_addr_support eq "true"} {
set_parameter_value ENABLE_4BYTE_ADDR "1"
set_parameter_value ASMI_ADDR_WIDTH 32
} else {
set_parameter_value ENABLE_4BYTE_ADDR "0"
set_parameter_value ASMI_ADDR_WIDTH 24
}
# check whether devices supporting multiple flash - only for Arria 10
if {[check_device_family_equivalence $DEVICE_FAMILY "Arria 10"]} {
set is_multi_flash_support "true"
if {$CHIP_SELS eq 3 } {set_parameter_value ADDR_WIDTH [ expr $temp_addr_width + 2]}
if {$CHIP_SELS eq 2 } {set_parameter_value ADDR_WIDTH [ expr $temp_addr_width + 1]}
if {$CHIP_SELS eq 1 } {set_parameter_value ADDR_WIDTH $temp_addr_width }
} else {
set is_multi_flash_support "false"
set_parameter_value ADDR_WIDTH $temp_addr_width
}
set_instance_parameter_value altera_epcq_controller_core DDASI $DDASI_ON
set_instance_parameter_value altera_epcq_controller_core FLASH_TYPE $FLASH_TYPE
set_instance_parameter_value altera_epcq_controller_core IO_MODE $IO_MODE
set_instance_parameter_value altera_epcq_controller_core ASI_WIDTH $ASI_WIDTH
set_instance_parameter_value altera_epcq_controller_core CS_WIDTH $CS_WIDTH
set_instance_parameter_value altera_epcq_controller_core CHIP_SELS $CHIP_SELS
set_instance_parameter_value altera_epcq_controller_core ASMI_ADDR_WIDTH [ get_parameter_value ASMI_ADDR_WIDTH ]
set_instance_parameter_value altera_epcq_controller_core ADDR_WIDTH [ get_parameter_value ADDR_WIDTH ]
set_instance_parameter_value altera_epcq_controller_core ENABLE_4BYTE_ADDR [ get_parameter_value ENABLE_4BYTE_ADDR ]
set QSPI_list {"EPCQ16" "EPCQ32" "EPCQ64" "EPCQ128" "EPCQ256" "EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024" \
"N25Q512" "S25FL127S"}
# devices that supported QSPI - Quad/Dual data width, asmi_dataout, asmi_sdoin, asmi_dataoe
set supported_QSPI_devices_list {"Arria 10" "Cyclone V" "Arria V GZ" "Arria V" "Stratix V"}
# devices that supported simulation
set supported_sim_devices_list {"Arria 10" "Cyclone V" "Arria V GZ" "Arria V" "Stratix V" "MAX 10 FPGA"}
# check whether is QSPI devices
foreach re_spi_0 $QSPI_list {
if {$re_spi_0 eq $FLASH_TYPE} {
set is_qspi "true"
break;
}
}
if {[check_device_family_equivalence $DEVICE_FAMILY $supported_QSPI_devices_list]} {
set is_qspi_devices_list "true"
} else {
set is_qspi_devices_list "false"
}
if {[check_device_family_equivalence $DEVICE_FAMILY $supported_sim_devices_list]} {
set is_sim_devices_list "true"
} else {
set is_sim_devices_list "false"
}
if {$is_qspi_devices_list eq "true" && $is_qspi eq "true"} {
set_parameter_property IO_MODE ENABLED true
set_instance_parameter_value altera_asmi_parallel DATA_WIDTH $IO_MODE
set_parameter_value ASI_WIDTH 4
} else {
set_parameter_property IO_MODE ENABLED false
set_parameter_value ASI_WIDTH 1
}
if { $FLASH_TYPE eq "EPCQL512" || $FLASH_TYPE eq "EPCQL1024" } {
set_instance_parameter_value altera_asmi_parallel gui_bulk_erase false
set ENABLE_BULK_ERASE 0
} else {
set_instance_parameter_value altera_asmi_parallel gui_bulk_erase true
set ENABLE_BULK_ERASE 1
}
if { $is_multi_flash_support eq "true"} {
set_parameter_value CS_WIDTH 3
set_parameter_property CHIP_SELS ENABLED true
} else {
set_parameter_value CS_WIDTH 1
set_parameter_property CHIP_SELS ENABLED false
}
set_instance_parameter_value altera_asmi_parallel EPCS_TYPE $FLASH_TYPE
set_instance_parameter_value altera_asmi_parallel gui_fast_read true
set_instance_parameter_value altera_asmi_parallel gui_page_write true
if { $FLASH_TYPE eq "EPCS16" || $FLASH_TYPE eq "EPCS64" } {
set_instance_parameter_value altera_asmi_parallel gui_read_sid true
} else {
set_instance_parameter_value altera_asmi_parallel gui_read_sid false
}
set_instance_parameter_value altera_asmi_parallel gui_read_rdid true
set_instance_parameter_value altera_asmi_parallel gui_read_status true
set_instance_parameter_value altera_asmi_parallel gui_sector_erase true
set_instance_parameter_value altera_asmi_parallel gui_sector_protect true
set_instance_parameter_value altera_asmi_parallel gui_wren true
set_instance_parameter_value altera_asmi_parallel gui_write true
set_instance_parameter_value altera_asmi_parallel gui_read_dummyclk true
set_instance_parameter_value altera_asmi_parallel PAGE_SIZE 256
set_instance_parameter_value altera_asmi_parallel gui_use_asmiblock $DDASI_ON
if {$is_sim_devices_list eq "true"} {
set_instance_parameter_value altera_asmi_parallel ENABLE_SIM true
} else {
set_instance_parameter_value altera_asmi_parallel ENABLE_SIM false
}
set_cmacros $is_qspi $FLASH_TYPE
}
# add ASMI PARALLEL
add_hdl_instance altera_asmi_parallel altera_asmi_parallel
# add EPCQ CONTROLLER
add_hdl_instance altera_epcq_controller_core altera_epcq_controller_core
# +-------------------------------------
# | Add settings needed by Nios tools
# +-------------------------------------
# Tells us component is a flash
set_module_assignment embeddedsw.memoryInfo.IS_FLASH 1
# interface assignments for embedded software
set_interface_assignment avl_mem embeddedsw.configuration.isFlash 1
set_interface_assignment avl_mem embeddedsw.configuration.isMemoryDevice 1
set_interface_assignment avl_mem embeddedsw.configuration.isNonVolatileStorage 1
set_interface_assignment avl_mem embeddedsw.configuration.isPrintableDevice 0
# These assignments tells tools to create byte-addressed .hex files only
set_module_assignment embeddedsw.memoryInfo.GENERATE_HEX 1
set_module_assignment embeddedsw.memoryInfo.USE_BYTE_ADDRESSING_FOR_HEX 1
set_module_assignment embeddedsw.memoryInfo.GENERATE_DAT_SYM 0
set_module_assignment embeddedsw.memoryInfo.GENERATE_FLASH 0
# Width of memory
set_module_assignment embeddedsw.memoryInfo.MEM_INIT_DATA_WIDTH 32
# Output directories for programming files
#set_module_assignment embeddedsw.memoryInfo.DAT_SYM_INSTALL_DIR {SIM_DIR}
#set_module_assignment embeddedsw.memoryInfo.FLASH_INSTALL_DIR {APP_DIR}
set_module_assignment embeddedsw.memoryInfo.HEX_INSTALL_DIR {QPF_DIR}
# Module assignments related to names of simulation files
#set_module_assignment postgeneration.simulation.init_file.param_name {INIT_FILENAME}
#set_module_assignment postgeneration.simulation.init_file.type {MEM_INIT}
# +-------------------------------------
# | Add settings needed by DTG tools
# +-------------------------------------
# add device tree properties
set_module_assignment embeddedsw.dts.vendor "altr"
set_module_assignment embeddedsw.dts.name "epcq"
set_module_assignment embeddedsw.dts.group "epcq"
set_module_assignment embeddedsw.dts.compatible "altr,epcq-1.0"
## Add documentation links for user guide and/or release notes
add_documentation_link "User Guide" https://documentation.altera.com/#/link/sfo1400787952932/iga1431459459085
add_documentation_link "Release Notes" https://documentation.altera.com/#/link/hco1421698042087/hco1421697689300

View File

@ -0,0 +1,260 @@
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2014 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* *
******************************************************************************/
#ifndef __ALTERA_EPCQ_CONTROLLER_REGS_H__
#define __ALTERA_EPCQ_CONTROLLER_REGS_H__
#include <io.h>
/*
* EPCQ_RD_STATUS register offset
*
* The EPCQ_RD_STATUS register contains information from the read status
* register operation. A full description of the register can be found in the
* data sheet,
*
*/
#define ALTERA_EPCQ_CONTROLLER_STATUS_REG (0x0)
/*
* EPCQ_RD_STATUS register access macros
*/
#define IOADDR_ALTERA_EPCQ_CONTROLLER_STATUS(base) \
__IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG)
#define IORD_ALTERA_EPCQ_CONTROLLER_STATUS(base) \
IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG)
#define IOWR_ALTERA_EPCQ_CONTROLLER_STATUS(base, data) \
IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG, data)
/*
* EPCQ_RD_STATUS register description macros
*/
/** Write in progress bit */
#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_MASK (0x00000001)
#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_AVAILABLE (0x00000000)
#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_BUSY (0x00000001)
/** When to time out a poll of the write in progress bit */
/* 0.7 sec time out */
#define ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE 700000
/*
* EPCQ_RD_SID register offset
*
* The EPCQ_RD_SID register contains the information from the read silicon ID
* operation and can be used to determine what type of EPCS device we have.
* Only support in EPCS16 and EPCS64.
*
* This register is valid only if the device is an EPCS.
*
*/
#define ALTERA_EPCQ_CONTROLLER_SID_REG (0x4)
/*
* EPCQ_RD_SID register access macros
*/
#define IOADDR_ALTERA_EPCQ_CONTROLLER_SID(base) \
__IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_SID_REG)
#define IORD_ALTERA_EPCQ_CONTROLLER_SID(base) \
IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_SID_REG)
#define IOWR_ALTERA_EPCQ_CONTROLLER_SID(base, data) \
IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_SID_REG, data)
/*
* EPCQ_RD_SID register description macros
*
* Specific device values obtained from Table 14 of:
* "Serial Configuration (EPCS) Devices Datasheet"
*/
#define ALTERA_EPCQ_CONTROLLER_SID_MASK (0x000000FF)
#define ALTERA_EPCQ_CONTROLLER_SID_EPCS16 (0x00000014)
#define ALTERA_EPCQ_CONTROLLER_SID_EPCS64 (0x00000016)
#define ALTERA_EPCQ_CONTROLLER_SID_EPCS128 (0x00000018)
/*
* EPCQ_RD_RDID register offset
*
* The EPCQ_RD_RDID register contains the information from the read memory
* capacity operation and can be used to determine what type of EPCQ device
* we have.
*
* This register is only valid if the device is an EPCQ.
*
*/
#define ALTERA_EPCQ_CONTROLLER_RDID_REG (0x8)
/*
* EPCQ_RD_RDID register access macros
*/
#define IOADDR_ALTERA_EPCQ_CONTROLLER_RDID(base) \
__IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_RDID_REG)
#define IORD_ALTERA_EPCQ_CONTROLLER_RDID(base) \
IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_RDID_REG)
#define IOWR_ALTERA_EPCQ_CONTROLLER_RDID(base, data) \
IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_RDID_REG, data)
/*
* EPCQ_RD_RDID register description macros
*
* Specific device values obtained from Table 28 of:
* "Quad-Serial Configuration (EPCQ (www.altera.com/literature/hb/cfg/cfg_cf52012.pdf))
* Devices Datasheet"
*/
#define ALTERA_EPCQ_CONTROLLER_RDID_MASK (0x000000FF)
#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ16 (0x00000015)
#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ32 (0x00000016)
#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ64 (0x00000017)
#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ128 (0x00000018)
#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ256 (0x00000019)
#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ512 (0x00000020)
#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ1024 (0x00000021)
/*
* EPCQ_MEM_OP register offset
*
* The EPCQ_MEM_OP register is used to do memory protect and erase operations
*
*/
#define ALTERA_EPCQ_CONTROLLER_MEM_OP_REG (0xC)
/*
* EPCQ_MEM_OP register access macros
*/
#define IOADDR_ALTERA_EPCQ_CONTROLLER_MEM_OP(base) \
__IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG)
#define IORD_ALTERA_EPCQ_CONTROLLER_MEM_OP(base) \
IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG)
#define IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(base, data) \
IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG, data)
/*
* EPCQ_MEM_OP register description macros
*/
#define ALTERA_EPCQ_CONTROLLER_MEM_OP_CMD_MASK (0x00000003)
#define ALTERA_EPCQ_CONTROLLER_MEM_OP_BULK_ERASE_CMD (0x00000001)
#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_ERASE_CMD (0x00000002)
#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_PROTECT_CMD (0x00000003)
/** see datasheet for sector values */
#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_VALUE_MASK (0x00FFFF00)
/*
* EPCQ_ISR register offset
*
* The EPCQ_ISR register is used to determine whether an invalid write or erase
* operation triggered an interrupt
*
*/
#define ALTERA_EPCQ_CONTROLLER_ISR_REG (0x10)
/*
* EPCQ_ISR register access macros
*/
#define IOADDR_ALTERA_EPCQ_CONTROLLER_ISR(base) \
__IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_ISR_REG)
#define IORD_ALTERA_EPCQ_CONTROLLER_ISR(base) \
IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_ISR_REG)
#define IOWR_ALTERA_EPCQ_CONTROLLER_ISR(base, data) \
IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_ISR_REG, data)
/*
* EPCQ_ISR register description macros
*/
#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK (0x00000001)
#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_ACTIVE (0x00000001)
#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK (0x00000002)
#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_ACTIVE (0x00000002)
/*
* EPCQ_IMR register offset
*
* The EPCQ_IMR register is used to mask the invalid erase or the invalid write
* interrupts.
*
*/
#define ALTERA_EPCQ_CONTROLLER_IMR_REG (0x14)
/*
* EPCQ_IMR register access macros
*/
#define IOADDR_ALTERA_EPCQ_CONTROLLER_IMR(base) \
__IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_IMR_REG)
#define IORD_ALTERA_EPCQ_CONTROLLER_IMR(base) \
IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_IMR_REG)
#define IOWR_ALTERA_EPCQ_CONTROLLER_IMR(base, data) \
IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_IMR_REG, data)
/*
* EPCQ_IMR register description macros
*/
#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_ERASE_MASK (0x00000001)
#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_ERASE_ENABLED (0x00000001)
#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_WRITE_MASK (0x00000002)
#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_WRITE_ENABLED (0x00000002)
/*
* EPCQ_CHIP_SELECT register offset
*
* The EPCQ_CHIP_SELECT register is used to issue chip select
*/
#define ALTERA_EPCQ_CHIP_SELECT_REG (0x18)
/*
* EPCQ_CHIP_SELECT register access macros
*/
#define IOADDR_ALTERA_EPCQ_CHIP_SELECT(base) \
__IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CHIP_SELECT_REG)
#define IOWR_ALTERA_EPCQ_CHIP_SELECT(base, data) \
IOWR_32DIRECT(base, ALTERA_EPCQ_CHIP_SELECT_REG, data)
/*
* EPCQ_CHIP_SELECT register description macros
*/
#define ALTERA_EPCQ_CHIP1_SELECT (0x00000001)
#define ALTERA_EPCQ_CHIP2_SELECT (0x00000002)
#define ALTERA_EPCQ_CHIP3_SELECT (0x00000003)
#endif /* __ALTERA_EPCQ_CONTROLLER_REGS_H__ */

View File

@ -0,0 +1,56 @@
// (C) 2001-2015 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
//Legal Notice: (C)2010 Altera Corporation. All rights reserved. Your
//use of Altera Corporation's design tools, logic functions and other
//software and tools, and its AMPP partner logic functions, and any
//output files any of the foregoing (including device programming or
//simulation files), and any associated documentation or information are
//expressly subject to the terms and conditions of the Altera Program
//License Subscription Agreement or other applicable license agreement,
//including, without limitation, that your use is for the sole purpose
//of programming logic devices manufactured by Altera and sold by Altera
//or its authorized distributors. Please refer to the applicable
//agreement for further details.
// synthesis translate_off
`timescale 1ns / 1ps
// synthesis translate_on
// turn off superfluous verilog processor warnings
// altera message_level Level1
// altera message_off 10034 10035 10036 10037 10230 10240 10030
module endianconverter_qsys (
// inputs:
dataa,
datab,
// outputs:
result
)
;
output [ 31: 0] result;
input [ 31: 0] dataa;
input [ 31: 0] datab;
wire [ 31: 0] result;
//s1, which is an e_custom_instruction_slave
assign result[7 : 0] = dataa[31 : 24];
assign result[15 : 8] = dataa[23 : 16];
assign result[23 : 16] = dataa[15 : 8];
assign result[31 : 24] = dataa[7 : 0];
endmodule

View File

@ -0,0 +1,84 @@
# (C) 2001-2015 Altera Corporation. All rights reserved.
# Your use of Altera Corporation's design tools, logic functions and other
# software and tools, and its AMPP partner logic functions, and any output
# files any of the foregoing (including device programming or simulation
# files), and any associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License Subscription
# Agreement, Altera MegaCore Function License Agreement, or other applicable
# license agreement, including, without limitation, that your use is for the
# sole purpose of programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the applicable
# agreement for further details.
# TCL File Generated by Component Editor 10.1
# Tue Aug 17 15:04:48 MYT 2010
# DO NOT MODIFY
# +-----------------------------------
# |
# |
# | ./converter_0.v syn, sim
# |
# +-----------------------------------
# +-----------------------------------
# | request TCL package from ACDS 10.1
# |
package require -exact sopc 10.1
# |
# +-----------------------------------
# +-----------------------------------
# | module altera_nios_custom_instr_endian_converter
# |
set_module_property NAME altera_nios_custom_instr_endianconverter
set_module_property VERSION "__VERSION_SHORT__"
set_module_property INTERNAL false
set_module_property GROUP "Custom Instruction Modules"
set_module_property AUTHOR "Altera Corporation"
set_module_property DISPLAY_NAME "Endian Converter"
set_module_property HIDE_FROM_SOPC true
set_module_property TOP_LEVEL_HDL_FILE endianconverter_qsys.v
set_module_property TOP_LEVEL_HDL_MODULE endianconverter_qsys
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property SIMULATION_MODEL_IN_VHDL true
set_module_property EDITABLE false
set_module_property ANALYZE_HDL FALSE
# |
# +-----------------------------------
# +-----------------------------------
# | files
# |
add_file endianconverter_qsys.v {SYNTHESIS SIMULATION}
# |
# +-----------------------------------
# +-----------------------------------
# | parameters
# |
# |
# +-----------------------------------
# +-----------------------------------
# | display items
# |
# |
# +-----------------------------------
# +-----------------------------------
# | connection point s1
# |
add_interface s1 nios_custom_instruction end
set_interface_property s1 clockCycle 1
set_interface_property s1 operands 1
set_interface_property s1 ENABLED true
add_interface_port s1 dataa dataa Input 32
add_interface_port s1 datab datab Input 32
add_interface_port s1 result result Output 32
# |
# +-----------------------------------

View File

@ -0,0 +1,159 @@
# (C) 2001-2015 Altera Corporation. All rights reserved.
# Your use of Altera Corporation's design tools, logic functions and other
# software and tools, and its AMPP partner logic functions, and any output
# files any of the foregoing (including device programming or simulation
# files), and any associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License Subscription
# Agreement, Altera MegaCore Function License Agreement, or other applicable
# license agreement, including, without limitation, that your use is for the
# sole purpose of programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the applicable
# agreement for further details.
# TCL File Generated by Component Editor 8.0
# Mon Dec 22 17:22:07 EST 2008
# DO NOT MODIFY
set aup_version 15.1
# +-----------------------------------
# |
# | Altera_UP_SD_Card_Avalon_Interface "Altera_UP_SD_Card_Avalon_Interface" v1.0
# | null 2008.12.22.17:22:07
# | A module that allows communication with an SD Card
# |
# | ./hdl/Altera_UP_SD_Card_Avalon_Interface.vhd syn
# | ./hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd syn
# | ./hdl/Altera_UP_SD_Card_Buffer.vhd syn
# | ./hdl/Altera_UP_SD_Card_Clock.vhd syn
# | ./hdl/Altera_UP_SD_Card_Control_FSM.vhd syn
# | ./hdl/Altera_UP_SD_Card_Interface.vhd syn
# | ./hdl/Altera_UP_SD_Card_Memory_Block.qip syn
# | ./hdl/Altera_UP_SD_Card_Response_Receiver.vhd syn
# | ./hdl/Altera_UP_SD_CRC16_Generator.vhd syn
# | ./hdl/Altera_UP_SD_CRC7_Generator.vhd syn
# | ./hdl/Altera_UP_SD_Signal_Trigger.vhd syn
# |
# +-----------------------------------
# +-----------------------------------
# | module Altera_UP_SD_Card_Avalon_Interface
# |
set_module_property DESCRIPTION "A module that allows communication with an SD Card"
set_module_property NAME Altera_UP_SD_Card_Avalon_Interface_mod
set_module_property VERSION $aup_version
set_module_property GROUP "Memory"
set_module_property DISPLAY_NAME "SD Card Interface"
set_module_property DATASHEET_URL "[pwd]/doc/SD_Card_Interface_for_SoPC_Builder.pdf"
set_module_property LIBRARIES {ieee.std_logic_1164.all ieee.std_logic_arith.all ieee.std_logic_unsigned.all std.standard.all}
set_module_property TOP_LEVEL_HDL_FILE "hdl/Altera_UP_SD_Card_Avalon_Interface.vhd"
set_module_property TOP_LEVEL_HDL_MODULE Altera_UP_SD_Card_Avalon_Interface
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property EDITABLE false
#set_module_property ANALYZE_HDL false
set_module_property SIMULATION_MODEL_IN_VERILOG false
set_module_property SIMULATION_MODEL_IN_VHDL false
set_module_property SIMULATION_MODEL_HAS_TULIPS false
set_module_property SIMULATION_MODEL_IS_OBFUSCATED false
# |
# +-----------------------------------
# +-----------------------------------
# | files
# |
add_file hdl/Altera_UP_SD_Card_Avalon_Interface.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_Card_Buffer.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_Card_Clock.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_Card_Control_FSM.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_Card_Interface.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_Card_Response_Receiver.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_CRC16_Generator.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_CRC7_Generator.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_Signal_Trigger.vhd {SYNTHESIS}
add_file hdl/Altera_UP_SD_Card_Memory_Block.vhd {SYNTHESIS}
# |
# +-----------------------------------
# +-----------------------------------
# | parameters
# |
# |
# +-----------------------------------
# +-----------------------------------
# | connection point avalon_sdcard_slave
# |
add_interface avalon_sdcard_slave avalon end
set_interface_property avalon_sdcard_slave holdTime 0
set_interface_property avalon_sdcard_slave linewrapBursts false
set_interface_property avalon_sdcard_slave minimumUninterruptedRunLength 1
set_interface_property avalon_sdcard_slave bridgesToMaster ""
set_interface_property avalon_sdcard_slave isMemoryDevice false
set_interface_property avalon_sdcard_slave burstOnBurstBoundariesOnly false
set_interface_property avalon_sdcard_slave addressSpan 1024
set_interface_property avalon_sdcard_slave timingUnits Cycles
set_interface_property avalon_sdcard_slave setupTime 0
set_interface_property avalon_sdcard_slave writeWaitTime 0
set_interface_property avalon_sdcard_slave isNonVolatileStorage false
set_interface_property avalon_sdcard_slave addressAlignment DYNAMIC
set_interface_property avalon_sdcard_slave maximumPendingReadTransactions 0
set_interface_property avalon_sdcard_slave readWaitTime 1
set_interface_property avalon_sdcard_slave readLatency 0
set_interface_property avalon_sdcard_slave printableDevice false
set_interface_property avalon_sdcard_slave associatedClock clk
set_interface_property avalon_sdcard_slave associatedReset reset
add_interface_port avalon_sdcard_slave i_avalon_chip_select chipselect Input 1
add_interface_port avalon_sdcard_slave i_avalon_address address Input 8
add_interface_port avalon_sdcard_slave i_avalon_read read Input 1
add_interface_port avalon_sdcard_slave i_avalon_write write Input 1
add_interface_port avalon_sdcard_slave i_avalon_byteenable byteenable Input 4
add_interface_port avalon_sdcard_slave i_avalon_writedata writedata Input 32
add_interface_port avalon_sdcard_slave o_avalon_readdata readdata Output 32
add_interface_port avalon_sdcard_slave o_avalon_waitrequest waitrequest Output 1
# |
# +-----------------------------------
# +-----------------------------------
# | connection point clk
# |
add_interface clk clock end
set_interface_property clk enabled true
add_interface_port clk i_clock clk Input 1
# |
# +-----------------------------------
# +-----------------------------------
# | connection point reset
# |
add_interface reset reset end
set_interface_property reset associatedClock clk
set_interface_property reset enabled true
set_interface_property reset synchronousEdges DEASSERT
add_interface_port reset i_reset_n reset_n Input 1
# |
# +-----------------------------------
# +-----------------------------------
# | connection point conduit_end
# |
add_interface conduit_end conduit end
add_interface_port conduit_end b_SD_cmd export Bidir 1
add_interface_port conduit_end b_SD_dat export Bidir 1
add_interface_port conduit_end b_SD_dat3 export Bidir 1
add_interface_port conduit_end o_SD_clock export Output 1
# |
# +-----------------------------------
## Add documentation links for user guide and/or release notes
add_documentation_link "User Guide" file:///ip/altera/university_program/memory/altera_up_sd_card_avalon_interface/doc/SD_Card_Interface_for_SoPC_Builder.pdf
add_documentation_link "Release Notes" https://documentation.altera.com/#/link/hco1421698042087/hco1421698013408

View File

@ -0,0 +1,56 @@
# (C) 2001-2015 Altera Corporation. All rights reserved.
# Your use of Altera Corporation's design tools, logic functions and other
# software and tools, and its AMPP partner logic functions, and any output
# files any of the foregoing (including device programming or simulation
# files), and any associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License Subscription
# Agreement, Altera MegaCore Function License Agreement, or other applicable
# license agreement, including, without limitation, that your use is for the
# sole purpose of programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the applicable
# agreement for further details.
# TCL File Generated by Altera University Program
# DO NOT MODIFY
set aup_version 15.1
# Create a new driver - this name must be different than the
# hardware component name
create_driver Altera_UP_SD_Card_Avalon_Interface_mod_driver
# Associate it with some hardware
set_sw_property hw_class_name Altera_UP_SD_Card_Avalon_Interface_mod
# The version of this driver
set_sw_property version $aup_version
# This driver is proclaimed to be compatible with 'component'
# as old as version "1.0". The component hardware version is set in the
# _hw.tcl file - If the hardware component version number is not equal
# or greater than the min_compatable_hw_version number, the driver
# source files will not be copied over to the BSP driver directory
set_sw_property min_compatible_hw_version 15.1
# Initialize the driver in alt_sys_init()
set_sw_property auto_initialize true
# Location in generated BSP that sources will be copied into
set_sw_property bsp_subdirectory drivers
#
# Source file listings...
#
# C/C++ source files
add_sw_property c_source HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c
# Include files
add_sw_property include_source HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h
# This driver supports HAL type
add_sw_property supported_bsp_type HAL
# End of file

View File

@ -0,0 +1,166 @@
#ifndef __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__
#define __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__
#include <stddef.h>
#include <alt_types.h>
#include <sys/alt_dev.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#define SD_RAW_IFACE
/*
* Device structure definition. Each instance of the driver uses one
* of these structures to hold its associated state.
*/
typedef struct alt_up_sd_card_dev {
/// @brief character mode device structure
/// @sa Developing Device Drivers for the HAL in Nios II Software Developer's Handbook
alt_dev dev;
/// @brief the base address of the device
unsigned int base;
} alt_up_sd_card_dev;
#ifndef bool
typedef enum e_bool { false = 0, true = 1 } bool;
#endif
//////////////////////////////////////////////////////////////////////////
// HAL system functions
alt_up_sd_card_dev* alt_up_sd_card_open_dev(const char *name);
/* Open an SD Card Interface if it is connected to the system. */
bool alt_up_sd_card_is_Present(void);
/* Check if there is an SD Card insterted into the SD Card socket.
*/
#ifndef SD_RAW_IFACE
bool alt_up_sd_card_is_FAT16(void);
/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16
* volume. Please note that FAT12 has a similar format, but will not be supported by this driver.
*/
short int alt_up_sd_card_fopen(char *name, bool create);
/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16
* volume. Please note that FAT12 has a similar format, but will not be supported by this driver.
*
* Inputs:
* name - a file name including a directory, relative to the root directory
* create - a flag set to true to create a file if it does not already exist
* Output:
* An index to the file record assigned to the specified file. -1 is returned if the file could not be opened.
*/
short int alt_up_sd_card_find_first(char *directory_to_search_through, char *file_name);
/* This function sets up a search algorithm to go through a given directory looking for files.
* If the search directory is valid, then the function searches for the first file it finds.
* Inputs:
* directory_to_search_through - name of the directory to search through
* file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination).
* Outputs:
* 0 - success
* 1 - invalid directory
* 2 - No card or incorrect card format.
*
* To specify a directory give the name in a format consistent with the following regular expression:
* [{[valid_chars]+}/]*.
*
* In other words, give a path name starting at the root directory, where each directory name is followed by a '/'.
* Then, append a '.' to the directory name. Examples:
* "." - look through the root directory
* "first/." - look through a directory named "first" that is located in the root directory.
* "first/sub/." - look through a directory named "sub", that is located within the subdirectory named "first". "first" is located in the root directory.
* Invalid examples include:
* "/.", "/////." - this is not the root directory.
* "/first/." - the first character may not be a '/'.
*/
short int alt_up_sd_card_find_next(char *file_name);
/* This function searches for the next file in a given directory, as specified by the find_first function.
* Inputs:
* file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination).
* Outputs:
* -1 - end of directory.
* 0 - success
* 2 - No card or incorrect card format.
* 4 - find_first has not been called successfully.
*/
void alt_up_sd_card_set_attributes(short int file_handle, short int attributes);
/* Set file attributes as needed.
*/
short int alt_up_sd_card_get_attributes(short int file_handle);
/* Return file attributes, or -1 if the file_handle is invalid.
*/
short int alt_up_sd_card_read(short int file_handle);
/* Read a single character from the given file. Return -1 if at the end of a file. Any other negative number
* means that the file could not be read. A number between 0 and 255 is an ASCII character read from the SD Card. */
bool alt_up_sd_card_write(short int file_handle, char byte_of_data);
/* Write a single character to a given file. Return true if successful, and false otherwise. */
bool alt_up_sd_card_fclose(short int file_handle);
// This function closes an opened file and saves data to SD Card if necessary.
#else
bool Write_Sector_Data(int sector_index, int partition_offset);
bool Save_Modified_Sector();
bool Read_Sector_Data(int sector_index, int partition_offset);
#endif //SD_RAW_IFACE
//////////////////////////////////////////////////////////////////////////
// file-like operation functions
//////////////////////////////////////////////////////////////////////////
// direct operation functions
/*
* Macros used by alt_sys_init
*/
#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INSTANCE(name, device) \
static alt_up_sd_card_dev device = \
{ \
{ \
ALT_LLIST_ENTRY, \
name##_NAME, \
NULL , /* open */ \
NULL , /* close */ \
NULL, /* read */ \
NULL, /* write */ \
NULL , /* lseek */ \
NULL , /* fstat */ \
NULL , /* ioctl */ \
}, \
name##_BASE, \
}
#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INIT(name, device) \
{ \
alt_dev_reg(&device.dev); \
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ */

View File

@ -0,0 +1,79 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
----------------------------------------------------------------------------------------
-- This generates the necessary 16-CRC for Command and Response
-- Implementation: serial input/parallel output
-- When input stream ends, the crcout output is the CRC checksum for them
--
-- NOTES/REVISIONS:
----------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Altera_UP_SD_CRC16_Generator is
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_sync_reset : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of Altera_UP_SD_CRC16_Generator is
-- Local wires
-- REGISTERED
signal shift_register : std_logic_vector(15 downto 0);
begin
process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
shift_register <= (OTHERS => '0');
else
if (rising_edge(i_clock)) then
if (i_sync_reset = '1') then
shift_register <= (OTHERS => '0');
elsif (i_enable = '1') then
if (i_shift = '0') then
shift_register(0) <= i_datain XOR shift_register(15);
shift_register(4 downto 1) <= shift_register(3 downto 0);
shift_register(5) <= shift_register(4) XOR i_datain XOR shift_register(15);
shift_register(11 downto 6) <= shift_register(10 downto 5);
shift_register(12) <= shift_register(11) XOR i_datain XOR shift_register(15);
shift_register(15 downto 13) <= shift_register(14 downto 12);
else -- shift CRC out (no more calculation now)
shift_register(15 downto 1) <= shift_register(14 downto 0);
shift_register(0) <= '0';
end if;
end if;
end if;
end if;
end process;
o_dataout <= shift_register(15);
o_crcout <= shift_register;
end rtl;

View File

@ -0,0 +1,76 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
---------------------------------------------------------------------------------------
-- This generates the necessary 7-CRC for Command and Response
-- Implementation: serial input/parallel output
--
-- When input stream ends, the crcout output is the CRC checksum for the input stream.
--
-- NOTES/REVISIONS:
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Altera_UP_SD_CRC7_Generator is
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(6 downto 0)
);
end entity;
architecture rtl of Altera_UP_SD_CRC7_Generator is
-- Local wires
-- REGISTERED
signal shift_register : std_logic_vector(6 downto 0);
begin
process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
shift_register <= (OTHERS => '0');
else
if (rising_edge(i_clock)) then
if (i_enable = '1') then
if (i_shift = '0') then
shift_register(0) <= i_datain XOR shift_register(6);
shift_register(1) <= shift_register(0);
shift_register(2) <= shift_register(1);
shift_register(3) <= shift_register(2) XOR i_datain XOR shift_register(6);
shift_register(4) <= shift_register(3);
shift_register(5) <= shift_register(4);
shift_register(6) <= shift_register(5);
else -- shift CRC out (no more calculation now)
shift_register(0) <= '0';
shift_register(6 downto 1) <= shift_register(5 downto 0);
end if;
end if;
end if;
end if;
end process;
o_dataout <= shift_register(6);
o_crcout <= shift_register;
end rtl;

View File

@ -0,0 +1,570 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-------------------------------------------------------------------------------------
-- This module takes a command ID and data, and generates a 48-bit message for it.
-- It will first check if the command is a valid 48-bit command and produce the
-- following outputs:
-- 1. o_dataout -> a single bit output that produces the message to be sent to the
-- SD card one bit at a time. Every time the i_message_bit_out input
-- is high and the i_clock has a positive edge, a new bit is produced.
-- 2. o_message_done -> a signal that is asserted high when the entire message has been
-- produced through the o_dataout output.
-- 3. o_valid -> is a signal that is asserted high if the specified message is valid.
-- 4. o_response_type -> indicates the command response type.
-- 5. o_returning_ocr -> the response from the SD card will contain the OCR register
-- 6. o_returning_cid -> the response from the SD card will contain the CID register
-- 7. o_returning_rca -> the response from the SD card will contain the RCA register
-- 8. o_returning_csd -> the response from the SD card will contain the CSD register
-- 9. o_data_read -> asserted when the command being sent is a data read command.
-- 10. o_data_write -> asserted when the command being sent is a data write command.
-- 11. o_wait_cmd_busy -> is set high when the response to this command will be
-- followed by a busy signal.
--
-- NOTES/REVISIONS:
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Altera_UP_SD_Card_48_bit_Command_Generator is
generic (
-- Basic commands
COMMAND_0_GO_IDLE : STD_LOGIC_VECTOR(5 downto 0) := "000000";
COMMAND_2_ALL_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "000010";
COMMAND_3_SEND_RCA : STD_LOGIC_VECTOR(5 downto 0) := "000011";
COMMAND_4_SET_DSR : STD_LOGIC_VECTOR(5 downto 0) := "000100";
COMMAND_6_SWITCH_FUNCTION : STD_LOGIC_VECTOR(5 downto 0) := "000110";
COMMAND_7_SELECT_CARD : STD_LOGIC_VECTOR(5 downto 0) := "000111";
COMMAND_9_SEND_CSD : STD_LOGIC_VECTOR(5 downto 0) := "001001";
COMMAND_10_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "001010";
COMMAND_12_STOP_TRANSMISSION : STD_LOGIC_VECTOR(5 downto 0) := "001100";
COMMAND_13_SEND_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101";
COMMAND_15_GO_INACTIVE : STD_LOGIC_VECTOR(5 downto 0) := "001111";
-- Block oriented read/write/lock commands
COMMAND_16_SET_BLOCK_LENGTH : STD_LOGIC_VECTOR(5 downto 0) := "010000";
-- Block oriented read commands
COMMAND_17_READ_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "010001";
COMMAND_18_READ_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010010";
-- Block oriented write commands
COMMAND_24_WRITE_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "011000";
COMMAND_25_WRITE_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "011001";
COMMAND_27_PROGRAM_CSD : STD_LOGIC_VECTOR(5 downto 0) := "011011";
-- Block oriented write-protection commands
COMMAND_28_SET_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011100";
COMMAND_29_CLEAR_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011101";
COMMAND_30_SEND_PROTECTED_GROUPS : STD_LOGIC_VECTOR(5 downto 0) := "011110";
-- Erase commands
COMMAND_32_ERASE_BLOCK_START : STD_LOGIC_VECTOR(5 downto 0) := "100000";
COMMAND_33_ERASE_BLOCK_END : STD_LOGIC_VECTOR(5 downto 0) := "100001";
COMMAND_38_ERASE_SELECTED_GROUPS: STD_LOGIC_VECTOR(5 downto 0) := "100110";
-- Block lock commands
COMMAND_42_LOCK_UNLOCK : STD_LOGIC_VECTOR(5 downto 0) := "101010";
-- Command Type Settings
COMMAND_55_APP_CMD : STD_LOGIC_VECTOR(5 downto 0) := "110111";
COMMAND_56_GEN_CMD : STD_LOGIC_VECTOR(5 downto 0) := "111000";
-- Application Specific commands - must be preceeded with command 55.
ACOMMAND_6_SET_BUS_WIDTH : STD_LOGIC_VECTOR(5 downto 0) := "000110";
ACOMMAND_13_SD_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101";
ACOMMAND_22_SEND_NUM_WR_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010100";
ACOMMAND_23_SET_BLK_ERASE_COUNT : STD_LOGIC_VECTOR(5 downto 0) := "010101";
ACOMMAND_41_SEND_OP_CONDITION : STD_LOGIC_VECTOR(5 downto 0) := "101001";
ACOMMAND_42_SET_CLR_CARD_DETECT : STD_LOGIC_VECTOR(5 downto 0) := "101010";
ACOMMAND_51_SEND_SCR : STD_LOGIC_VECTOR(5 downto 0) := "110011";
-- First custom_command
FIRST_NON_PREDEFINED_COMMAND : STD_LOGIC_VECTOR(3 downto 0) := "1010"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_message_bit_out : in std_logic;
i_command_ID : in std_logic_vector(5 downto 0);
i_argument : in std_logic_vector(31 downto 0);
i_predefined_message : in std_logic_vector(3 downto 0);
i_generate : in std_logic;
i_DSR : in std_logic_vector(15 downto 0);
i_OCR : in std_logic_vector(31 downto 0);
i_RCA : in std_logic_vector(15 downto 0);
o_dataout : out std_logic;
o_message_done : out std_logic;
o_valid : out std_logic;
o_returning_ocr : out std_logic;
o_returning_cid : out std_logic;
o_returning_rca : out std_logic;
o_returning_csd : out std_logic;
o_returning_status : out std_logic;
o_data_read : out std_logic;
o_data_write : out std_logic;
o_wait_cmd_busy : out std_logic;
o_last_cmd_was_55 : out std_logic;
o_response_type : out std_logic_vector(2 downto 0)
);
end entity;
architecture rtl of Altera_UP_SD_Card_48_bit_Command_Generator is
component Altera_UP_SD_CRC7_Generator
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(6 downto 0)
);
end component;
-- Local wires
-- REGISTERED
signal counter : std_logic_vector(6 downto 0);
signal last_command_id : std_logic_vector(5 downto 0);
signal message_bits : std_logic_vector(39 downto 0);
signal last_command_sent_was_CMD55, valid : std_logic;
signal bit_to_send, sending_CRC, command_valid : std_logic;
signal returning_cid_reg, returning_rca_reg, returning_csd_reg, returning_dsr_reg, returning_ocr_reg, returning_status_reg : std_logic;
-- UNREGISTERED
signal temp_4_bits : std_logic_vector(3 downto 0);
signal message_done, CRC_generator_out, produce_next_bit : std_logic;
signal app_specific_valid, regular_command_valid : std_logic;
signal response_type, response_type_reg : std_logic_vector(2 downto 0);
signal cmd_argument : std_logic_vector(31 downto 0);
begin
-- This set of bits is necessary to allow the SD card to accept a VDD level for communication.
temp_4_bits <= "1111" when ((i_OCR(23) = '1') or (i_OCR(22) = '1') or (i_OCR(21) = '1') or (i_OCR(20) = '1')) else "0000";
-- Generate the bits to be sent to the SD card. These bits must pass through the CRC generator
-- to produce error checking code. The error checking code will follow the message. The message terminates with
-- a logic '1'. Total message length is 48 bits.
message_data_generator: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
message_bits <= (OTHERS => '0');
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
-- Store type of a response.
response_type_reg <= response_type;
-- Generate a message. Please note that the predefined messages are used for initialization.
-- If executed in sequence, they will initialize the SD card to work correctly. Only once these
-- instructions are completed can the data transfer begin.
case (i_predefined_message) is
when "0000" =>
-- Generate a predefined message - CMD0.
message_bits <= ("01" & COMMAND_0_GO_IDLE & "00000000000000000000000000000000");
when "0001" =>
-- Generate a predefined message - CMD55.
message_bits <= ("01" & COMMAND_55_APP_CMD & "0000000000000000" & "0000000000000000");
when "0010" =>
-- Generate a predefined message - ACMD41.
message_bits <= ("01" & ACOMMAND_41_SEND_OP_CONDITION & "0000" & temp_4_bits & "000" & i_OCR(20) & "00000000000000000000");
when "0011" =>
-- Generate a predefined message - CMD2.
message_bits <= ("01" & COMMAND_2_ALL_SEND_CID & "00000000000000000000000000000000");
when "0100" =>
-- Generate a predefined message - CMD3.
message_bits <= ("01" & COMMAND_3_SEND_RCA & "00000000000000000000000000000000");
when "0101" =>
-- Generate a predefined message - CMD9.
message_bits <= ("01" & COMMAND_9_SEND_CSD & i_RCA & "0000000000000000");
when "0110" =>
-- Generate a predefined message - CMD4.
message_bits <= ("01" & COMMAND_4_SET_DSR & i_DSR & "0000000000000000");
when "0111" =>
-- Generate a predefined message - CMD16. Set block length to 512.
message_bits <= ("01" & COMMAND_16_SET_BLOCK_LENGTH & "0000000000000000" & "0000001000000000" );
when "1000" =>
-- Generate a predefined message - CMD7. Select the card so we can access it's data.
message_bits <= ("01" & COMMAND_7_SELECT_CARD & i_RCA & "0000001000000000" );
when "1001" =>
-- Generate a predefined message - CMD13. Send SD card status.
message_bits <= ("01" & COMMAND_13_SEND_STATUS & i_RCA & "0000000000000000");
when others =>
-- Generate a custom message
message_bits <= ("01" & i_command_ID & cmd_argument);
end case;
else
-- Shift bits out as needed
if (produce_next_bit = '1') then
-- Shift message bits.
message_bits(39 downto 1) <= message_bits(38 downto 0);
message_bits(0) <= '0';
end if;
end if;
end if;
end if;
end process;
-- Generate command argument based on the command_ID. For most commands, the argument is user specified.
-- For some commands, it is necessary to send a particular SD Card register contents. Hence, these contents are
-- sent instead of the user data.
argument_generator: process (i_command_ID, last_command_sent_was_CMD55, i_generate, i_RCA, i_DSR, i_OCR, i_argument)
begin
cmd_argument <= i_argument;
if (i_generate = '1') then
case (i_command_ID) is
when COMMAND_4_SET_DSR =>
cmd_argument <= i_DSR & i_argument(15 downto 0);
when COMMAND_7_SELECT_CARD =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_9_SEND_CSD =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_10_SEND_CID =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_13_SEND_STATUS =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_15_GO_INACTIVE =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_55_APP_CMD =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when ACOMMAND_41_SEND_OP_CONDITION =>
if (last_command_sent_was_CMD55 = '1') then
cmd_argument <= i_OCR;
end if;
when others =>
cmd_argument <= i_argument;
end case;
end if;
end process;
-- Validate the message ID before sending it out.
command_validator: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
command_valid <= '0';
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
if (("0" & i_predefined_message) >= ("0" & FIRST_NON_PREDEFINED_COMMAND)) then
-- Check the custom message
if (last_command_sent_was_CMD55 = '1') then
-- Check the application specific messages
command_valid <= app_specific_valid;
else
-- Check the default messages.
command_valid <= regular_command_valid;
end if;
else
-- A command is valid if the message is predefined.
command_valid <= '1';
end if;
end if;
end if;
end if;
end process;
-- Registers that indicate that the command sent will return contents of a control register.
-- The contents of the response should therefore be stored in the appropriate register.
responses_with_control_regs: process(i_clock, i_reset_n, last_command_sent_was_CMD55, last_command_id, message_done)
begin
if (i_reset_n = '0') then
returning_ocr_reg <= '0';
returning_cid_reg <= '0';
returning_rca_reg <= '0';
returning_csd_reg <= '0';
returning_status_reg <= '0';
elsif (rising_edge(i_clock)) then
if (i_generate = '1') then
returning_ocr_reg <= '0';
returning_cid_reg <= '0';
returning_rca_reg <= '0';
returning_csd_reg <= '0';
returning_status_reg <= '0';
elsif (message_done = '1') then
-- OCR
if ((last_command_sent_was_CMD55 = '1') and (last_command_id = ACOMMAND_41_SEND_OP_CONDITION)) then
returning_ocr_reg <= '1';
end if;
-- CID
if (last_command_id = COMMAND_2_ALL_SEND_CID) then
returning_cid_reg <= '1';
end if;
-- RCA
if (last_command_id = COMMAND_3_SEND_RCA) then
returning_rca_reg <= '1';
end if;
-- CSD
if (last_command_id = COMMAND_9_SEND_CSD) then
returning_csd_reg <= '1';
end if;
-- Status
if ((last_command_sent_was_CMD55 = '0') and (last_command_id = COMMAND_13_SEND_STATUS)) then
returning_status_reg <= '1';
end if;
end if;
end if;
end process;
-- Count the number of bits sent using a counter.
sent_bit_counter: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter)
begin
if (i_reset_n = '0') then
counter <= (OTHERS => '0');
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
-- Reset the counter indicating the number of bits produced.
counter <= "0000000";
else
if (produce_next_bit = '1') then
-- Update the number of message bits sent.
counter <= counter + '1';
end if;
end if;
end if;
end if;
end process;
-- Select the source for the output data to be either the message data or the CRC bits.
source_selector: process(i_clock, i_reset_n, i_generate)
begin
if (i_reset_n = '0') then
sending_CRC <= '0';
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
-- Set sending CRC flag to 0.
sending_CRC <= '0';
else
-- If this is the last bit being sent, then bits that follow are the CRC bits.
if (counter = "0101000") then
sending_CRC <= '1';
end if;
end if;
end if;
end if;
end process;
-- When the message is sent, store its ID. In a special case when CMD55 is sent, the next command can be an application
-- specific command. We need to check those command IDs to verify the validity of the message.
CMD55_recognizer: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter, message_done, last_command_id)
begin
if (i_reset_n = '0') then
last_command_sent_was_CMD55 <= '0';
else
if (rising_edge(i_clock)) then
if (i_generate = '0') then
-- Store the ID of the current command.
if (produce_next_bit = '1') then
if (counter = "0000000") then
last_command_id <= message_bits(37 downto 32);
end if;
end if;
-- When message has been sent then check if it was CMD55.
if (message_done = '1') then
if (last_command_id = COMMAND_55_APP_CMD) then
last_command_sent_was_CMD55 <= '1';
else
last_command_sent_was_CMD55 <= '0';
end if;
end if;
end if;
end if;
end if;
end process;
-- Instantiate a CRC7 generator. Message bits will pass through it to create the CRC code for the message.
CRC7_Gen: Altera_UP_SD_CRC7_Generator PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_enable => i_message_bit_out,
i_shift => sending_CRC,
i_datain => message_bits(39),
o_dataout => CRC_generator_out
);
-- Define the source of the data produced by this module, depending on the counter value and the sending_CRC register state.
data_bit_register: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter)
begin
if (i_reset_n = '0') then
bit_to_send <= '1';
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
bit_to_send <= '1';
elsif (produce_next_bit = '1') then
-- Send data to output.
if (sending_CRC = '0') then
-- Send message bits
bit_to_send <= message_bits(39);
else
-- Send CRC bits
if ((counter = "0101111") or (counter = "0110000")) then
-- At the end of CRC bits put a 1.
bit_to_send <= '1';
else
bit_to_send <= CRC_generator_out;
end if;
end if;
end if;
end if;
end if;
end process;
-- Define conditions to produce the next message bit on the module output port o_dataout.
produce_next_bit <= i_message_bit_out and (not message_done);
-- Message is done when the last bit appears at the output.
message_done <= '1' when (counter = "0110001") else '0';
-- Check the application specific messages
app_specific_valid <= '1' when (
--(i_command_ID = COMMAND_0_GO_IDLE) or
(i_command_ID = COMMAND_2_ALL_SEND_CID) or
(i_command_ID = COMMAND_3_SEND_RCA) or
(i_command_ID = COMMAND_4_SET_DSR) or
--(i_command_ID = ACOMMAND_6_SET_BUS_WIDTH) or
--(i_command_ID = COMMAND_7_SELECT_CARD) or
(i_command_ID = COMMAND_9_SEND_CSD) or
(i_command_ID = COMMAND_10_SEND_CID) or
--(i_command_ID = COMMAND_12_STOP_TRANSMISSION) or
(i_command_ID = ACOMMAND_13_SD_STATUS) or
--(i_command_ID = COMMAND_15_GO_INACTIVE) or
--(i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or
(i_command_ID = COMMAND_17_READ_BLOCK) or
--(i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or
(i_command_ID = ACOMMAND_22_SEND_NUM_WR_BLOCKS) or
(i_command_ID = ACOMMAND_23_SET_BLK_ERASE_COUNT) or
(i_command_ID = COMMAND_24_WRITE_BLOCK) or
(i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or
(i_command_ID = COMMAND_27_PROGRAM_CSD) or
(i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or
(i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or
(i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or
(i_command_ID = COMMAND_32_ERASE_BLOCK_START) or
(i_command_ID = COMMAND_33_ERASE_BLOCK_END) or
(i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or
(i_command_ID = ACOMMAND_41_SEND_OP_CONDITION) or
(i_command_ID = ACOMMAND_42_SET_CLR_CARD_DETECT) or
(i_command_ID = ACOMMAND_51_SEND_SCR) or
(i_command_ID = COMMAND_55_APP_CMD) or
(i_command_ID = COMMAND_56_GEN_CMD)
)
else '0';
-- Check the default messages.
regular_command_valid <= '1' when (
-------------------------------------------------------
-- Disabled to prevent malfunction of the core
-------------------------------------------------------
--(i_command_ID = COMMAND_0_GO_IDLE) or
--(i_command_ID = COMMAND_6_SWITCH_FUNCTION) or
--(i_command_ID = COMMAND_7_SELECT_CARD) or
--(i_command_ID = COMMAND_15_GO_INACTIVE) or
--(i_command_ID = COMMAND_27_PROGRAM_CSD) or
--(i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or
--(i_command_ID = COMMAND_42_LOCK_UNLOCK) or
-------------------------------------------------------
(i_command_ID = COMMAND_2_ALL_SEND_CID) or
(i_command_ID = COMMAND_3_SEND_RCA) or
(i_command_ID = COMMAND_4_SET_DSR) or
(i_command_ID = COMMAND_9_SEND_CSD) or
(i_command_ID = COMMAND_10_SEND_CID) or
(i_command_ID = COMMAND_13_SEND_STATUS) or
-------------------------------------------------------
-- Disabled to simplify the circuit
-------------------------------------------------------
--(i_command_ID = COMMAND_12_STOP_TRANSMISSION) or
--(i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or
--(i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or
--(i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or
-------------------------------------------------------
(i_command_ID = COMMAND_17_READ_BLOCK) or
(i_command_ID = COMMAND_24_WRITE_BLOCK) or
(i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or
(i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or
(i_command_ID = COMMAND_32_ERASE_BLOCK_START) or
(i_command_ID = COMMAND_33_ERASE_BLOCK_END) or
(i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or
(i_command_ID = COMMAND_55_APP_CMD) or
(i_command_ID = COMMAND_56_GEN_CMD)
)
else '0';
response_type <= "001" when -- Wait for type 1 response when
(
(i_predefined_message = "0001") or
(i_predefined_message = "0111") or
(i_predefined_message = "1000") or
(i_predefined_message = "1001") or
((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and
((i_command_ID = COMMAND_6_SWITCH_FUNCTION) or
(i_command_ID = COMMAND_7_SELECT_CARD) or
(i_command_ID = COMMAND_12_STOP_TRANSMISSION) or
(i_command_ID = COMMAND_13_SEND_STATUS) or
(i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or
(i_command_ID = COMMAND_17_READ_BLOCK) or
(i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or
(i_command_ID = COMMAND_24_WRITE_BLOCK) or
(i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or
(i_command_ID = COMMAND_27_PROGRAM_CSD) or
(i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or
(i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or
(i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or
(i_command_ID = COMMAND_32_ERASE_BLOCK_START) or
(i_command_ID = COMMAND_33_ERASE_BLOCK_END) or
(i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or
(i_command_ID = COMMAND_42_LOCK_UNLOCK) or
(i_command_ID = COMMAND_55_APP_CMD) or
(i_command_ID = COMMAND_56_GEN_CMD) or
((last_command_sent_was_CMD55 = '1') and
((i_command_ID = ACOMMAND_6_SET_BUS_WIDTH) or
(i_command_ID = ACOMMAND_13_SD_STATUS) or
(i_command_ID = ACOMMAND_22_SEND_NUM_WR_BLOCKS) or
(i_command_ID = ACOMMAND_23_SET_BLK_ERASE_COUNT) or
(i_command_ID = ACOMMAND_42_SET_CLR_CARD_DETECT) or
(i_command_ID = ACOMMAND_51_SEND_SCR)))))
) else
"010" when -- Wait for type 2 response when
(
((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and
((i_command_ID = COMMAND_2_ALL_SEND_CID) or
(i_command_ID = COMMAND_9_SEND_CSD) or
(i_command_ID = COMMAND_10_SEND_CID))) or
(i_predefined_message = "0011") or
(i_predefined_message = "0101")
) else
"011" when -- Wait for type 3 response when
(
((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and (last_command_sent_was_CMD55 = '1') and (i_command_ID = ACOMMAND_41_SEND_OP_CONDITION)) or
(i_predefined_message = "0010")
) else
"110" when -- Wait for type 6 response when
(((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and (i_command_ID = COMMAND_3_SEND_RCA)) or
(i_predefined_message = "0100"))
else "000"; -- Otherwise there is no response pending.
-- Define circuit outputs
o_message_done <= message_done;
o_response_type <= response_type_reg;
o_valid <= command_valid;
o_dataout <= bit_to_send;
o_returning_ocr <= returning_ocr_reg;
o_returning_cid <= returning_cid_reg;
o_returning_rca <= returning_rca_reg;
o_returning_csd <= returning_csd_reg;
o_returning_status <= returning_status_reg;
o_data_read <= '1' when (last_command_id = COMMAND_17_READ_BLOCK) else '0';
o_data_write <= '1' when (last_command_id = COMMAND_24_WRITE_BLOCK) else '0';
o_last_cmd_was_55 <= last_command_sent_was_CMD55;
o_wait_cmd_busy <= '1' when (
(last_command_id = COMMAND_7_SELECT_CARD) or
(last_command_id = COMMAND_12_STOP_TRANSMISSION) or
(last_command_id = COMMAND_28_SET_WRITE_PROTECT) or
(last_command_id = COMMAND_29_CLEAR_WRITE_PROTECT) or
(last_command_id = COMMAND_38_ERASE_SELECTED_GROUPS))
else '0';
end rtl;

View File

@ -0,0 +1,518 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
----------------------------------------------------------------------------------------------------------------
-- This is an FSM that allows access to the SD Card IP core via the Avalon Interconnect.
--
-- This module takes a range of addresses on the Avalon Interconnect. Specifically:
-- - 0x00000000 to 0x000001ff
-- word addressable buffer space. The data to be written to the SD card as well
-- as data read from the SD card can be accessed here.
--
-- - 0x00000200 to 0x0000020f
-- 128-bit containing the Card Identification Number. The meaning of each bit is described in the
-- SD Card Physical Layer Specification Document.
--
-- - 0x00000210 to 0x0000021f
-- 128-bit register containing Card Specific Data. The meaning of each bit is described in the
-- SD Card Physical Layer Specification Document.
--
-- - 0x00000220 to 0x00000223
-- 32-bit register containing Operating Conditions Register. The meaning of each bit is described
-- in the SD Card Physical Layer Specification Document.
--
-- - 0x00000224 to 0x00000227
-- 32-bit register containing the Status Register. The meaning of each bit is described
-- in the SD Card Physical Layer Specification Document. However, if the card is not connected or the
-- status register could not be read from the SD card, this register will contain invalid data. In such
-- a case, wait for a card to be connected by checking the Auxiliary Status Register (UP Core Specific), and
-- a command 13 (SEND_STATUS) to update the contents of this register when possible. If a card is connected then
-- the Auxiliary Status Register can be polled until such a time that Status Register is valid, as the SD Card
-- interface circuit updates the status register approximately every 0.1 of a second, and after every command
-- is executed.
--
-- - 0x00000228 to 0x000000229
-- 16-bit register containing the Relative Card Address. This address uniquely identifies a card
-- connected to the SD Card slot.
--
-- - 0x0000022C to 0x00000022F
-- 32-bit register used to set the argument for a command to be sent to the SD Card.
--
-- - 0x00000230 to 0x000000231
-- 16-bit register used to send a command to an SD card. Once written, the interface will issue the
-- specified command. The meaning of each bit in this register is as follows:
-- - 0-5 - command index. This is a command index as per SD Card Physical Layer specification document.
-- - 6 - use most recent RCA. If this bit is set, the command argument will be replaced with the contents of
-- the Relative Card Address register, followed by 16 0s. For commands that require RCA to be sent as
-- an argument, this bit should be set and users will not need to specify RCA themselves.
-- - 7-15 - currently unused bits. They will be ignored.
-- NOTE: If a specified command is determined to be invalid, or the card is not connected to the SD Card socket,
-- then the SD Card interface circuit will not issue the command.
--
-- - 0x00000234 to 0x00000235
-- 16-bit register with Auxiliary Status Register. This is the Altera UP SD Card Interface status. The meaning of
-- the bits is as follows:
-- - 0 - last command valid - Set to '1' if the most recently user issued command was valid.
-- - 1 - card connected - Set to '1' if at present an SD card
-- - 2 - execution in progress - Set to '1' if the command recently issued is currently being executed. If true,
-- then the current state of SD Card registers should be ignored.
-- - 3 - status register valid - Set to '1' if the status register is valid.
-- - 4 - command timed out - Set to '1' if the last command timed out.
-- - 5 - crc failed - Set to '1' if the last command failed a CRC check.
-- - 6-15 - unused.
--
-- - 0x00000238 to 0x0000023B
-- 32-bit register containing the 32-bit R1 response message. Use it to test validity of the response. This register
-- will not store the response to SEND_STATUS command. Insteand, read the SD_status register at location 0x00000224.
--
-- Date: December 8, 2008
-- NOTES/REVISIONS:
-- December 17, 2008 - added R1 response register to the core. It is now available at 0x00000238.
----------------------------------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Altera_UP_SD_Card_Avalon_Interface is
generic (
ADDRESS_BUFFER : std_logic_vector(7 downto 0) := "00000000";
ADDRESS_CID : std_logic_vector(7 downto 0) := "10000000";
ADDRESS_CSD : std_logic_vector(7 downto 0) := "10000100";
ADDRESS_OCR : std_logic_vector(7 downto 0) := "10001000";
ADDRESS_SR : std_logic_vector(7 downto 0) := "10001001";
ADDRESS_RCA : std_logic_vector(7 downto 0) := "10001010";
ADDRESS_ARGUMENT : std_logic_vector(7 downto 0) := "10001011";
ADDRESS_COMMAND : std_logic_vector(7 downto 0) := "10001100";
ADDRESS_ASR : std_logic_vector(7 downto 0) := "10001101";
ADDRESS_R1 : std_logic_vector(7 downto 0) := "10001110"
);
port
(
-- Clock and Reset signals
i_clock : in STD_LOGIC;
i_reset_n : in STD_LOGIC; -- Asynchronous reset
-- Avalon Interconnect Signals
i_avalon_address : in STD_LOGIC_VECTOR(7 downto 0);
i_avalon_chip_select : in STD_LOGIC;
i_avalon_read : in STD_LOGIC;
i_avalon_write : in STD_LOGIC;
i_avalon_byteenable : in STD_LOGIC_VECTOR(3 downto 0);
i_avalon_writedata : in STD_LOGIC_VECTOR(31 downto 0);
o_avalon_readdata : out STD_LOGIC_VECTOR(31 downto 0);
o_avalon_waitrequest : out STD_LOGIC;
-- SD Card interface ports
b_SD_cmd : inout STD_LOGIC;
b_SD_dat : inout STD_LOGIC;
b_SD_dat3 : inout STD_LOGIC;
o_SD_clock : out STD_LOGIC
);
end entity;
architecture rtl of Altera_UP_SD_Card_Avalon_Interface is
component Altera_UP_SD_Card_Interface is
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
-- Command interface
b_SD_cmd : inout std_logic;
b_SD_dat : inout std_logic;
b_SD_dat3 : inout std_logic;
i_command_ID : in std_logic_vector(5 downto 0);
i_argument : in std_logic_vector(31 downto 0);
i_user_command_ready : in std_logic;
o_SD_clock : out std_logic;
o_card_connected : out std_logic;
o_command_completed : out std_logic;
o_command_valid : out std_logic;
o_command_timed_out : out std_logic;
o_command_crc_failed : out std_logic;
-- Buffer access
i_buffer_enable : in std_logic;
i_buffer_address : in std_logic_vector(7 downto 0);
i_buffer_write : in std_logic;
i_buffer_data_in : in std_logic_vector(15 downto 0);
o_buffer_data_out : out std_logic_vector(15 downto 0);
-- Show SD Card registers as outputs
o_SD_REG_card_identification_number : out std_logic_vector(127 downto 0);
o_SD_REG_relative_card_address : out std_logic_vector(15 downto 0);
o_SD_REG_operating_conditions_register : out std_logic_vector(31 downto 0);
o_SD_REG_card_specific_data : out std_logic_vector(127 downto 0);
o_SD_REG_status_register : out std_logic_vector(31 downto 0);
o_SD_REG_response_R1 : out std_logic_vector(31 downto 0);
o_SD_REG_status_register_valid : out std_logic
);
end component;
-- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state
-- of the switches.
type buffer_state_type is ( s_RESET, s_WAIT_REQUEST, s_READ_FIRST_WORD, s_READ_SECOND_WORD, s_RECEIVE_FIRST_WORD,
s_RECEIVE_SECOND_WORD, s_WR_READ_FIRST_WORD, s_WR_READ_FIRST_WORD_DELAY, s_WRITE_FIRST_BYTE, s_WRITE_FIRST_WORD,
s_WR_READ_SECOND_WORD, s_WR_READ_SECOND_WORD_DELAY, s_WRITE_SECOND_BYTE, s_WRITE_SECOND_WORD, s_WAIT_RELEASE);
type command_state_type is (s_RESET_CMD, s_WAIT_COMMAND, s_WAIT_RESPONSE, s_UPDATE_AUX_SR);
-- Register to hold the current state
signal current_state : buffer_state_type;
signal next_state : buffer_state_type;
signal current_cmd_state : command_state_type;
signal next_cmd_state : command_state_type;
-------------------
-- Local signals
-------------------
-- REGISTERED
signal auxiliary_status_reg : std_logic_vector(5 downto 0);
signal buffer_data_out_reg : std_logic_vector(31 downto 0);
signal buffer_data_in_reg : std_logic_vector(31 downto 0);
signal buffer_data_out : std_logic_vector(15 downto 0);
signal command_ID_reg : std_logic_vector( 5 downto 0);
signal argument_reg : std_logic_vector(31 downto 0);
signal avalon_address : std_logic_vector(7 downto 0);
signal avalon_byteenable : std_logic_vector(3 downto 0);
-- UNREGISTERED
signal buffer_address : std_logic_vector(7 downto 0);
signal buffer_data_in : std_logic_vector(15 downto 0);
signal SD_REG_card_identification_number : std_logic_vector(127 downto 0);
signal SD_REG_relative_card_address : std_logic_vector(15 downto 0);
signal SD_REG_operating_conditions_register : std_logic_vector(31 downto 0);
signal SD_REG_card_specific_data : std_logic_vector(127 downto 0);
signal SD_REG_status_register : std_logic_vector(31 downto 0);
signal SD_REG_response_R1 : std_logic_vector(31 downto 0);
signal command_ready, send_command_ready,
command_valid, command_completed, card_connected : std_logic;
signal status_reg_valid, argument_write : std_logic;
signal read_buffer_request, write_buffer_request, buffer_enable, buffer_write : std_logic;
signal command_timed_out, command_crc_failed : std_logic;
begin
-- Define state transitions for buffer interface.
state_transitions_buffer: process (current_state, read_buffer_request, write_buffer_request, i_avalon_byteenable, avalon_byteenable)
begin
case current_state is
when s_RESET =>
-- Reset local registers.
next_state <= s_WAIT_REQUEST;
when s_WAIT_REQUEST =>
-- Wait for a user command.
if (read_buffer_request = '1') then
next_state <= s_READ_FIRST_WORD;
elsif (write_buffer_request = '1') then
if ((i_avalon_byteenable(1) = '1') and (i_avalon_byteenable(0) = '1')) then
next_state <= s_WRITE_FIRST_WORD;
elsif ((i_avalon_byteenable(3) = '1') and (i_avalon_byteenable(2) = '1')) then
next_state <= s_WRITE_SECOND_WORD;
elsif ((i_avalon_byteenable(1) = '1') or (i_avalon_byteenable(0) = '1')) then
next_state <= s_WR_READ_FIRST_WORD;
elsif ((i_avalon_byteenable(3) = '1') or (i_avalon_byteenable(2) = '1')) then
next_state <= s_WR_READ_SECOND_WORD;
else
next_state <= s_WAIT_REQUEST;
end if;
else
next_state <= s_WAIT_REQUEST;
end if;
when s_READ_FIRST_WORD =>
-- Read first 16-bit word from the buffer
next_state <= s_READ_SECOND_WORD;
when s_READ_SECOND_WORD =>
-- Read second 16-bit word from the buffer
next_state <= s_RECEIVE_FIRST_WORD;
when s_RECEIVE_FIRST_WORD =>
-- Store first word read
next_state <= s_RECEIVE_SECOND_WORD;
when s_RECEIVE_SECOND_WORD =>
-- Store second word read
next_state <= s_WAIT_RELEASE;
-- The following states control writing to the buffer. To write a single byte it is necessary to read a
-- word and then write it back, changing only on of its bytes.
when s_WR_READ_FIRST_WORD =>
-- Read first 16-bit word from the buffer
next_state <= s_WR_READ_FIRST_WORD_DELAY;
when s_WR_READ_FIRST_WORD_DELAY =>
-- Wait a cycle
next_state <= s_WRITE_FIRST_BYTE;
when s_WRITE_FIRST_BYTE =>
-- Write one of the bytes in the given word into the memory.
if ((avalon_byteenable(3) = '1') and (avalon_byteenable(2) = '1')) then
next_state <= s_WRITE_SECOND_WORD;
elsif ((avalon_byteenable(3) = '1') or (avalon_byteenable(2) = '1')) then
next_state <= s_WR_READ_SECOND_WORD;
else
next_state <= s_WAIT_RELEASE;
end if;
when s_WR_READ_SECOND_WORD =>
-- Read second 16-bit word from the buffer
next_state <= s_WR_READ_SECOND_WORD_DELAY;
when s_WR_READ_SECOND_WORD_DELAY =>
-- Wait a cycle
next_state <= s_WRITE_SECOND_BYTE;
when s_WRITE_SECOND_BYTE =>
-- Write one of the bytes in the given word into the memory.
next_state <= s_WAIT_RELEASE;
-- Full word writing can be done without reading the word in the first place.
when s_WRITE_FIRST_WORD =>
-- Write the first word into memory
if ((avalon_byteenable(3) = '1') and (avalon_byteenable(2) = '1')) then
next_state <= s_WRITE_SECOND_WORD;
elsif ((avalon_byteenable(3) = '1') or (avalon_byteenable(2) = '1')) then
next_state <= s_WR_READ_SECOND_WORD;
else
next_state <= s_WAIT_RELEASE;
end if;
when s_WRITE_SECOND_WORD =>
-- Write the second word into memory
next_state <= s_WAIT_RELEASE;
when s_WAIT_RELEASE =>
-- if ((read_buffer_request = '1') or (write_buffer_request = '1')) then
-- next_state <= s_WAIT_RELEASE;
-- else
next_state <= s_WAIT_REQUEST;
-- end if;
when others =>
-- Make sure to start in the reset state if the circuit powers up in an odd state.
next_state <= s_RESET;
end case;
end process;
-- State Registers
buffer_state_regs: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
current_state <= s_RESET;
elsif(rising_edge(i_clock)) then
current_state <= next_state;
end if;
end process;
helper_regs: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
avalon_address <= (OTHERS => '0');
buffer_data_out_reg <= (OTHERS => '0');
buffer_data_in_reg <= (OTHERS => '0');
avalon_byteenable <= (OTHERS => '0');
elsif(rising_edge(i_clock)) then
if (current_state = s_WAIT_REQUEST) then
avalon_address <= i_avalon_address;
buffer_data_in_reg <= i_avalon_writedata;
avalon_byteenable <= i_avalon_byteenable;
end if;
if (current_state = s_RECEIVE_FIRST_WORD) then
buffer_data_out_reg(15 downto 0) <= buffer_data_out;
end if;
if (current_state = s_RECEIVE_SECOND_WORD) then
buffer_data_out_reg(31 downto 16) <= buffer_data_out;
end if;
end if;
end process;
-- FSM outputs
o_avalon_waitrequest <= (read_buffer_request or write_buffer_request) when (not (current_state = s_WAIT_RELEASE)) else '0';
buffer_address(7 downto 1) <= avalon_address(6 downto 0);
buffer_address(0) <= '1' when ( (current_state = s_READ_SECOND_WORD) or (current_state = s_WRITE_SECOND_WORD) or
(current_state = s_WR_READ_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else
'0';
buffer_enable <= '1' when ( (current_state = s_READ_FIRST_WORD) or (current_state = s_WR_READ_FIRST_WORD) or
(current_state = s_READ_SECOND_WORD) or (current_state = s_WR_READ_SECOND_WORD) or
(current_state = s_WRITE_FIRST_WORD) or (current_state = s_WRITE_FIRST_BYTE) or
(current_state = s_WRITE_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else
'0';
buffer_write <= '1' when ( (current_state = s_WRITE_FIRST_WORD) or (current_state = s_WRITE_FIRST_BYTE) or
(current_state = s_WRITE_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else
'0';
buffer_data_in <= (buffer_data_out(15 downto 8) & buffer_data_in_reg(7 downto 0)) when ((current_state = s_WRITE_FIRST_BYTE) and (avalon_byteenable(1 downto 0) = "01")) else
(buffer_data_in_reg(15 downto 8) & buffer_data_out(7 downto 0)) when ((current_state = s_WRITE_FIRST_BYTE) and (avalon_byteenable(1 downto 0) = "10")) else
(buffer_data_out(15 downto 8) & buffer_data_in_reg(23 downto 16)) when ((current_state = s_WRITE_SECOND_BYTE) and (avalon_byteenable(3 downto 2) = "01")) else
(buffer_data_in_reg(31 downto 24) & buffer_data_out(7 downto 0)) when ((current_state = s_WRITE_SECOND_BYTE) and (avalon_byteenable(3 downto 2) = "10")) else
buffer_data_in_reg(15 downto 0) when (current_state = s_WRITE_FIRST_WORD) else
buffer_data_in_reg(31 downto 16);
-- Glue Logic
read_buffer_request <= (not i_avalon_address(7)) and (i_avalon_chip_select) and (i_avalon_read);
write_buffer_request <= (not i_avalon_address(7)) and (i_avalon_chip_select) and (i_avalon_write);
-- Define state transitions for command interface.
state_transitions_cmd: process (current_cmd_state, command_completed, command_valid, command_ready)
begin
case current_cmd_state is
when s_RESET_CMD =>
-- Reset local registers.
next_cmd_state <= s_WAIT_COMMAND;
when s_WAIT_COMMAND =>
-- Wait for a user command.
if (command_ready = '1') then
next_cmd_state <= s_WAIT_RESPONSE;
else
next_cmd_state <= s_WAIT_COMMAND;
end if;
when s_WAIT_RESPONSE =>
-- Generate a predefined command to the SD card. This is the identification process for the SD card.
if ((command_completed = '1') or (command_valid = '0')) then
next_cmd_state <= s_UPDATE_AUX_SR;
else
next_cmd_state <= s_WAIT_RESPONSE;
end if;
when s_UPDATE_AUX_SR =>
-- Update the Auxiliary status register.
if (command_ready = '1') then
next_cmd_state <= s_UPDATE_AUX_SR;
else
next_cmd_state <= s_WAIT_COMMAND;
end if;
when others =>
-- Make sure to start in the reset state if the circuit powers up in an odd state.
next_cmd_state <= s_RESET_CMD;
end case;
end process;
-- State registers
cmd_state_regs: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
current_cmd_state <= s_RESET_CMD;
elsif(rising_edge(i_clock)) then
current_cmd_state <= next_cmd_state;
end if;
end process;
-- FSM outputs
send_command_ready <= '1' when ((current_cmd_state = s_WAIT_RESPONSE) or (current_cmd_state = s_UPDATE_AUX_SR)) else '0';
-- Glue logic
command_ready <= '1' when ( (i_avalon_chip_select = '1') and (i_avalon_write = '1') and
(i_avalon_address = ADDRESS_COMMAND)) else '0';
argument_write <= '1' when ((i_avalon_chip_select = '1') and (i_avalon_write = '1') and
(i_avalon_address = ADDRESS_ARGUMENT)) else '0';
-- Local Registers
local_regs: process(i_clock, i_reset_n, current_cmd_state, card_connected, command_valid, i_avalon_writedata, command_completed, command_ready)
begin
if (i_reset_n = '0') then
auxiliary_status_reg <= "000000";
command_ID_reg <= (OTHERS => '0');
elsif(rising_edge(i_clock)) then
-- AUX Status Register
if ((current_cmd_state = s_WAIT_RESPONSE) or (current_cmd_state = s_UPDATE_AUX_SR)) then
auxiliary_status_reg(2) <= not command_completed;
auxiliary_status_reg(4) <= command_timed_out;
auxiliary_status_reg(5) <= command_crc_failed;
end if;
auxiliary_status_reg(0) <= command_valid;
auxiliary_status_reg(1) <= card_connected;
auxiliary_status_reg(3) <= status_reg_valid;
-- Command
if (command_ready = '1') then
command_ID_reg <= i_avalon_writedata(5 downto 0);
end if;
end if;
end process;
argument_regs_processing: process(i_clock, i_reset_n, current_cmd_state, i_avalon_writedata, command_ready)
begin
if (i_reset_n = '0') then
argument_reg <= (OTHERS => '0');
elsif(rising_edge(i_clock)) then
-- Argument register
if ((command_ready = '1') and ( i_avalon_writedata(6) = '1')) then
argument_reg <= SD_REG_relative_card_address & "0000000000000000";
elsif (argument_write = '1') then
argument_reg <= i_avalon_writedata;
end if;
end if;
end process;
o_avalon_readdata <= buffer_data_out_reg when (not (current_state = s_WAIT_REQUEST)) else
SD_REG_card_identification_number(31 downto 0) when (i_avalon_address = ADDRESS_CID) else
SD_REG_card_identification_number(63 downto 32) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "01") else
SD_REG_card_identification_number(95 downto 64) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "10") else
SD_REG_card_identification_number(127 downto 96) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "11") else
SD_REG_card_specific_data(31 downto 0) when (i_avalon_address = ADDRESS_CSD) else
SD_REG_card_specific_data(63 downto 32) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "01") else
SD_REG_card_specific_data(95 downto 64) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "10") else
SD_REG_card_specific_data(127 downto 96) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "11") else
SD_REG_operating_conditions_register when (i_avalon_address = ADDRESS_OCR) else
SD_REG_status_register when (i_avalon_address = ADDRESS_SR) else
("0000000000000000" & SD_REG_relative_card_address)when (i_avalon_address = ADDRESS_RCA) else
argument_reg when (i_avalon_address = ADDRESS_ARGUMENT) else
("00000000000000000000000000" & command_ID_reg) when (i_avalon_address = ADDRESS_COMMAND) else
SD_REG_response_R1 when (i_avalon_address = ADDRESS_R1) else
("00000000000000000000000000" & auxiliary_status_reg);
-- Instantiated Components
SD_Card_Port: Altera_UP_SD_Card_Interface
port map
(
i_clock => i_clock,
i_reset_n => i_reset_n,
-- Command interface
b_SD_cmd => b_SD_cmd,
b_SD_dat => b_SD_dat,
b_SD_dat3 => b_SD_dat3,
i_command_ID => command_ID_reg,
i_argument => argument_reg,
i_user_command_ready => send_command_ready,
o_SD_clock => o_SD_clock,
o_card_connected => card_connected,
o_command_completed => command_completed,
o_command_valid => command_valid,
o_command_timed_out => command_timed_out,
o_command_crc_failed => command_crc_failed,
-- Buffer access
i_buffer_enable => buffer_enable,
i_buffer_address => buffer_address,
i_buffer_write => buffer_write,
i_buffer_data_in => buffer_data_in,
o_buffer_data_out => buffer_data_out,
-- Show SD Card registers as outputs
o_SD_REG_card_identification_number => SD_REG_card_identification_number,
o_SD_REG_relative_card_address => SD_REG_relative_card_address,
o_SD_REG_operating_conditions_register => SD_REG_operating_conditions_register,
o_SD_REG_card_specific_data => SD_REG_card_specific_data,
o_SD_REG_status_register => SD_REG_status_register,
o_SD_REG_response_R1 => SD_REG_response_R1,
o_SD_REG_status_register_valid => status_reg_valid
);
end rtl;

View File

@ -0,0 +1,382 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-------------------------------------------------------------------------------------
-- This module is a dual port memory block. It has a 16-bit port and a 1-bit port.
-- The 1-bit port is used to either send or receive data, while the 16-bit port is used
-- by Avalon interconnet to store and retrieve data.
--
-- NOTES/REVISIONS:
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Altera_UP_SD_Card_Buffer is
generic (
TIMEOUT : std_logic_vector(15 downto 0) := "1111111111111111";
BUSY_WAIT : std_logic_vector(15 downto 0) := "0000001111110000"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
-- 1 bit port to transmit and receive data on the data line.
i_begin : in std_logic;
i_sd_clock_pulse_trigger : in std_logic;
i_transmit : in std_logic;
i_1bit_data_in : in std_logic;
o_1bit_data_out : out std_logic;
o_operation_complete : out std_logic;
o_crc_passed : out std_logic;
o_timed_out : out std_logic;
o_dat_direction : out std_logic; -- set to 1 to send data, set to 0 to receive it.
-- 16 bit port to be accessed by a user circuit.
i_enable_16bit_port : in std_logic;
i_address_16bit_port : in std_logic_vector(7 downto 0);
i_write_16bit : in std_logic;
i_16bit_data_in : in std_logic_vector(15 downto 0);
o_16bit_data_out : out std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of Altera_UP_SD_Card_Buffer is
component Altera_UP_SD_CRC16_Generator
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_sync_reset : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(15 downto 0)
);
end component;
component Altera_UP_SD_Card_Memory_Block
PORT
(
address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
clock_a : IN STD_LOGIC ;
clock_b : IN STD_LOGIC ;
data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
enable_a : IN STD_LOGIC := '1';
enable_b : IN STD_LOGIC := '1';
wren_a : IN STD_LOGIC := '1';
wren_b : IN STD_LOGIC := '1';
q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0)
);
END component;
-- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state
-- of the switches.
type state_type is (s_RESET, s_WAIT_REQUEST, s_SEND_START_BIT, s_SEND_DATA, s_SEND_CRC, s_SEND_STOP, s_WAIT_BUSY, s_WAIT_BUSY_END,
s_WAIT_DATA_START, s_RECEIVING_LEADING_BITS, s_RECEIVING_DATA, s_RECEIVING_STOP_BIT, s_WAIT_DEASSERT);
-- Register to hold the current state
signal current_state : state_type;
signal next_state : state_type;
-- Local wires
-- REGISTERED
signal crc_counter : std_logic_vector(3 downto 0);
signal local_mode : std_logic;
signal dataout_1bit : std_logic;
signal bit_counter : std_logic_vector(2 downto 0);
signal byte_counter : std_logic_vector(8 downto 0);
signal shift_register : std_logic_vector(16 downto 0);
signal timeout_register : std_logic_vector(15 downto 0);
signal data_in_reg : std_logic;
-- UNREGISTERED
signal crc_out : std_logic_vector(15 downto 0);
signal single_bit_conversion, single_bit_out : std_logic_vector( 0 downto 0);
signal packet_mem_addr_b : std_logic_vector(11 downto 0);
signal local_reset, to_crc_generator, from_crc_generator, from_mem_1_bit, shift_crc,
recv_data, crc_generator_enable : std_logic;
begin
-- State transitions
state_transitions: process( current_state, i_begin, i_sd_clock_pulse_trigger, i_transmit, byte_counter,
bit_counter, crc_counter, i_1bit_data_in, timeout_register, data_in_reg)
begin
case (current_state) is
when s_RESET =>
-- Reset local registers and begin waiting for user input.
next_state <= s_WAIT_REQUEST;
when s_WAIT_REQUEST =>
-- Wait for i_begin to be high
if ((i_begin = '1') and (i_sd_clock_pulse_trigger = '1')) then
if (i_transmit = '1') then
next_state <= s_SEND_START_BIT;
else
next_state <= s_WAIT_DATA_START;
end if;
else
next_state <= s_WAIT_REQUEST;
end if;
when s_SEND_START_BIT =>
-- Send a 0 first, followed by 4096 bits of data, 16 CRC bits, and stop bit.
if (i_sd_clock_pulse_trigger = '1') then
next_state <= s_SEND_DATA;
else
next_state <= s_SEND_START_BIT;
end if;
when s_SEND_DATA =>
-- Send 4096 data bits
if ((i_sd_clock_pulse_trigger = '1') and (bit_counter = "000") and (byte_counter = "111111111")) then
next_state <= s_SEND_CRC;
else
next_state <= s_SEND_DATA;
end if;
when s_SEND_CRC =>
-- Send 16 CRC bits
if ((i_sd_clock_pulse_trigger = '1') and (crc_counter = "1111")) then
next_state <= s_SEND_STOP;
else
next_state <= s_SEND_CRC;
end if;
when s_SEND_STOP =>
-- Send stop bit.
if (i_sd_clock_pulse_trigger = '1') then
next_state <= s_WAIT_BUSY;
else
next_state <= s_SEND_STOP;
end if;
when s_WAIT_BUSY =>
-- After a write, wait for the busy signal. Do not return a done signal until you receive a busy signal.
-- If you do not and a long time expires, then the data must have been rejected (due to CRC error maybe).
-- In such a case return failure.
if ((i_sd_clock_pulse_trigger = '1') and (data_in_reg = '0') and (timeout_register = "0000000000010000")) then
next_state <= s_WAIT_BUSY_END;
else
if (timeout_register = BUSY_WAIT) then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_BUSY;
end if;
end if;
when s_WAIT_BUSY_END =>
if (i_sd_clock_pulse_trigger = '1') then
if (data_in_reg = '1') then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_BUSY_END;
end if;
else
next_state <= s_WAIT_BUSY_END;
end if;
when s_WAIT_DATA_START =>
-- Wait for the start bit
if ((i_sd_clock_pulse_trigger = '1') and (data_in_reg = '0')) then
next_state <= s_RECEIVING_LEADING_BITS;
else
if (timeout_register = TIMEOUT) then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_DATA_START;
end if;
end if;
when s_RECEIVING_LEADING_BITS =>
-- shift the start bit in as well as the next 16 bits. Once they are all in you can start putting data into memory.
if ((i_sd_clock_pulse_trigger = '1') and (crc_counter = "1111")) then
next_state <= s_RECEIVING_DATA;
else
next_state <= s_RECEIVING_LEADING_BITS;
end if;
when s_RECEIVING_DATA =>
-- Wait until all bits arrive.
if ((i_sd_clock_pulse_trigger = '1') and (bit_counter = "000") and (byte_counter = "111111111")) then
next_state <= s_RECEIVING_STOP_BIT;
else
next_state <= s_RECEIVING_DATA;
end if;
when s_RECEIVING_STOP_BIT =>
-- Wait until all bits arrive.
if (i_sd_clock_pulse_trigger = '1')then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_RECEIVING_STOP_BIT;
end if;
when s_WAIT_DEASSERT =>
if (i_begin = '1') then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_REQUEST;
end if;
when others =>
next_state <= s_RESET;
end case;
end process;
-- State registers
state_regs: process(i_clock, i_reset_n, local_reset)
begin
if (i_reset_n = '0') then
current_state <= s_RESET;
elsif (rising_edge(i_clock)) then
current_state <= next_state;
end if;
end process;
-- FSM outputs
to_crc_generator <= shift_register(16) when (current_state = s_RECEIVING_DATA) else
from_mem_1_bit when (current_state = s_SEND_DATA) else
'0';
shift_crc <= '1' when (current_state = s_SEND_CRC) else '0';
local_reset <= '1' when ((current_state = s_RESET) or (current_state = s_WAIT_REQUEST)) else '0';
recv_data <= '1' when (current_state = s_RECEIVING_DATA) else '0';
single_bit_conversion(0) <= shift_register(15);
crc_generator_enable <= '0' when (current_state = s_WAIT_DEASSERT) else i_sd_clock_pulse_trigger;
o_operation_complete <= '1' when (current_state = s_WAIT_DEASSERT) else '0';
o_dat_direction <= '1' when ( (current_state = s_SEND_START_BIT) or
(current_state = s_SEND_DATA) or
(current_state = s_SEND_CRC) or
(current_state = s_SEND_STOP))
else '0';
o_1bit_data_out <= dataout_1bit;
o_crc_passed <= '1' when ((crc_out = shift_register(16 downto 1)) and (shift_register(0) = '1')) else '0';
o_timed_out <= '1' when (timeout_register = TIMEOUT) else '0';
-- Local components
local_regs: process(i_clock, i_reset_n, local_reset)
begin
if (i_reset_n = '0') then
bit_counter <= (OTHERS => '1');
byte_counter <= (OTHERS => '0');
dataout_1bit <= '1';
crc_counter <= (OTHERS => '0');
shift_register <= (OTHERS => '0');
elsif (rising_edge(i_clock)) then
-- counters and serial output
if (local_reset = '1') then
bit_counter <= (OTHERS => '1');
byte_counter <= (OTHERS => '0');
dataout_1bit <= '1';
data_in_reg <= '1';
crc_counter <= (OTHERS => '0');
shift_register <= (OTHERS => '0');
elsif (i_sd_clock_pulse_trigger = '1') then
if ((not (current_state = s_RECEIVING_LEADING_BITS)) and (not (current_state = s_SEND_CRC))) then
crc_counter <= (OTHERS => '0');
else
if (not (crc_counter = "1111")) then
crc_counter <= crc_counter + '1';
end if;
end if;
if ((current_state = s_RECEIVING_DATA) or (current_state = s_SEND_DATA)) then
if (not ((bit_counter = "000") and (byte_counter = "111111111"))) then
if (bit_counter = "000") then
byte_counter <= byte_counter + '1';
bit_counter <= "111";
else
bit_counter <= bit_counter - '1';
end if;
end if;
end if;
-- Output data bit.
if (current_state = s_SEND_START_BIT) then
dataout_1bit <= '0';
elsif (current_state = s_SEND_DATA) then
dataout_1bit <= from_mem_1_bit;
elsif (current_state = s_SEND_CRC) then
dataout_1bit <= from_crc_generator;
else
dataout_1bit <= '1'; -- Stop bit.
end if;
-- Shift register to store the CRC bits once the message is received.
if ((current_state = s_RECEIVING_DATA) or
(current_state = s_RECEIVING_LEADING_BITS) or
(current_state = s_RECEIVING_STOP_BIT)) then
shift_register(16 downto 1) <= shift_register(15 downto 0);
shift_register(0) <= data_in_reg;
end if;
data_in_reg <= i_1bit_data_in;
end if;
end if;
end process;
-- Register holding the timeout value for data transmission.
timeout_reg: process(i_clock, i_reset_n, current_state, i_sd_clock_pulse_trigger)
begin
if (i_reset_n = '0') then
timeout_register <= (OTHERS => '0');
elsif (rising_edge(i_clock)) then
if ((current_state = s_SEND_STOP) or
(current_state = s_WAIT_REQUEST)) then
timeout_register <= (OTHERS => '0');
elsif (i_sd_clock_pulse_trigger = '1') then
-- Increment the timeout counter
if (((current_state = s_WAIT_DATA_START) or
(current_state = s_WAIT_BUSY)) and (not (timeout_register = TIMEOUT))) then
timeout_register <= timeout_register + '1';
end if;
end if;
end if;
end process;
-- Instantiated components.
crc16_checker: Altera_UP_SD_CRC16_Generator
port map
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_sync_reset => local_reset,
i_enable => crc_generator_enable,
i_shift => shift_crc,
i_datain => to_crc_generator,
o_dataout => from_crc_generator,
o_crcout => crc_out
);
packet_memory: Altera_UP_SD_Card_Memory_Block
PORT MAP
(
address_a => i_address_16bit_port,
address_b => packet_mem_addr_b,
clock_a => i_clock,
clock_b => i_clock,
data_a => i_16bit_data_in,
data_b => single_bit_conversion,
enable_a => i_enable_16bit_port,
enable_b => '1',
wren_a => i_write_16bit,
wren_b => recv_data,
q_a => o_16bit_data_out,
q_b => single_bit_out
);
from_mem_1_bit <= single_bit_out(0);
packet_mem_addr_b <= (byte_counter & bit_counter);
end rtl;

View File

@ -0,0 +1,80 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-------------------------------------------------------------------------------------
-- This module is a clock generator for the SD card interface. It takes a 50 MHz
-- clock as input and produces a clock signal that depends on the mode in which the
-- SD card interface is in. For a card identification mode a clock with a frequency of
-- 390.625 kHz is generated. For the data transfer mode, a clock with a frequency of
-- 12.5MHz is generated.
--
-- In addition, the generator produces a clock_mode value that identifies the frequency
-- of the o_SD_clock that is currently being generated.
--
-- NOTES/REVISIONS:
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Altera_UP_SD_Card_Clock is
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_enable : in std_logic;
i_mode : in std_logic; -- 0 for card identification mode, 1 for data transfer mode.
o_SD_clock : out std_logic;
o_clock_mode : out std_logic;
o_trigger_receive : out std_logic;
o_trigger_send : out std_logic
);
end entity;
architecture rtl of Altera_UP_SD_Card_Clock is
-- Local wires
-- REGISTERED
signal counter : std_logic_vector(6 downto 0);
signal local_mode : std_logic;
-- UNREGISTERED
begin
process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
counter <= (OTHERS => '0');
local_mode <= '0';
else
if (rising_edge(i_clock)) then
if (i_enable = '1') then
counter <= counter + '1';
end if;
-- Change the clock pulse only when at the positive edge of the clock
if (counter = "1000000") then
local_mode <= i_mode;
end if;
end if;
end if;
end process;
o_clock_mode <= local_mode;
o_SD_clock <= counter(6) when (local_mode = '0') else counter(1);
o_trigger_receive <= '1' when ((local_mode = '0') and (counter = "0111111")) else
((not counter(1)) and (counter(0))) when (local_mode = '1') else '0';
o_trigger_send <= '1' when ((local_mode = '0') and (counter = "0011111")) else
((counter(1)) and (counter(0))) when (local_mode = '1') else '0';
end rtl;

View File

@ -0,0 +1,347 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
----------------------------------------------------------------------------------------------------------------
-- This is an FSM that controls the SD Card interface circuitry.
--
-- On reset, the FSM will initiate a predefined set of commands in an attempt to connect to the SD Card.
-- When successful, it will allow commands to be issued to the SD Card, otherwise it will return a signal that
-- no card is present in the SD Card slot.
--
-- NOTES/REVISIONS:
----------------------------------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Altera_UP_SD_Card_Control_FSM is
generic (
PREDEFINED_COMMAND_GET_STATUS : STD_LOGIC_VECTOR(3 downto 0) := "1001"
);
port
(
-- Clock and Reset signals
i_clock : in STD_LOGIC;
i_reset_n : in STD_LOGIC;
-- FSM Inputs
i_user_command_ready : in std_logic;
i_response_received : in STD_LOGIC;
i_response_timed_out : in STD_LOGIC;
i_response_crc_passed : in STD_LOGIC;
i_command_sent : in STD_LOGIC;
i_powerup_busy_n : in STD_LOGIC;
i_clocking_pulse_enable : in std_logic;
i_current_clock_mode : in std_logic;
i_user_message_valid : in std_logic;
i_last_cmd_was_55 : in std_logic;
i_allow_partial_rw : in std_logic;
-- FSM Outputs
o_generate_command : out STD_LOGIC;
o_predefined_command_ID : out STD_LOGIC_VECTOR(3 downto 0);
o_receive_response : out STD_LOGIC;
o_drive_CMD_line : out STD_LOGIC;
o_SD_clock_mode : out STD_LOGIC; -- 0 means slow clock for card identification, 1 means fast clock for transfer mode.
o_resetting : out std_logic;
o_card_connected : out STD_LOGIC;
o_command_completed : out std_logic;
o_clear_response_register : out std_logic;
o_enable_clock_generator : out std_logic
);
end entity;
architecture rtl of Altera_UP_SD_Card_Control_FSM is
-- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state
-- of the switches.
type state_type is (s_RESET, s_WAIT_74_CYCLES, s_GENERATE_PREDEFINED_COMMAND, s_WAIT_PREDEFINED_COMMAND_TRANSMITTED, s_WAIT_PREDEFINED_COMMAND_RESPONSE,
s_GO_TO_NEXT_COMMAND, s_TOGGLE_CLOCK_FREQUENCY, s_AWAIT_USER_COMMAND, s_REACTIVATE_CLOCK,
s_GENERATE_COMMAND, s_SEND_COMMAND, s_WAIT_RESPONSE, s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE, s_WAIT_DEASSERT,
s_PERIODIC_STATUS_CHECK);
-- Register to hold the current state
signal current_state : state_type;
signal next_state : state_type;
-------------------
-- Local signals
-------------------
-- REGISTERED
signal SD_clock_mode, waiting_for_vdd_setup : std_logic;
signal id_sequence_step_index : std_logic_vector(3 downto 0);
signal delay_counter : std_logic_vector(6 downto 0);
signal periodic_status_check : std_logic_vector(23 downto 0);
-- UNREGISTERED
begin
-- Define state transitions.
state_transitions: process (current_state, i_command_sent, i_response_received, id_sequence_step_index,
i_response_timed_out, i_response_crc_passed, delay_counter, waiting_for_vdd_setup,
i_user_command_ready, i_clocking_pulse_enable, i_current_clock_mode,
i_user_message_valid, i_last_cmd_was_55, periodic_status_check)
begin
case current_state is
when s_RESET =>
-- Reset local registers and begin identification process.
next_state <= s_WAIT_74_CYCLES;
when s_WAIT_74_CYCLES =>
-- Wait 74 cycles before the card can be sent commands to.
if (delay_counter = "1001010") then
next_state <= s_GENERATE_PREDEFINED_COMMAND;
else
next_state <= s_WAIT_74_CYCLES;
end if;
when s_GENERATE_PREDEFINED_COMMAND =>
-- Generate a predefined command to the SD card. This is the identification process for the SD card.
next_state <= s_WAIT_PREDEFINED_COMMAND_TRANSMITTED;
when s_WAIT_PREDEFINED_COMMAND_TRANSMITTED =>
-- Send a predefined command to the SD card. This is the identification process for the SD card.
if (i_command_sent = '1') then
next_state <= s_WAIT_PREDEFINED_COMMAND_RESPONSE;
else
next_state <= s_WAIT_PREDEFINED_COMMAND_TRANSMITTED;
end if;
when s_WAIT_PREDEFINED_COMMAND_RESPONSE =>
-- Wait for a response from SD card.
if (i_response_received = '1') then
if (i_response_timed_out = '1') then
if (waiting_for_vdd_setup = '1') then
next_state <= s_GO_TO_NEXT_COMMAND;
else
next_state <= s_RESET;
end if;
else
if (i_response_crc_passed = '0') then
next_state <= s_GENERATE_PREDEFINED_COMMAND;
else
next_state <= s_GO_TO_NEXT_COMMAND;
end if;
end if;
else
next_state <= s_WAIT_PREDEFINED_COMMAND_RESPONSE;
end if;
when s_GO_TO_NEXT_COMMAND =>
-- Process the next command in the ID sequence.
if (id_sequence_step_index = PREDEFINED_COMMAND_GET_STATUS) then
next_state <= s_TOGGLE_CLOCK_FREQUENCY;
else
next_state <= s_GENERATE_PREDEFINED_COMMAND;
end if;
when s_TOGGLE_CLOCK_FREQUENCY =>
-- Now that the card has been initialized, increase the SD card clock frequency to 25MHz.
-- Wait for the clock generator to switch operating mode before proceeding further.
if (i_current_clock_mode = '1') then
next_state <= s_AWAIT_USER_COMMAND;
else
next_state <= s_TOGGLE_CLOCK_FREQUENCY;
end if;
when s_AWAIT_USER_COMMAND =>
-- Wait for the user to send a command to the SD card
if (i_user_command_ready = '1') then
next_state <= s_REACTIVATE_CLOCK;
else
-- Every 5 million cycles, or 0.1 of a second.
if (periodic_status_check = "010011000100101101000000") then
next_state <= s_PERIODIC_STATUS_CHECK;
else
next_state <= s_AWAIT_USER_COMMAND;
end if;
end if;
when s_PERIODIC_STATUS_CHECK =>
-- Update status every now and then.
next_state <= s_GENERATE_PREDEFINED_COMMAND;
when s_REACTIVATE_CLOCK =>
-- Activate the clock signal and wait 8 clock cycles.
if (delay_counter = "0001000") then
next_state <= s_GENERATE_COMMAND;
else
next_state <= s_REACTIVATE_CLOCK;
end if;
when s_GENERATE_COMMAND =>
-- Generate user command. If valid, proceed further. Otherwise, indicate that the command is invalid.
if (i_user_message_valid = '0') then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_SEND_COMMAND;
end if;
when s_SEND_COMMAND =>
-- Wait for the command to be sent.
if (i_command_sent = '1') then
next_state <= s_WAIT_RESPONSE;
else
next_state <= s_SEND_COMMAND;
end if;
when s_WAIT_RESPONSE =>
-- Wait for the SD card to respond.
if (i_response_received = '1') then
if (i_response_timed_out = '1') then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE;
end if;
else
next_state <= s_WAIT_RESPONSE;
end if;
when s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE =>
-- Wait for a positive clock edge before you disable the clock.
if (i_clocking_pulse_enable = '1') then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE;
end if;
when s_WAIT_DEASSERT =>
-- wait for the user to release command generation request.
if (i_user_command_ready = '1') then
next_state <= s_WAIT_DEASSERT;
else
if (i_last_cmd_was_55 = '1') then
next_state <= s_AWAIT_USER_COMMAND;
else
-- Send a get status command to obtain the result of sending the last command.
next_state <= s_GENERATE_PREDEFINED_COMMAND;
end if;
end if;
when others =>
-- Make sure to start in the reset state if the circuit powers up in an odd state.
next_state <= s_RESET;
end case;
end process;
-- State registers.
state_registers: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
current_state <= s_RESET;
elsif (rising_edge(i_clock)) then
current_state <= next_state;
end if;
end process;
-- Local FFs:
local_ffs:process ( i_clock, i_reset_n, i_powerup_busy_n, current_state,
id_sequence_step_index, i_response_received, i_response_timed_out,
i_allow_partial_rw)
begin
if (i_reset_n = '0') then
SD_clock_mode <= '0';
id_sequence_step_index <= (OTHERS => '0');
periodic_status_check <= (OTHERS => '0');
waiting_for_vdd_setup <= '0';
elsif (rising_edge(i_clock)) then
-- Set SD clock mode to 0 initially, thereby using a clock with frequency between 100 kHz and 400 kHz as
-- per SD card specifications. When the card is initialized change the clock to run at 25 MHz.
if (current_state = s_WAIT_DEASSERT) then
periodic_status_check <= (OTHERS => '0');
elsif (current_state = s_AWAIT_USER_COMMAND) then
periodic_status_check <= periodic_status_check + '1';
end if;
if (current_state = s_RESET) then
SD_clock_mode <= '0';
elsif (current_state = s_TOGGLE_CLOCK_FREQUENCY) then
SD_clock_mode <= '1';
end if;
-- Update the ID sequence step as needed.
if (current_state = s_RESET) then
id_sequence_step_index <= (OTHERS => '0');
elsif (current_state = s_GO_TO_NEXT_COMMAND) then
if ((i_powerup_busy_n = '0') and (id_sequence_step_index = "0010")) then
id_sequence_step_index <= "0001";
else
if (id_sequence_step_index = "0110") then
if (i_allow_partial_rw = '0') then
-- If partial read-write not allowed, then skip SET_BLK_LEN command - it will fail.
id_sequence_step_index <= "1000";
else
id_sequence_step_index <= "0111";
end if;
else
id_sequence_step_index <= id_sequence_step_index + '1';
end if;
end if;
elsif (current_state = s_WAIT_DEASSERT) then
if (i_last_cmd_was_55 = '0') then
-- After each command execute a get status command.
id_sequence_step_index <= PREDEFINED_COMMAND_GET_STATUS;
end if;
elsif (current_state = s_PERIODIC_STATUS_CHECK) then
id_sequence_step_index <= PREDEFINED_COMMAND_GET_STATUS;
end if;
-- Do not reset the card when SD card is having its VDD set up. Wait for it to respond, this may take some time.
if (id_sequence_step_index = "0010") then
waiting_for_vdd_setup <= '1';
elsif ((id_sequence_step_index = "0011") or (current_state = s_RESET)) then
waiting_for_vdd_setup <= '0';
end if;
end if;
end process;
-- Counter that counts to 74 to delay any commands.
initial_delay_counter: process(i_clock, i_reset_n, i_clocking_pulse_enable )
begin
if (i_reset_n = '0') then
delay_counter <= (OTHERS => '0');
elsif (rising_edge(i_clock)) then
if ((current_state = s_RESET) or (current_state = s_AWAIT_USER_COMMAND))then
delay_counter <= (OTHERS => '0');
elsif (((current_state = s_WAIT_74_CYCLES) or (current_state = s_REACTIVATE_CLOCK)) and
(i_clocking_pulse_enable = '1')) then
delay_counter <= delay_counter + '1';
end if;
end if;
end process;
-- FSM outputs.
o_SD_clock_mode <= SD_clock_mode;
o_generate_command <= '1' when ((current_state = s_GENERATE_PREDEFINED_COMMAND) or
(current_state = s_GENERATE_COMMAND))
else '0';
o_receive_response <= '1' when ((current_state = s_WAIT_PREDEFINED_COMMAND_RESPONSE) or
(current_state = s_WAIT_RESPONSE))
else '0';
o_drive_CMD_line <= '1' when ( (current_state = s_WAIT_PREDEFINED_COMMAND_TRANSMITTED) or
(current_state = s_SEND_COMMAND)) else '0';
o_predefined_command_ID <= id_sequence_step_index;
o_card_connected <= '1' when (id_sequence_step_index(3) = '1') and (
(id_sequence_step_index(2) = '1') or
(id_sequence_step_index(1) = '1') or
(id_sequence_step_index(0) = '1'))
else '0';
o_resetting <= '1' when (current_state = s_RESET) else '0';
o_command_completed <= '1' when (current_state = s_WAIT_DEASSERT) else '0';
o_enable_clock_generator <= '0' when (current_state = s_AWAIT_USER_COMMAND) else '1';
o_clear_response_register <= '1' when (current_state = s_REACTIVATE_CLOCK) else '0';
end rtl;

View File

@ -0,0 +1,518 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-------------------------------------------------------------------------------------
-- This module is an interface to the Secure Data Card. This module is intended to be
-- used with the DE2 board.
--
-- This version of the interface supports only a 1-bit serial data transfer. This
-- allows the interface to support a MultiMedia card as well.
--
-- NOTES/REVISIONS:
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Altera_UP_SD_Card_Interface is
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
-- Command interface
b_SD_cmd : inout std_logic;
b_SD_dat : inout std_logic;
b_SD_dat3 : inout std_logic;
i_command_ID : in std_logic_vector(5 downto 0);
i_argument : in std_logic_vector(31 downto 0);
i_user_command_ready : in std_logic;
o_SD_clock : out std_logic;
o_card_connected : out std_logic;
o_command_completed : out std_logic;
o_command_valid : out std_logic;
o_command_timed_out : out std_logic;
o_command_crc_failed : out std_logic;
-- Buffer access
i_buffer_enable : in std_logic;
i_buffer_address : in std_logic_vector(7 downto 0);
i_buffer_write : in std_logic;
i_buffer_data_in : in std_logic_vector(15 downto 0);
o_buffer_data_out : out std_logic_vector(15 downto 0);
-- Show SD Card registers as outputs
o_SD_REG_card_identification_number : out std_logic_vector(127 downto 0);
o_SD_REG_relative_card_address : out std_logic_vector(15 downto 0);
o_SD_REG_operating_conditions_register : out std_logic_vector(31 downto 0);
o_SD_REG_card_specific_data : out std_logic_vector(127 downto 0);
o_SD_REG_status_register : out std_logic_vector(31 downto 0);
o_SD_REG_response_R1 : out std_logic_vector(31 downto 0);
o_SD_REG_status_register_valid : out std_logic
);
end entity;
architecture rtl of Altera_UP_SD_Card_Interface is
component Altera_UP_SD_Card_Clock
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_enable : in std_logic;
i_mode : in std_logic; -- 0 for card identification mode, 1 for data transfer mode.
o_SD_clock : out std_logic;
o_clock_mode : out std_logic;
o_trigger_receive : out std_logic;
o_trigger_send : out std_logic
);
end component;
component Altera_UP_SD_CRC7_Generator
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(6 downto 0)
);
end component;
component Altera_UP_SD_CRC16_Generator
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(15 downto 0)
);
end component;
component Altera_UP_SD_Signal_Trigger
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_signal : in std_logic;
o_trigger : out std_logic
);
end component;
component Altera_UP_SD_Card_48_bit_Command_Generator
generic (
-- Basic commands
COMMAND_0_GO_IDLE : STD_LOGIC_VECTOR(5 downto 0) := "000000";
COMMAND_2_ALL_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "000010";
COMMAND_3_SEND_RCA : STD_LOGIC_VECTOR(5 downto 0) := "000011";
COMMAND_4_SET_DSR : STD_LOGIC_VECTOR(5 downto 0) := "000100";
COMMAND_6_SWITCH_FUNCTION : STD_LOGIC_VECTOR(5 downto 0) := "000110";
COMMAND_7_SELECT_CARD : STD_LOGIC_VECTOR(5 downto 0) := "000111";
COMMAND_9_SEND_CSD : STD_LOGIC_VECTOR(5 downto 0) := "001001";
COMMAND_10_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "001010";
COMMAND_12_STOP_TRANSMISSION : STD_LOGIC_VECTOR(5 downto 0) := "001100";
COMMAND_13_SEND_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101";
COMMAND_15_GO_INACTIVE : STD_LOGIC_VECTOR(5 downto 0) := "001111";
-- Block oriented read/write/lock commands
COMMAND_16_SET_BLOCK_LENGTH : STD_LOGIC_VECTOR(5 downto 0) := "010000";
-- Block oriented read commands
COMMAND_17_READ_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "010001";
COMMAND_18_READ_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010010";
-- Block oriented write commands
COMMAND_24_WRITE_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "011000";
COMMAND_25_WRITE_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "011001";
COMMAND_27_PROGRAM_CSD : STD_LOGIC_VECTOR(5 downto 0) := "011011";
-- Block oriented write-protection commands
COMMAND_28_SET_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011100";
COMMAND_29_CLEAR_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011101";
COMMAND_30_SEND_PROTECTED_GROUPS : STD_LOGIC_VECTOR(5 downto 0) := "011110";
-- Erase commands
COMMAND_32_ERASE_BLOCK_START : STD_LOGIC_VECTOR(5 downto 0) := "100000";
COMMAND_33_ERASE_BLOCK_END : STD_LOGIC_VECTOR(5 downto 0) := "100001";
COMMAND_38_ERASE_SELECTED_GROUPS : STD_LOGIC_VECTOR(5 downto 0) := "100110";
-- Block lock commands
COMMAND_42_LOCK_UNLOCK : STD_LOGIC_VECTOR(5 downto 0) := "101010";
-- Command Type Settings
COMMAND_55_APP_CMD : STD_LOGIC_VECTOR(5 downto 0) := "110111";
COMMAND_56_GEN_CMD : STD_LOGIC_VECTOR(5 downto 0) := "111000";
-- Application Specific commands - must be preceeded with command 55.
ACOMMAND_6_SET_BUS_WIDTH : STD_LOGIC_VECTOR(5 downto 0) := "000110";
ACOMMAND_13_SD_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101";
ACOMMAND_22_SEND_NUM_WR_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010100";
ACOMMAND_23_SET_BLK_ERASE_COUNT : STD_LOGIC_VECTOR(5 downto 0) := "010101";
ACOMMAND_41_SEND_OP_CONDITION : STD_LOGIC_VECTOR(5 downto 0) := "101001";
ACOMMAND_42_SET_CLR_CARD_DETECT : STD_LOGIC_VECTOR(5 downto 0) := "101010";
ACOMMAND_51_SEND_SCR : STD_LOGIC_VECTOR(5 downto 0) := "110011";
-- First custom_command
FIRST_NON_PREDEFINED_COMMAND : STD_LOGIC_VECTOR(3 downto 0) := "1010"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_message_bit_out : in std_logic;
i_command_ID : in std_logic_vector(5 downto 0);
i_argument : in std_logic_vector(31 downto 0);
i_predefined_message : in std_logic_vector(3 downto 0);
i_generate : in std_logic;
i_DSR : in std_logic_vector(15 downto 0);
i_OCR : in std_logic_vector(31 downto 0);
i_RCA : in std_logic_vector(15 downto 0);
o_dataout : out std_logic;
o_message_done : out std_logic;
o_valid : out std_logic;
o_returning_ocr : out std_logic;
o_returning_cid : out std_logic;
o_returning_rca : out std_logic;
o_returning_csd : out std_logic;
o_returning_status : out std_logic;
o_data_read : out std_logic;
o_data_write : out std_logic;
o_wait_cmd_busy : out std_logic;
o_last_cmd_was_55 : out std_logic;
o_response_type : out std_logic_vector(2 downto 0)
);
end component;
component Altera_UP_SD_Card_Response_Receiver
generic (
TIMEOUT : std_logic_vector(7 downto 0) := "00111000";
BUSY_WAIT : std_logic_vector(7 downto 0) := "00110000";
PROCESSING_DELAY : std_logic_vector(7 downto 0) := "00001000"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_begin : in std_logic;
i_scan_pulse : in std_logic;
i_datain : in std_logic;
i_wait_cmd_busy : in std_logic;
i_response_type : in std_logic_vector(2 downto 0);
o_data : out std_logic_vector(127 downto 0);
o_CRC_passed : out std_logic;
o_timeout : out std_logic;
o_done : out std_logic
);
end component;
component Altera_UP_SD_Card_Control_FSM
generic (
PREDEFINED_COMMAND_GET_STATUS : STD_LOGIC_VECTOR(3 downto 0) := "1001"
);
port
(
-- Clock and Reset signals
i_clock : in STD_LOGIC;
i_reset_n : in STD_LOGIC;
-- FSM Inputs
i_user_command_ready : in std_logic;
i_response_received : in STD_LOGIC;
i_response_timed_out : in STD_LOGIC;
i_response_crc_passed : in STD_LOGIC;
i_command_sent : in STD_LOGIC;
i_powerup_busy_n : in STD_LOGIC;
i_clocking_pulse_enable : in std_logic;
i_current_clock_mode : in std_logic;
i_user_message_valid : in std_logic;
i_last_cmd_was_55 : in std_logic;
i_allow_partial_rw : in std_logic;
-- FSM Outputs
o_generate_command : out STD_LOGIC;
o_predefined_command_ID : out STD_LOGIC_VECTOR(3 downto 0);
o_receive_response : out STD_LOGIC;
o_drive_CMD_line : out STD_LOGIC;
o_SD_clock_mode : out STD_LOGIC; -- 0 means slow clock for card identification, 1 means fast clock for transfer mode.
o_resetting : out std_logic;
o_card_connected : out STD_LOGIC;
o_command_completed : out std_logic;
o_clear_response_register : out std_logic;
o_enable_clock_generator : out std_logic
);
end component;
component Altera_UP_SD_Card_Buffer
generic (
TIMEOUT : std_logic_vector(15 downto 0) := "1111111111111111";
BUSY_WAIT : std_logic_vector(15 downto 0) := "0000001111110000"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
-- 1 bit port to transmit and receive data on the data line.
i_begin : in std_logic;
i_sd_clock_pulse_trigger : in std_logic;
i_transmit : in std_logic;
i_1bit_data_in : in std_logic;
o_1bit_data_out : out std_logic;
o_operation_complete : out std_logic;
o_crc_passed : out std_logic;
o_timed_out : out std_logic;
o_dat_direction : out std_logic; -- set to 1 to send data, set to 0 to receive it.
-- 16 bit port to be accessed by a user circuit.
i_enable_16bit_port : in std_logic;
i_address_16bit_port : in std_logic_vector(7 downto 0);
i_write_16bit : in std_logic;
i_16bit_data_in : in std_logic_vector(15 downto 0);
o_16bit_data_out : out std_logic_vector(15 downto 0)
);
end component;
-- Local wires
-- REGISTERED
signal sd_mode : std_logic;
-- SD Card Registers:
signal SD_REG_card_identification_number : std_logic_vector(127 downto 0);
signal SD_REG_response_R1 : std_logic_vector(31 downto 0);
signal SD_REG_relative_card_address : std_logic_vector(15 downto 0);
signal SD_REG_driver_stage_register : std_logic_vector(15 downto 0);
signal SD_REG_card_specific_data : std_logic_vector(127 downto 0);
signal SD_REG_operating_conditions_register : std_logic_vector(31 downto 0);
signal SD_REG_status_register : std_logic_vector(31 downto 0);
signal SD_REG_status_register_valid : std_logic;
-- UNREGISTERED
signal data_from_buffer : std_logic_vector(15 downto 0);
signal clock_generator_mode, enable_generator, SD_clock, create_message : std_logic;
signal send_next_bit, receive_next_bit : std_logic;
signal timed_out, response_done, passed_crc, begin_reading_response, resetting : std_logic;
signal returning_cid, returning_rca, returning_csd, returning_ocr : std_logic;
signal response_type : std_logic_vector(2 downto 0);
signal message_valid, messange_sent, data_to_CMD_line, CMD_tristate_buffer_enable, message_sent : std_logic;
signal predef_message_ID : std_logic_vector(3 downto 0);
signal receive_data_out : std_logic_vector(127 downto 0);
signal data_line_done, data_line_crc, data_line_timeout, data_line_direction, data_line_out : std_logic;
signal data_read, data_write, wait_cmd_busy, clear_response_register : std_logic;
signal response_done_combined : std_logic;
signal timeout_combined : std_logic;
signal crc_combined, allow_partial_rw : std_logic;
signal begin_data_line_operations, last_cmd_was_55, message_sent_trigger, returning_status : std_logic;
signal data_line_sd_clock_pulse_trigger : std_logic;
begin
-- Glue logic
SD_REG_driver_stage_register <= (OTHERS => '0');
response_done_combined <= (response_done and (not data_read) and (not data_write)) or
(response_done and (data_read or data_write) and data_line_done);
timeout_combined <= (timed_out and (not data_read) and (not data_write)) or
(timed_out and (data_read or data_write) and data_line_timeout);
crc_combined <= (passed_crc and (not data_read) and (not data_write)) or
(passed_crc and (data_read or data_write) and data_line_crc);
begin_data_line_operations <= (data_read and message_sent) or (data_write and response_done);
-- Partial read and write are only allowed when both bit 79 (partial read allowed) is high and
-- bit 21 (partial write allowed) is high.
allow_partial_rw <= SD_REG_card_specific_data(79) and SD_REG_card_specific_data(21);
-- SD Card control registers
control_regs: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
SD_REG_operating_conditions_register <= (OTHERS => '0');
SD_REG_card_identification_number <= (OTHERS => '0');
SD_REG_relative_card_address <= (OTHERS => '0');
SD_REG_card_specific_data <= (OTHERS => '0');
SD_REG_status_register <= (OTHERS => '0');
SD_REG_response_R1 <= (OTHERS => '1');
SD_REG_status_register_valid <= '0';
elsif (rising_edge(i_clock)) then
if ((response_type = "001") and (response_done = '1') and (returning_status = '0') and (clear_response_register = '0')) then
SD_REG_response_R1 <= receive_data_out(31 downto 0);
elsif (clear_response_register = '1') then
SD_REG_response_R1 <= (OTHERS => '1');
end if;
if (resetting = '1') then
SD_REG_operating_conditions_register <= (OTHERS => '0');
elsif ((returning_ocr = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_operating_conditions_register <= receive_data_out(31 downto 0);
end if;
if ((returning_cid = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_card_identification_number <= receive_data_out;
end if;
if ((returning_rca = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_relative_card_address <= receive_data_out(31 downto 16);
end if;
if ((returning_csd = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_card_specific_data <= receive_data_out;
end if;
if (message_sent_trigger = '1') then
SD_REG_status_register_valid <= '0';
elsif ((returning_status = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_status_register <= receive_data_out(31 downto 0);
SD_REG_status_register_valid <= '1';
end if;
end if;
end process;
-- Instantiated components
command_generator: Altera_UP_SD_Card_48_bit_Command_Generator PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_message_bit_out => send_next_bit,
i_command_ID => i_command_ID,
i_argument => i_argument,
i_predefined_message => predef_message_ID,
i_generate => create_message,
i_DSR => SD_REG_driver_stage_register,
i_OCR => SD_REG_operating_conditions_register,
i_RCA => SD_REG_relative_card_address,
o_dataout => data_to_CMD_line,
o_message_done => message_sent,
o_valid => message_valid,
o_returning_ocr => returning_ocr,
o_returning_cid => returning_cid,
o_returning_rca => returning_rca,
o_returning_csd => returning_csd,
o_returning_status => returning_status,
o_data_read => data_read,
o_data_write => data_write,
o_wait_cmd_busy => wait_cmd_busy,
o_last_cmd_was_55 => last_cmd_was_55,
o_response_type => response_type
);
response_receiver: Altera_UP_SD_Card_Response_Receiver PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_begin => begin_reading_response,
i_scan_pulse => receive_next_bit,
i_datain => b_SD_cmd,
i_response_type => response_type,
i_wait_cmd_busy => wait_cmd_busy,
o_data => receive_data_out,
o_CRC_passed => passed_crc,
o_timeout => timed_out,
o_done => response_done
);
control_FSM: Altera_UP_SD_Card_Control_FSM PORT MAP
(
-- Clock and Reset signals
i_clock => i_clock,
i_reset_n => i_reset_n,
-- FSM Inputs
i_user_command_ready => i_user_command_ready,
i_clocking_pulse_enable => receive_next_bit,
i_response_received => response_done_combined,
i_response_timed_out => timeout_combined,
i_response_crc_passed => crc_combined,
i_command_sent => message_sent,
i_powerup_busy_n => SD_REG_operating_conditions_register(31),
i_current_clock_mode => clock_generator_mode,
i_user_message_valid => message_valid,
i_last_cmd_was_55 => last_cmd_was_55,
i_allow_partial_rw => allow_partial_rw,
-- FSM Outputs
o_generate_command => create_message,
o_predefined_command_ID => predef_message_ID,
o_receive_response => begin_reading_response,
o_drive_CMD_line => CMD_tristate_buffer_enable,
o_SD_clock_mode => sd_mode, -- 0 means slow clock for card identification, 1 means fast clock for transfer mode.
o_card_connected => o_card_connected,
o_command_completed => o_command_completed,
o_resetting => resetting,
o_clear_response_register => clear_response_register,
o_enable_clock_generator => enable_generator
);
clock_generator: Altera_UP_SD_Card_Clock PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_mode => sd_mode,
i_enable => enable_generator,
o_SD_clock => SD_clock,
o_clock_mode => clock_generator_mode,
o_trigger_receive => receive_next_bit,
o_trigger_send => send_next_bit
);
SD_clock_pulse_trigger: Altera_UP_SD_Signal_Trigger PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_signal => message_sent,
o_trigger => message_sent_trigger
);
data_line: Altera_UP_SD_Card_Buffer
port map
(
i_clock => i_clock,
i_reset_n => i_reset_n,
-- 1 bit port to transmit and receive data on the data line.
i_begin => begin_data_line_operations,
i_sd_clock_pulse_trigger => data_line_sd_clock_pulse_trigger,
i_transmit => data_write,
i_1bit_data_in => b_SD_dat,
o_1bit_data_out => data_line_out,
o_operation_complete => data_line_done,
o_crc_passed => data_line_crc,
o_timed_out => data_line_timeout,
o_dat_direction => data_line_direction,
-- 16 bit port to be accessed by a user circuit.
i_enable_16bit_port => i_buffer_enable,
i_address_16bit_port => i_buffer_address,
i_write_16bit => i_buffer_write,
i_16bit_data_in => i_buffer_data_in,
o_16bit_data_out => data_from_buffer
);
data_line_sd_clock_pulse_trigger <= (data_write and send_next_bit) or ((not data_write) and receive_next_bit);
-- Buffer output registers.
buff_regs: process(i_clock, i_reset_n, data_from_buffer)
begin
if (i_reset_n = '0') then
o_buffer_data_out <= (OTHERS=> '0');
elsif (rising_edge(i_clock)) then
o_buffer_data_out <= data_from_buffer;
end if;
end process;
-- Circuit outputs.
o_command_valid <= message_valid;
o_command_timed_out <= timeout_combined;
o_command_crc_failed <= not crc_combined;
o_SD_clock <= SD_clock;
b_SD_cmd <= data_to_CMD_line when (CMD_tristate_buffer_enable = '1') else 'Z';
b_SD_dat <= data_line_out when (data_line_direction = '1') else 'Z';
b_SD_dat3 <= 'Z'; -- Set SD card to SD mode.
-- SD card registers
o_SD_REG_card_identification_number <= SD_REG_card_identification_number;
o_SD_REG_relative_card_address <= SD_REG_relative_card_address;
o_SD_REG_operating_conditions_register <= SD_REG_operating_conditions_register;
o_SD_REG_card_specific_data <= SD_REG_card_specific_data;
o_SD_REG_status_register <= SD_REG_status_register;
o_SD_REG_response_R1 <= SD_REG_response_R1;
o_SD_REG_status_register_valid <= SD_REG_status_register_valid;
end rtl;

View File

@ -0,0 +1,296 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-- megafunction wizard: %RAM: 2-PORT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altsyncram
-- ============================================================
-- File Name: Altera_UP_SD_Card_Memory_Block.vhd
-- Megafunction Name(s):
-- altsyncram
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 8.0 Build 215 05/29/2008 SJ Full Version
-- ************************************************************
--Copyright (C) 1991-2013 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY Altera_UP_SD_Card_Memory_Block IS
PORT
(
address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
clock_a : IN STD_LOGIC ;
clock_b : IN STD_LOGIC ;
data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
enable_a : IN STD_LOGIC := '1';
enable_b : IN STD_LOGIC := '1';
wren_a : IN STD_LOGIC := '1';
wren_b : IN STD_LOGIC := '1';
q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0)
);
END Altera_UP_SD_Card_Memory_Block;
ARCHITECTURE SYN OF altera_up_sd_card_memory_block IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (15 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (0 DOWNTO 0);
COMPONENT altsyncram
GENERIC (
address_reg_b : STRING;
clock_enable_input_a : STRING;
clock_enable_input_b : STRING;
clock_enable_output_a : STRING;
clock_enable_output_b : STRING;
indata_reg_b : STRING;
init_file : STRING;
init_file_layout : STRING;
intended_device_family : STRING;
lpm_type : STRING;
numwords_a : NATURAL;
numwords_b : NATURAL;
operation_mode : STRING;
outdata_aclr_a : STRING;
outdata_aclr_b : STRING;
outdata_reg_a : STRING;
outdata_reg_b : STRING;
power_up_uninitialized : STRING;
widthad_a : NATURAL;
widthad_b : NATURAL;
width_a : NATURAL;
width_b : NATURAL;
width_byteena_a : NATURAL;
width_byteena_b : NATURAL;
wrcontrol_wraddress_reg_b : STRING
);
PORT (
clocken0 : IN STD_LOGIC ;
clocken1 : IN STD_LOGIC ;
wren_a : IN STD_LOGIC ;
clock0 : IN STD_LOGIC ;
wren_b : IN STD_LOGIC ;
clock1 : IN STD_LOGIC ;
address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0)
);
END COMPONENT;
BEGIN
q_a <= sub_wire0(15 DOWNTO 0);
q_b <= sub_wire1(0 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
address_reg_b => "CLOCK1",
clock_enable_input_a => "NORMAL",
clock_enable_input_b => "NORMAL",
clock_enable_output_a => "BYPASS",
clock_enable_output_b => "BYPASS",
indata_reg_b => "CLOCK1",
init_file => "initial_data.mif",
init_file_layout => "PORT_A",
intended_device_family => "Cyclone II",
lpm_type => "altsyncram",
numwords_a => 256,
numwords_b => 4096,
operation_mode => "BIDIR_DUAL_PORT",
outdata_aclr_a => "NONE",
outdata_aclr_b => "NONE",
outdata_reg_a => "UNREGISTERED",
outdata_reg_b => "UNREGISTERED",
power_up_uninitialized => "FALSE",
widthad_a => 8,
widthad_b => 12,
width_a => 16,
width_b => 1,
width_byteena_a => 1,
width_byteena_b => 1,
wrcontrol_wraddress_reg_b => "CLOCK1"
)
PORT MAP (
clocken0 => enable_a,
clocken1 => enable_b,
wren_a => wren_a,
clock0 => clock_a,
wren_b => wren_b,
clock1 => clock_b,
address_a => address_a,
address_b => address_b,
data_a => data_a,
data_b => data_b,
q_a => sub_wire0,
q_b => sub_wire1
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
-- Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
-- Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
-- Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "1"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0"
-- Retrieval info: PRIVATE: CLRdata NUMERIC "0"
-- Retrieval info: PRIVATE: CLRq NUMERIC "0"
-- Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
-- Retrieval info: PRIVATE: CLRrren NUMERIC "0"
-- Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
-- Retrieval info: PRIVATE: CLRwren NUMERIC "0"
-- Retrieval info: PRIVATE: Clock NUMERIC "5"
-- Retrieval info: PRIVATE: Clock_A NUMERIC "0"
-- Retrieval info: PRIVATE: Clock_B NUMERIC "0"
-- Retrieval info: PRIVATE: ECC NUMERIC "0"
-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
-- Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1"
-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
-- Retrieval info: PRIVATE: MEMSIZE NUMERIC "4096"
-- Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "1"
-- Retrieval info: PRIVATE: MIFfilename STRING "initial_data.mif"
-- Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3"
-- Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3"
-- Retrieval info: PRIVATE: REGdata NUMERIC "1"
-- Retrieval info: PRIVATE: REGq NUMERIC "0"
-- Retrieval info: PRIVATE: REGrdaddress NUMERIC "0"
-- Retrieval info: PRIVATE: REGrren NUMERIC "0"
-- Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
-- Retrieval info: PRIVATE: REGwren NUMERIC "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
-- Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
-- Retrieval info: PRIVATE: VarWidth NUMERIC "1"
-- Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "16"
-- Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "1"
-- Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "16"
-- Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "1"
-- Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1"
-- Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: enable NUMERIC "1"
-- Retrieval info: PRIVATE: rden NUMERIC "0"
-- Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "NORMAL"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
-- Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1"
-- Retrieval info: CONSTANT: INIT_FILE STRING "initial_data.mif"
-- Retrieval info: CONSTANT: INIT_FILE_LAYOUT STRING "PORT_A"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256"
-- Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "4096"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT"
-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
-- Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED"
-- Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8"
-- Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "12"
-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "16"
-- Retrieval info: CONSTANT: WIDTH_B NUMERIC "1"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1"
-- Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1"
-- Retrieval info: USED_PORT: address_a 0 0 8 0 INPUT NODEFVAL address_a[7..0]
-- Retrieval info: USED_PORT: address_b 0 0 12 0 INPUT NODEFVAL address_b[11..0]
-- Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT NODEFVAL clock_a
-- Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL clock_b
-- Retrieval info: USED_PORT: data_a 0 0 16 0 INPUT NODEFVAL data_a[15..0]
-- Retrieval info: USED_PORT: data_b 0 0 1 0 INPUT NODEFVAL data_b[0..0]
-- Retrieval info: USED_PORT: enable_a 0 0 0 0 INPUT VCC enable_a
-- Retrieval info: USED_PORT: enable_b 0 0 0 0 INPUT VCC enable_b
-- Retrieval info: USED_PORT: q_a 0 0 16 0 OUTPUT NODEFVAL q_a[15..0]
-- Retrieval info: USED_PORT: q_b 0 0 1 0 OUTPUT NODEFVAL q_b[0..0]
-- Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT VCC wren_a
-- Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT VCC wren_b
-- Retrieval info: CONNECT: @data_a 0 0 16 0 data_a 0 0 16 0
-- Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0
-- Retrieval info: CONNECT: q_a 0 0 16 0 @q_a 0 0 16 0
-- Retrieval info: CONNECT: q_b 0 0 1 0 @q_b 0 0 1 0
-- Retrieval info: CONNECT: @address_a 0 0 8 0 address_a 0 0 8 0
-- Retrieval info: CONNECT: @data_b 0 0 1 0 data_b 0 0 1 0
-- Retrieval info: CONNECT: @address_b 0 0 12 0 address_b 0 0 12 0
-- Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0
-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0
-- Retrieval info: CONNECT: @clocken0 0 0 0 0 enable_a 0 0 0 0
-- Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0
-- Retrieval info: CONNECT: @clocken1 0 0 0 0 enable_b 0 0 0 0
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_waveforms.html TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@ -0,0 +1,308 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-------------------------------------------------------------------------------------
-- This module looks at the data on the CMD line and waits to receive a response.
-- It begins examining the data lines when the i_begin signal is asserted. It then
-- waits for a first '0'. It then proceeds to store as many bits as are required by
-- the response packet. Each message bit passes through the CRC7 circuit so that
-- the CRC check sum can be verified at the end of transmission. The circuit then produces
-- the o_data and o_CRC_passed outputs to indicate the message received and if the CRC
-- check passed.
--
-- If for some reason the requested response does not arrive within 56 clock cycles
-- then the circuit will produce a '1' on the o_timeout output. In such a case the
-- o_data should be ignored.
--
-- In case of a response that is not 001, 010, 011 or 110, the circuit expects
-- no response.
--
-- A signal o_done is asserted when the circuit has completed response retrieval. In
-- a case when a response is not expected, just wait for the CD Card to process the
-- command. This is done by waiting 8 (=PROCESSING_DELAY) clock cycles.
--
-- NOTES/REVISIONS:
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Altera_UP_SD_Card_Response_Receiver is
generic (
TIMEOUT : std_logic_vector(7 downto 0) := "00111000";
BUSY_WAIT : std_logic_vector(7 downto 0) := "00110000";
PROCESSING_DELAY : std_logic_vector(7 downto 0) := "00001000"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_begin : in std_logic;
i_scan_pulse : in std_logic;
i_datain : in std_logic;
i_wait_cmd_busy : in std_logic;
i_response_type : in std_logic_vector(2 downto 0);
o_data : out std_logic_vector(127 downto 0);
o_CRC_passed : out std_logic;
o_timeout : out std_logic;
o_done : out std_logic
);
end entity;
architecture rtl of Altera_UP_SD_Card_Response_Receiver is
component Altera_UP_SD_CRC7_Generator
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(6 downto 0)
);
end component;
-- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state
-- of the switches.
type state_type is (s_WAIT_BEGIN, s_WAIT_END, s_WAIT_PROCESSING_DELAY, s_WAIT_BUSY, s_WAIT_BUSY_END, s_WAIT_BEGIN_DEASSERT);
-- Register to hold the current state
signal current_state : state_type;
signal next_state : state_type;
-- Local wires
-- REGISTERED
signal registered_data_input : std_logic_vector(127 downto 0);
signal response_incoming : std_logic;
signal counter, timeout_counter : std_logic_vector(7 downto 0);
signal crc_shift, keep_reading_bits, shift_crc_bits : std_logic;
-- UNREGISTERED
signal limit, limit_minus_1 : std_logic_vector(7 downto 0);
signal check_crc : std_logic;
signal CRC_bits : std_logic_vector(6 downto 0);
signal start_reading_bits, operation_complete, enable_crc_unit : std_logic;
begin
-- Control FSM. Begin operation when i_begin is raised, then wait for the operation to end and i_begin to be deasserted.
state_regs: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
current_state <= s_WAIT_BEGIN;
elsif (rising_edge(i_clock)) then
current_state <= next_state;
end if;
end process;
state_transitions: process(current_state, i_begin, operation_complete, timeout_counter, i_wait_cmd_busy, i_scan_pulse, i_datain)
begin
case current_state is
when s_WAIT_BEGIN =>
if (i_begin = '1') then
next_state <= s_WAIT_END;
else
next_state <= s_WAIT_BEGIN;
end if;
when s_WAIT_END =>
if (operation_complete = '1') then
if (timeout_counter = TIMEOUT) then
next_state <= s_WAIT_BEGIN_DEASSERT;
else
next_state <= s_WAIT_PROCESSING_DELAY;
end if;
else
next_state <= s_WAIT_END;
end if;
when s_WAIT_PROCESSING_DELAY =>
if (timeout_counter = PROCESSING_DELAY) then
if (i_wait_cmd_busy = '1') then
next_state <= s_WAIT_BUSY;
else
next_state <= s_WAIT_BEGIN_DEASSERT;
end if;
else
next_state <= s_WAIT_PROCESSING_DELAY;
end if;
when s_WAIT_BUSY =>
if ((i_scan_pulse = '1') and (i_datain = '0')) then
next_state <= s_WAIT_BUSY_END;
else
if (timeout_counter = BUSY_WAIT) then
-- If the card did not become busy, then it would not have raised the optional busy signal.
-- In such a case, proceeed further as the command has finished correctly.
next_state <= s_WAIT_BEGIN_DEASSERT;
else
next_state <= s_WAIT_BUSY;
end if;
end if;
when s_WAIT_BUSY_END =>
if ((i_scan_pulse = '1') and (i_datain = '1')) then
next_state <= s_WAIT_BEGIN_DEASSERT;
else
next_state <= s_WAIT_BUSY_END;
end if;
when s_WAIT_BEGIN_DEASSERT =>
if (i_begin = '1') then
next_state <= s_WAIT_BEGIN_DEASSERT;
else
next_state <= s_WAIT_BEGIN;
end if;
when others =>
next_state <= s_WAIT_BEGIN;
end case;
end process;
-- Store the response as it appears on the i_datain line.
received_data_buffer: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
registered_data_input <= (OTHERS=>'0');
elsif (rising_edge(i_clock)) then
-- Only read new data and update the counter value when the scan pulse is high.
if (i_scan_pulse = '1') then
if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then
registered_data_input(127 downto 1) <= registered_data_input(126 downto 0);
registered_data_input(0) <= i_datain;
end if;
end if;
end if;
end process;
-- Counter received bits
data_read_counter: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
counter <= (OTHERS=>'0');
elsif (rising_edge(i_clock)) then
-- Reset he counter every time you being reading the response.
if (current_state = s_WAIT_BEGIN) then
counter <= (OTHERS => '0');
end if;
-- Update the counter value when the scan pulse is high.
if (i_scan_pulse = '1') then
if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then
counter <= counter + '1';
end if;
end if;
end if;
end process;
operation_complete <= '1' when (((counter = limit) and (not (limit = "00000000"))) or
(timeout_counter = TIMEOUT) or
((timeout_counter = PROCESSING_DELAY) and (limit = "00000000"))) else '0';
-- Count the number of scan pulses before the response is received. If the counter
-- exceeds TIMEOUT value, then an error must have occured when the SD card received a message.
timeout_counter_control: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
timeout_counter <= (OTHERS=>'0');
elsif (rising_edge(i_clock)) then
-- Reset the counter every time you begin reading the response.
if ((current_state = s_WAIT_BEGIN) or ((current_state = s_WAIT_END) and (operation_complete = '1') and (not (timeout_counter = TIMEOUT)))) then
timeout_counter <= (OTHERS => '0');
end if;
-- Update the counter value when the scan pulse is high.
if (i_scan_pulse = '1') then
if (((start_reading_bits = '0') and (keep_reading_bits = '0') and (current_state = s_WAIT_END) and (not (timeout_counter = TIMEOUT))) or
(current_state = s_WAIT_PROCESSING_DELAY) or (current_state = s_WAIT_BUSY)) then
timeout_counter <= timeout_counter + '1';
end if;
end if;
end if;
end process;
-- Enable data storing only after you see the first 0.
read_enable_logic: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
keep_reading_bits <= '0';
elsif (rising_edge(i_clock)) then
if (i_scan_pulse = '1') then
if ((start_reading_bits = '1') or ((keep_reading_bits = '1') and (not (counter = limit_minus_1)))) then
keep_reading_bits <= '1';
else
keep_reading_bits <= '0';
end if;
end if;
end if;
end process;
start_reading_bits <= '1' when ((current_state = s_WAIT_END) and (i_datain = '0') and
(counter = "00000000") and (not (limit = "00000000"))) else '0';
-- CRC7 checker.
crc_checker: Altera_UP_SD_CRC7_Generator PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_enable => enable_crc_unit,
i_shift => shift_crc_bits,
i_datain => registered_data_input(7),
o_crcout => CRC_bits
);
enable_crc_unit <= '1' when ((i_scan_pulse = '1') and (current_state = s_WAIT_END)) else '0';
-- Clear CRC7 registers before processing the response bits
crc_control_register: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
shift_crc_bits <= '1';
elsif (rising_edge(i_clock)) then
-- Reset he counter every time you being reading the response.
if (current_state = s_WAIT_BEGIN) then
-- clear the CRC7 contents before you process the next message.
shift_crc_bits <= '1';
end if;
-- Only read new data and update the counter value when the scan pulse is high.
if (i_scan_pulse = '1') then
if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then
if (counter = "00000111") then
-- Once the 7-bits of the CRC checker have been cleared you can process the message and
-- compute its CRC bits to verify the validity of the transmission.
shift_crc_bits <= '0';
end if;
end if;
end if;
end if;
end process;
-- Indicate the number of bits to expect in the response packet.
limit <= "00110000" when ((i_response_type = "001") or
(i_response_type = "011") or
(i_response_type = "110")) else
"10001000" when (i_response_type = "010") else
"00000000"; -- No response
limit_minus_1 <=
"00101111" when ((i_response_type = "001") or
(i_response_type = "011") or
(i_response_type = "110")) else
"10000111" when (i_response_type = "010") else
"00000000"; -- No response
check_crc <= '1' when ((i_response_type = "001") or (i_response_type = "110")) else '0';
-- Generate Circuit outputs
o_data <= (registered_data_input(127 downto 1) & '1') when (i_response_type = "010") else
(CONV_STD_LOGIC_VECTOR(0, 96) & registered_data_input(39 downto 8));
o_CRC_passed <= '1' when ((check_crc = '0') or
((registered_data_input(0) = '1') and (CRC_bits = registered_data_input(7 downto 1)))) else '0';
o_timeout <= '1' when (timeout_counter = TIMEOUT) else '0';
o_done <= '1' when (current_state = s_WAIT_BEGIN_DEASSERT) else '0';
end rtl;

View File

@ -0,0 +1,57 @@
-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
---------------------------------------------------------------------------------------
-- This module generates a trigger pulse every time it sees a transition
-- from 0 to 1 on signal i_signal.
--
-- NOTES/REVISIONS:
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Altera_UP_SD_Signal_Trigger is
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_signal : in std_logic;
o_trigger : out std_logic
);
end entity;
architecture rtl of Altera_UP_SD_Signal_Trigger is
-- Local wires
-- REGISTERED
signal local_reg : std_logic;
begin
process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
local_reg <= '0';
else
if (rising_edge(i_clock)) then
local_reg <= i_signal;
end if;
end if;
end process;
o_trigger <= '1' when ((local_reg = '0') and (i_signal = '1'))
else '0';
end rtl;

View File

@ -0,0 +1,99 @@
/* these test were created to show how to use the opencores I2C along with a driver found in
* the I2C_opencores component to talk to various components.
* This test example uses a littel daughter board from microtronix
* it has a I2c to parallel chip (PCA9554A) a EEPORM and real time clock.
* I chose not to impliment the real time clock.
* But you can see how the calls work
* There are only 4 functions associalted with the I2C driver
* I2C start - send start bit and address of the chip
* I2C_read - read data
* I2C_write. - write data
* how and when each of these get used is based on the device you
* are talking to.
* See the driver code for details of each function.
* */
#include <stdio.h>
#include "system.h"
#include "i2c_opencores.h"
int main()
{
int data;
int i;
// testing the PCA9554A paralle interface
// this writes a 5 to the leds and read the position of the dip switches.
printf(" tesing the PCA9554A interface the\n the LEDS should be at a 5 \n");
// address 0x38
// set the fequesncy that you want to run at
// most devices work at 100Khz some faster
I2C_init(I2CA_BASE,ALT_CPU_FREQ,100000);
I2C_init(I2CA_BASE,ALT_CPU_FREQ,100000);
// for the parallel io only the first 4 are output s
// the PCA9554A uses a command word right after the chip address word ( the start work)
I2C_start(I2CA_BASE,0x38,0);// chip address in write mode
I2C_write(I2CA_BASE,3,0); // write to register 3 command
I2C_write(I2CA_BASE,0xf0,1); // set the bottom 4 bits to outputs for the LEDs set the stop
// now right to the leds
I2C_start(I2CA_BASE,0x38,0); // address the chip in write mode
I2C_write(I2CA_BASE,1,0); // set command to the pca9554 to be output register
I2C_write(I2CA_BASE,5,1); // write the data to the output register and set the stop
//now read the dip switches
// first set the command to 0
I2C_start(I2CA_BASE,0x38,0); //address the chip in write mode
data = I2C_write(I2CA_BASE,0,0); // set command to read input register.
I2C_start(I2CA_BASE,0x38,1); //send start again but this time in read mode
data = I2C_read(I2CA_BASE,1); // read the input register and send stop
data = 0xff & (data >>4);
printf("dip switch 0x%x\n",data);
printf("\nNow writing and reading from the EEPROM\n");
//address 0x50-57
I2C_start(I2CA_BASE,0x50,0); // chip address in write mode
I2C_write(I2CA_BASE,0,0); // write to starting address of 0
// now write the data
for (i=0;i<7;i++) // can only write 8 bites at a time
{
I2C_write(I2CA_BASE,i,0); // writ the data
}
I2C_write(I2CA_BASE,i,1); // write last one with last flag
while ( I2C_start(I2CA_BASE,0x50,0)); // make sure the write is done be fore continuing.
// can ony burst 8 at a time.
I2C_write(I2CA_BASE,8,0); // write to starting address of 8
// now write the data
for (i=0;i<7;i++) // write the next 8 bytes
{
I2C_write(I2CA_BASE,i+8,0); //
}
I2C_write(I2CA_BASE,i+8,1); // write last one with last flag
while ( I2C_start(I2CA_BASE,0x50,0)); // make sure the write is done be fore continuing.
//now read the values
// first set the command to 0
I2C_start(I2CA_BASE,0x50,0); //set chip address and set to write/
I2C_write(I2CA_BASE,0,0); // set address to 0.
I2C_start(I2CA_BASE,0x50,1); //set chip address in read mode
for (i=0;i<15;i++)
{
data = I2C_read(I2CA_BASE,0); // memory array
printf("\tdata = 0x%x\n",data);
}
data = I2C_read(I2CA_BASE,1); // last memory read
printf("\tdata = 0x%x\n",data);
printf("Hello from Nios II!\n");
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,33 @@
#ifndef __I2C_OPENCORES_H__
#define __I2C_OPENCORES_H__
#include "alt_types.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void I2C_init(alt_u32 base,alt_u32 clk,alt_u32 speed);
int I2C_start(alt_u32 base, alt_u32 add, alt_u32 read);
alt_u32 I2C_read(alt_u32 base,alt_u32 last);
alt_u32 I2C_write(alt_u32 base,alt_u8 data, alt_u32 last);
alt_u32 SPI_read(alt_u32 base);
void SPI_write(alt_u32 base,alt_u8 data);
#define I2C_OK (0)
#define I2C_ACK (0)
#define I2C_NOACK (1)
#define I2C_ABITRATION_LOST (2)
#define I2C_OPENCORES_INSTANCE(name, dev) extern int alt_no_storage
#define I2C_OPENCORES_INIT(name, dev) while (0)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __I2C_OPENCORES_H__ */

View File

@ -0,0 +1,38 @@
# *******************************************************************************
# * *
# * License Agreement *
# * *
# * Copyright (c) 2003 Altera Corporation, San Jose, California, USA. *
# * All rights reserved. *
# * *
# * Permission is hereby granted, free of charge, to any person obtaining a *
# * copy of this software and associated documentation files (the "Software"), *
# * to deal in the Software without restriction, including without limitation *
# * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
# * and/or sell copies of the Software, and to permit persons to whom the *
# * Software is furnished to do so, subject to the following conditions: *
# * *
# * The above copyright notice and this permission notice shall be included in *
# * all copies or substantial portions of the Software. *
# * *
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
# * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
# * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
# * DEALINGS IN THE SOFTWARE. *
# * *
# * This agreement shall be governed in all respects by the laws of the State *
# * of California and by the laws of the United States of America. *
# * *
# * Altera does not recommend, suggest or require that this reference design *
# * file be used in conjunction or combination with any other product. *
# *******************************************************************************
# List all source files supplied by this component.
C_LIB_SRCS += i2c_opencores.c
ASM_LIB_SRCS +=

View File

@ -0,0 +1,206 @@
#include "alt_types.h"
#include "i2c_opencores_regs.h"
#include "i2c_opencores.h"
// #define I2C_DEBUG
//int I2C_init(alt_u32 base,alt_u32 clk, alt_u32 speed)
//int I2C_start(alt_u32 base, alt_u32 add, alt_u32 write);
//alt_u32 I2C_read(alt_u32 base);
//int I2C_write(alt_u32 base, alt_u8 data);
//int I2C_stop(alt_u32 base);
/* these functions are polled only. */
/* all functions wait until the I2C is done before exiting */
/****************************************************************
int I2C_init
This function inititlizes the prescalor for the scl
and then enables the core. This must be run before
any other i2c code is executed
inputs
base = the base address of the component
clk = freuqency of the clock driving this component ( in Hz)
speed = SCL speed ie 100K, 400K ... (in Hz)
15-OCT-07 initial release
*****************************************************************/
void I2C_init(alt_u32 base,alt_u32 clk,alt_u32 speed)
{
alt_u32 prescale = (clk/( 5 * speed))-1;
#ifdef I2C_DEBUG
printf(" Initializing I2C at 0x%x, \n\twith clock speed 0x%x \n\tand SCL speed 0x%x \n\tand prescale 0x%x\n",base,clk,speed,prescale);
#endif
IOWR_I2C_OPENCORES_CTR(base, 0x00); /* turn off the core*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_IACK_MSK); /* clearn any pening IRQ*/
IOWR_I2C_OPENCORES_PRERLO(base, (0xff & prescale)); /* load low presacle bit*/
IOWR_I2C_OPENCORES_PRERHI(base, (0xff & (prescale>>8))); /* load upper prescale bit */
IOWR_I2C_OPENCORES_CTR(base, I2C_OPENCORES_CTR_EN_MSK); /* turn on the core*/
}
/****************************************************************
int I2C_start
Sets the start bit and then sends the first byte which
is the address of the device + the write bit.
inputs
base = the base address of the component
add = address of I2C device
read = 1== read 0== write
return value
0 if address is acknowledged
1 if address was not acknowledged
15-OCT-07 initial release
*****************************************************************/
int I2C_start(alt_u32 base, alt_u32 add, alt_u32 read)
{
#ifdef I2C_DEBUG
printf(" Start I2C at 0x%x, \n\twith address 0x%x \n\tand read 0x%x \n\tand prescale 0x%x\n",base,add,read);
#endif
/* transmit the address shifted by one and the read/write bit*/
IOWR_I2C_OPENCORES_TXR(base, ((add<<1) + (0x1 & read)));
/* set start and write bits which will start the transaction*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_STA_MSK | I2C_OPENCORES_CR_WR_MSK );
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
/* now check to see if the address was acknowledged */
if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK)
{
#ifdef I2C_DEBUG
printf("\tNOACK\n");
#endif
return (I2C_NOACK);
}
else
{
#ifdef I2C_DEBUG
printf("\tACK\n");
#endif
return (I2C_ACK);
}
}
/****************************************************************
int I2C_read
assumes that any addressing and start
has already been done.
reads one byte of data from the slave. on the last read
we don't acknowldge and set the stop bit.
inputs
base = the base address of the component
last = on the last read there must not be a ack
return value
byte read back.
15-OCT-07 initial release
*****************************************************************/
alt_u32 I2C_read(alt_u32 base,alt_u32 last)
{
#ifdef I2C_DEBUG
printf(" Read I2C at 0x%x, \n\twith last0x%x\n",base,last);
#endif
if( last)
{
/* start a read and no ack and stop bit*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK |
I2C_OPENCORES_CR_NACK_MSK | I2C_OPENCORES_CR_STO_MSK);
}
else
{
/* start read*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK );
}
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
/* now read the data */
return (IORD_I2C_OPENCORES_RXR(base));
}
/****************************************************************
int I2C_write
assumes that any addressing and start
has already been done.
writes one byte of data from the slave.
If last is set the stop bit set.
inputs
base = the base address of the component
data = byte to write
last = on the last read there must not be a ack
return value
0 if address is acknowledged
1 if address was not acknowledged
15-OCT-07 initial release
*****************************************************************/
alt_u32 I2C_write(alt_u32 base,alt_u8 data, alt_u32 last)
{
#ifdef I2C_DEBUG
printf(" Read I2C at 0x%x, \n\twith data 0x%x,\n\twith last0x%x\n",base,data,last);
#endif
/* transmit the data*/
IOWR_I2C_OPENCORES_TXR(base, data);
if( last)
{
/* start a write with ack and stop bit*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK |
I2C_OPENCORES_CR_STO_MSK);
}
else
{
/* start write with ack */
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK );
}
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
/* now check to see if the address was acknowledged */
if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK)
{
#ifdef I2C_DEBUG
printf("\tNOACK\n");
#endif
return (I2C_NOACK);
}
else
{
#ifdef I2C_DEBUG
printf("\tACK\n");
#endif
return (I2C_ACK);
}
}
alt_u32 SPI_read(alt_u32 base)
{
/* start read*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK|I2C_OPENCORES_CR_NACK_MSK|I2C_OPENCORES_CR_SPIM_MSK );
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
/* now read the data */
return (IORD_I2C_OPENCORES_RXR(base));
}
void SPI_write(alt_u32 base,alt_u8 data) {
/* transmit the data*/
IOWR_I2C_OPENCORES_TXR(base, data);
/* start write */
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK|I2C_OPENCORES_CR_NACK_MSK|I2C_OPENCORES_CR_SPIM_MSK );
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
}

View File

@ -0,0 +1,621 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE rev.B2 compliant I2C Master bit-controller ////
//// ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: i2c_master_bit_ctrl.v,v 1.11 2004/05/07 11:02:26 rherveille Exp $
//
// $Date: 2004/05/07 11:02:26 $
// $Revision: 1.11 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: i2c_master_bit_ctrl.v,v $
// Revision 1.11 2004/05/07 11:02:26 rherveille
// Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit.
//
// Revision 1.10 2003/08/09 07:01:33 rherveille
// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
// Fixed a potential bug in the byte controller's host-acknowledge generation.
//
// Revision 1.9 2003/03/10 14:26:37 rherveille
// Fixed cmd_ack generation item (no bug).
//
// Revision 1.8 2003/02/05 00:06:10 rherveille
// Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles.
//
// Revision 1.7 2002/12/26 16:05:12 rherveille
// Small code simplifications
//
// Revision 1.6 2002/12/26 15:02:32 rherveille
// Core is now a Multimaster I2C controller
//
// Revision 1.5 2002/11/30 22:24:40 rherveille
// Cleaned up code
//
// Revision 1.4 2002/10/30 18:10:07 rherveille
// Fixed some reported minor start/stop generation timing issuess.
//
// Revision 1.3 2002/06/15 07:37:03 rherveille
// Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment.
//
// Revision 1.2 2001/11/05 11:59:25 rherveille
// Fixed wb_ack_o generation bug.
// Fixed bug in the byte_controller statemachine.
// Added headers.
//
//
/////////////////////////////////////
// Bit controller section
/////////////////////////////////////
//
// Translate simple commands into SCL/SDA transitions
// Each command has 5 states, A/B/C/D/idle
//
// start: SCL ~~~~~~~~~~\____
// SDA ~~~~~~~~\______
// x | A | B | C | D | i
//
// repstart SCL ____/~~~~\___
// SDA __/~~~\______
// x | A | B | C | D | i
//
// stop SCL ____/~~~~~~~~
// SDA ==\____/~~~~~
// x | A | B | C | D | i
//
//- write SCL ____/~~~~\____
// SDA ==X=========X=
// x | A | B | C | D | i
//
//- read SCL ____/~~~~\____
// SDA XXXX=====XXXX
// x | A | B | C | D | i
//
// Timing: Normal mode Fast mode
///////////////////////////////////////////////////////////////////////
// Fscl 100KHz 400KHz
// Th_scl 4.0us 0.6us High period of SCL
// Tl_scl 4.7us 1.3us Low period of SCL
// Tsu:sta 4.7us 0.6us setup time for a repeated start condition
// Tsu:sto 4.0us 0.6us setup time for a stop conditon
// Tbuf 4.7us 1.3us Bus free time between a stop and start condition
//
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
`include "i2c_master_defines.v"
module i2c_master_bit_ctrl(
clk, rst, nReset,
clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout,
scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen
);
//
// inputs & outputs
//
input clk;
input rst;
input nReset;
input ena; // core enable signal
input [15:0] clk_cnt; // clock prescale value
input [5:0] cmd;
output cmd_ack; // command complete acknowledge
reg cmd_ack;
output busy; // i2c bus busy
reg busy;
output al; // i2c bus arbitration lost
reg al;
input din;
output dout;
reg dout;
// I2C lines
input scl_i; // i2c clock line input
output scl_o; // i2c clock line output
output scl_oen; // i2c clock line output enable (active low)
reg scl_oen;
input sda_i; // i2c data line input
output sda_o; // i2c data line output
output sda_oen; // i2c data line output enable (active low)
reg sda_oen;
//
// variable declarations
//
reg sSCL, sSDA; // synchronized SCL and SDA inputs
reg dscl_oen; // delayed scl_oen
reg sda_chk; // check SDA output (Multi-master arbitration)
reg clk_en; // clock generation signals
wire slave_wait;
// reg [15:0] cnt = clk_cnt; // clock divider counter (simulation)
reg [15:0] cnt; // clock divider counter (synthesis)
// state machine variable
reg [24:0] c_state;
//
// module body
//
// whenever the slave is not ready it can delay the cycle by pulling SCL low
// delay scl_oen
always @(posedge clk)
dscl_oen <= #1 scl_oen;
assign slave_wait = dscl_oen && !sSCL;
// generate clk enable signal
always @(posedge clk or negedge nReset)
if(~nReset)
begin
cnt <= #1 16'h0;
clk_en <= #1 1'b1;
end
else if (rst)
begin
cnt <= #1 16'h0;
clk_en <= #1 1'b1;
end
else if ( ~|cnt || ~ena)
if (~slave_wait)
begin
cnt <= #1 clk_cnt;
clk_en <= #1 1'b1;
end
else
begin
cnt <= #1 cnt;
clk_en <= #1 1'b0;
end
else
begin
cnt <= #1 cnt - 16'h1;
clk_en <= #1 1'b0;
end
// generate bus status controller
reg dSCL, dSDA;
reg sta_condition;
reg sto_condition;
// synchronize SCL and SDA inputs
// reduce metastability risc
always @(posedge clk or negedge nReset)
if (~nReset)
begin
sSCL <= #1 1'b1;
sSDA <= #1 1'b1;
dSCL <= #1 1'b1;
dSDA <= #1 1'b1;
end
else if (rst)
begin
sSCL <= #1 1'b1;
sSDA <= #1 1'b1;
dSCL <= #1 1'b1;
dSDA <= #1 1'b1;
end
else
begin
sSCL <= #1 scl_i;
sSDA <= #1 sda_i;
dSCL <= #1 sSCL;
dSDA <= #1 sSDA;
end
// detect start condition => detect falling edge on SDA while SCL is high
// detect stop condition => detect rising edge on SDA while SCL is high
always @(posedge clk or negedge nReset)
if (~nReset)
begin
sta_condition <= #1 1'b0;
sto_condition <= #1 1'b0;
end
else if (rst)
begin
sta_condition <= #1 1'b0;
sto_condition <= #1 1'b0;
end
else
begin
sta_condition <= #1 ~sSDA & dSDA & sSCL;
sto_condition <= #1 sSDA & ~dSDA & sSCL;
end
// generate i2c bus busy signal
always @(posedge clk or negedge nReset)
if(!nReset)
busy <= #1 1'b0;
else if (rst)
busy <= #1 1'b0;
else
busy <= #1 (sta_condition | busy) & ~sto_condition;
// generate arbitration lost signal
// aribitration lost when:
// 1) master drives SDA high, but the i2c bus is low
// 2) stop detected while not requested
reg cmd_stop;
always @(posedge clk or negedge nReset)
if (~nReset)
cmd_stop <= #1 1'b0;
else if (rst)
cmd_stop <= #1 1'b0;
else if (clk_en)
cmd_stop <= #1 (cmd & (`I2C_CMD_STOP|`SPI_CMD_WRITE|`SPI_CMD_READ)) != 6'b000000;
always @(posedge clk or negedge nReset)
if (~nReset)
al <= #1 1'b0;
else if (rst)
al <= #1 1'b0;
else
al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop);
// generate dout signal (store SDA on rising edge of SCL)
always @(posedge clk)
if(sSCL & ~dSCL)
dout <= #1 sSDA;
// generate statemachine
// nxt_state decoder
parameter [24:0] idle = 25'b0_0000_0000_0000_0000_0000_0000;
parameter [24:0] start_a = 25'b0_0000_0000_0000_0000_0000_0001;
parameter [24:0] start_b = 25'b0_0000_0000_0000_0000_0000_0010;
parameter [24:0] start_c = 25'b0_0000_0000_0000_0000_0000_0100;
parameter [24:0] start_d = 25'b0_0000_0000_0000_0000_0000_1000;
parameter [24:0] start_e = 25'b0_0000_0000_0000_0000_0001_0000;
parameter [24:0] stop_a = 25'b0_0000_0000_0000_0000_0010_0000;
parameter [24:0] stop_b = 25'b0_0000_0000_0000_0000_0100_0000;
parameter [24:0] stop_c = 25'b0_0000_0000_0000_0000_1000_0000;
parameter [24:0] stop_d = 25'b0_0000_0000_0000_0001_0000_0000;
parameter [24:0] rd_a = 25'b0_0000_0000_0000_0010_0000_0000;
parameter [24:0] rd_b = 25'b0_0000_0000_0000_0100_0000_0000;
parameter [24:0] rd_c = 25'b0_0000_0000_0000_1000_0000_0000;
parameter [24:0] rd_d = 25'b0_0000_0000_0001_0000_0000_0000;
parameter [24:0] wr_a = 25'b0_0000_0000_0010_0000_0000_0000;
parameter [24:0] wr_b = 25'b0_0000_0000_0100_0000_0000_0000;
parameter [24:0] wr_c = 25'b0_0000_0000_1000_0000_0000_0000;
parameter [24:0] wr_d = 25'b0_0000_0001_0000_0000_0000_0000;
parameter [24:0] spi_rd_a = 25'b0_0000_0010_0000_0000_0000_0000;
parameter [24:0] spi_rd_b = 25'b0_0000_0100_0000_0000_0000_0000;
parameter [24:0] spi_rd_c = 25'b0_0000_1000_0000_0000_0000_0000;
parameter [24:0] spi_rd_d = 25'b0_0001_0000_0000_0000_0000_0000;
parameter [24:0] spi_wr_a = 25'b0_0010_0000_0000_0000_0000_0000;
parameter [24:0] spi_wr_b = 25'b0_0100_0000_0000_0000_0000_0000;
parameter [24:0] spi_wr_c = 25'b0_1000_0000_0000_0000_0000_0000;
parameter [24:0] spi_wr_d = 25'b1_0000_0000_0000_0000_0000_0000;
always @(posedge clk or negedge nReset)
if (!nReset)
begin
c_state <= #1 idle;
cmd_ack <= #1 1'b0;
scl_oen <= #1 1'b1;
sda_oen <= #1 1'b1;
sda_chk <= #1 1'b0;
end
else if (rst | al)
begin
c_state <= #1 idle;
cmd_ack <= #1 1'b0;
scl_oen <= #1 1'b1;
sda_oen <= #1 1'b1;
sda_chk <= #1 1'b0;
end
else
begin
cmd_ack <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle
if (clk_en)
case (c_state)
// idle state
idle:
begin
case (cmd)
`I2C_CMD_START:
c_state <= #1 start_a;
`I2C_CMD_STOP:
c_state <= #1 stop_a;
`I2C_CMD_WRITE:
c_state <= #1 wr_a;
`I2C_CMD_READ:
c_state <= #1 rd_a;
`SPI_CMD_WRITE:
c_state <= #1 spi_wr_a;
`SPI_CMD_READ:
c_state <= #1 spi_rd_a;
default:
c_state <= #1 idle;
endcase
scl_oen <= #1 scl_oen; // keep SCL in same state
sda_oen <= #1 sda_oen; // keep SDA in same state
sda_chk <= #1 1'b0; // don't check SDA output
end
// start
start_a:
begin
c_state <= #1 start_b;
scl_oen <= #1 scl_oen; // keep SCL in same state
sda_oen <= #1 1'b1; // set SDA high
sda_chk <= #1 1'b0; // don't check SDA output
end
start_b:
begin
c_state <= #1 start_c;
scl_oen <= #1 1'b1; // set SCL high
sda_oen <= #1 1'b1; // keep SDA high
sda_chk <= #1 1'b0; // don't check SDA output
end
start_c:
begin
c_state <= #1 start_d;
scl_oen <= #1 1'b1; // keep SCL high
sda_oen <= #1 1'b0; // set SDA low
sda_chk <= #1 1'b0; // don't check SDA output
end
start_d:
begin
c_state <= #1 start_e;
scl_oen <= #1 1'b1; // keep SCL high
sda_oen <= #1 1'b0; // keep SDA low
sda_chk <= #1 1'b0; // don't check SDA output
end
start_e:
begin
c_state <= #1 idle;
cmd_ack <= #1 1'b1;
scl_oen <= #1 1'b0; // set SCL low
sda_oen <= #1 1'b0; // keep SDA low
sda_chk <= #1 1'b0; // don't check SDA output
end
// stop
stop_a:
begin
c_state <= #1 stop_b;
scl_oen <= #1 1'b0; // keep SCL low
sda_oen <= #1 1'b0; // set SDA low
sda_chk <= #1 1'b0; // don't check SDA output
end
stop_b:
begin
c_state <= #1 stop_c;
scl_oen <= #1 1'b1; // set SCL high
sda_oen <= #1 1'b0; // keep SDA low
sda_chk <= #1 1'b0; // don't check SDA output
end
stop_c:
begin
c_state <= #1 stop_d;
scl_oen <= #1 1'b1; // keep SCL high
sda_oen <= #1 1'b0; // keep SDA low
sda_chk <= #1 1'b0; // don't check SDA output
end
stop_d:
begin
c_state <= #1 idle;
cmd_ack <= #1 1'b1;
scl_oen <= #1 1'b1; // keep SCL high
sda_oen <= #1 1'b1; // set SDA high
sda_chk <= #1 1'b0; // don't check SDA output
end
// read
rd_a:
begin
c_state <= #1 rd_b;
scl_oen <= #1 1'b0; // keep SCL low
sda_oen <= #1 1'b1; // tri-state SDA
sda_chk <= #1 1'b0; // don't check SDA output
end
rd_b:
begin
c_state <= #1 rd_c;
scl_oen <= #1 1'b1; // set SCL high
sda_oen <= #1 1'b1; // keep SDA tri-stated
sda_chk <= #1 1'b0; // don't check SDA output
end
rd_c:
begin
c_state <= #1 rd_d;
scl_oen <= #1 1'b1; // keep SCL high
sda_oen <= #1 1'b1; // keep SDA tri-stated
sda_chk <= #1 1'b0; // don't check SDA output
end
rd_d:
begin
c_state <= #1 idle;
cmd_ack <= #1 1'b1;
scl_oen <= #1 1'b0; // set SCL low
sda_oen <= #1 1'b1; // keep SDA tri-stated
sda_chk <= #1 1'b0; // don't check SDA output
end
// write
wr_a:
begin
c_state <= #1 wr_b;
scl_oen <= #1 1'b0; // keep SCL low
sda_oen <= #1 din; // set SDA
sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
end
wr_b:
begin
c_state <= #1 wr_c;
scl_oen <= #1 1'b1; // set SCL high
sda_oen <= #1 din; // keep SDA
sda_chk <= #1 1'b1; // check SDA output
end
wr_c:
begin
c_state <= #1 wr_d;
scl_oen <= #1 1'b1; // keep SCL high
sda_oen <= #1 din;
sda_chk <= #1 1'b1; // check SDA output
end
wr_d:
begin
c_state <= #1 idle;
cmd_ack <= #1 1'b1;
scl_oen <= #1 1'b0; // set SCL low
sda_oen <= #1 din;
sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
end
// read (last SPI bit)
spi_rd_a:
begin
c_state <= #1 spi_rd_b;
scl_oen <= #1 1'b0; // set SCL low
sda_oen <= #1 1'b1; // tri-state SDA
sda_chk <= #1 1'b0; // don't check SDA output
end
spi_rd_b:
begin
c_state <= #1 spi_rd_c;
scl_oen <= #1 1'b0; // keep SCL low
sda_oen <= #1 1'b1; // keep SDA tri-stated
sda_chk <= #1 1'b0; // don't check SDA output
end
spi_rd_c:
begin
c_state <= #1 spi_rd_d;
scl_oen <= #1 1'b1; // set SCL high
sda_oen <= #1 1'b1; // keep SDA tri-stated
sda_chk <= #1 1'b0; // don't check SDA output
end
spi_rd_d:
begin
c_state <= #1 idle;
cmd_ack <= #1 1'b1;
scl_oen <= #1 1'b1; // tri-state SCL
sda_oen <= #1 1'b1; // keep SDA tri-stated
sda_chk <= #1 1'b0; // don't check SDA output
end
// write (last SPI bit)
spi_wr_a:
begin
c_state <= #1 spi_wr_b;
scl_oen <= #1 1'b0; // set SCL low
sda_oen <= #1 1'b1; // keep SDA
sda_chk <= #1 1'b0; // don't check SDA output
end
spi_wr_b:
begin
c_state <= #1 spi_wr_c;
scl_oen <= #1 1'b0; // keep SCL low
sda_oen <= #1 din; // set SDA
sda_chk <= #1 1'b0; // don't check SDA output
end
spi_wr_c:
begin
c_state <= #1 spi_wr_d;
scl_oen <= #1 1'b1; // keep SCL high
sda_oen <= #1 din; // keep SDA
sda_chk <= #1 1'b0; // don't check SDA output
end
spi_wr_d:
begin
c_state <= #1 idle;
cmd_ack <= #1 1'b1;
scl_oen <= #1 1'b1; // tri-state SCL
sda_oen <= #1 1'b1; // tri-state SDA
sda_chk <= #1 1'b0; // don't check SDA output
end
default:
c_state <= #1 idle;
endcase
end
// assign scl and sda output (always gnd)
assign scl_o = 1'b0;
assign sda_o = 1'b0;
endmodule

View File

@ -0,0 +1,382 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE rev.B2 compliant I2C Master byte-controller ////
//// ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: i2c_master_byte_ctrl.v,v 1.7 2004/02/18 11:40:46 rherveille Exp $
//
// $Date: 2004/02/18 11:40:46 $
// $Revision: 1.7 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: i2c_master_byte_ctrl.v,v $
// Revision 1.7 2004/02/18 11:40:46 rherveille
// Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command.
//
// Revision 1.6 2003/08/09 07:01:33 rherveille
// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
// Fixed a potential bug in the byte controller's host-acknowledge generation.
//
// Revision 1.5 2002/12/26 15:02:32 rherveille
// Core is now a Multimaster I2C controller
//
// Revision 1.4 2002/11/30 22:24:40 rherveille
// Cleaned up code
//
// Revision 1.3 2001/11/05 11:59:25 rherveille
// Fixed wb_ack_o generation bug.
// Fixed bug in the byte_controller statemachine.
// Added headers.
//
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
`include "i2c_master_defines.v"
module i2c_master_byte_ctrl (
clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, spi_mode, din,
cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen );
//
// inputs & outputs
//
input clk; // master clock
input rst; // synchronous active high reset
input nReset; // asynchronous active low reset
input ena; // core enable signal
input [15:0] clk_cnt; // 4x SCL
// control inputs
input start;
input stop;
input read;
input write;
input ack_in;
input spi_mode;
input [7:0] din;
// status outputs
output cmd_ack;
reg cmd_ack;
output ack_out;
reg ack_out;
output i2c_busy;
output i2c_al;
output [7:0] dout;
// I2C signals
input scl_i;
output scl_o;
output scl_oen;
input sda_i;
output sda_o;
output sda_oen;
//
// Variable declarations
//
// statemachine
parameter [6:0] ST_IDLE = 7'b000_0000;
parameter [6:0] ST_START = 7'b000_0001;
parameter [6:0] ST_READ = 7'b000_0010;
parameter [6:0] ST_WRITE = 7'b000_0100;
parameter [6:0] ST_ACK = 7'b000_1000;
parameter [6:0] ST_STOP = 7'b001_0000;
parameter [6:0] ST_SPI_READ = 7'b010_0000;
parameter [6:0] ST_SPI_WRITE = 7'b100_0000;
// signals for bit_controller
reg [5:0] core_cmd;
reg core_txd;
wire core_ack, core_rxd;
// signals for shift register
reg [7:0] sr; //8bit shift register
reg shift, ld;
// signals for state machine
wire go;
reg [2:0] dcnt;
wire cnt_done;
//
// Module body
//
// hookup bit_controller
i2c_master_bit_ctrl bit_controller (
.clk ( clk ),
.rst ( rst ),
.nReset ( nReset ),
.ena ( ena ),
.clk_cnt ( clk_cnt ),
.cmd ( core_cmd ),
.cmd_ack ( core_ack ),
.busy ( i2c_busy ),
.al ( i2c_al ),
.din ( core_txd ),
.dout ( core_rxd ),
.scl_i ( scl_i ),
.scl_o ( scl_o ),
.scl_oen ( scl_oen ),
.sda_i ( sda_i ),
.sda_o ( sda_o ),
.sda_oen ( sda_oen )
);
// generate go-signal
assign go = (read | write | stop) & ~cmd_ack;
// assign dout output to shift-register
assign dout = sr;
// generate shift register
always @(posedge clk or negedge nReset)
if (!nReset)
sr <= #1 8'h0;
else if (rst)
sr <= #1 8'h0;
else if (ld)
sr <= #1 din;
else if (shift)
sr <= #1 {sr[6:0], core_rxd};
// generate counter
always @(posedge clk or negedge nReset)
if (!nReset)
dcnt <= #1 3'h0;
else if (rst)
dcnt <= #1 3'h0;
else if (ld)
dcnt <= #1 3'h7;
else if (shift)
dcnt <= #1 dcnt - 3'h1;
assign cnt_done = ~(|dcnt);
//
// state machine
//
reg [6:0] c_state; // synopsis enum_state
always @(posedge clk or negedge nReset)
if (!nReset)
begin
core_cmd <= #1 `I2C_CMD_NOP;
core_txd <= #1 1'b0;
shift <= #1 1'b0;
ld <= #1 1'b0;
cmd_ack <= #1 1'b0;
c_state <= #1 ST_IDLE;
ack_out <= #1 1'b0;
end
else if (rst | i2c_al)
begin
core_cmd <= #1 `I2C_CMD_NOP;
core_txd <= #1 1'b0;
shift <= #1 1'b0;
ld <= #1 1'b0;
cmd_ack <= #1 1'b0;
c_state <= #1 ST_IDLE;
ack_out <= #1 1'b0;
end
else
begin
// initially reset all signals
core_txd <= #1 sr[7];
shift <= #1 1'b0;
ld <= #1 1'b0;
cmd_ack <= #1 1'b0;
case (c_state) // synopsys full_case parallel_case
ST_IDLE:
if (go)
begin
if (start)
begin
c_state <= #1 ST_START;
core_cmd <= #1 `I2C_CMD_START;
end
else if (read)
begin
c_state <= #1 spi_mode ? ST_SPI_READ : ST_READ;
core_cmd <= #1 spi_mode ? `SPI_CMD_READ : `I2C_CMD_READ;
end
else if (write)
begin
c_state <= #1 spi_mode ? ST_SPI_WRITE : ST_WRITE;
core_cmd <= #1 spi_mode ? `SPI_CMD_WRITE : `I2C_CMD_WRITE;
end
else // stop
begin
c_state <= #1 ST_STOP;
core_cmd <= #1 `I2C_CMD_STOP;
end
ld <= #1 1'b1;
end
ST_START:
if (core_ack)
begin
if (read)
begin
c_state <= #1 ST_READ;
core_cmd <= #1 `I2C_CMD_READ;
end
else
begin
c_state <= #1 ST_WRITE;
core_cmd <= #1 `I2C_CMD_WRITE;
end
ld <= #1 1'b1;
end
ST_WRITE:
if (core_ack)
if (cnt_done)
begin
c_state <= #1 ST_ACK;
core_cmd <= #1 `I2C_CMD_READ;
end
else
begin
c_state <= #1 ST_WRITE; // stay in same state
core_cmd <= #1 `I2C_CMD_WRITE; // write next bit
shift <= #1 1'b1;
end
ST_READ:
if (core_ack)
begin
if (cnt_done)
begin
c_state <= #1 ST_ACK;
core_cmd <= #1 `I2C_CMD_WRITE;
end
else
begin
c_state <= #1 ST_READ; // stay in same state
core_cmd <= #1 `I2C_CMD_READ; // read next bit
end
shift <= #1 1'b1;
core_txd <= #1 ack_in;
end
ST_ACK:
if (core_ack)
begin
if (stop)
begin
c_state <= #1 ST_STOP;
core_cmd <= #1 `I2C_CMD_STOP;
end
else
begin
c_state <= #1 ST_IDLE;
core_cmd <= #1 `I2C_CMD_NOP;
// generate command acknowledge signal
cmd_ack <= #1 1'b1;
end
// assign ack_out output to bit_controller_rxd (contains last received bit)
ack_out <= #1 core_rxd;
core_txd <= #1 1'b1;
end
else
core_txd <= #1 ack_in;
ST_STOP:
if (core_ack)
begin
c_state <= #1 ST_IDLE;
core_cmd <= #1 `I2C_CMD_NOP;
// generate command acknowledge signal
cmd_ack <= #1 1'b1;
end
ST_SPI_WRITE:
if (core_ack)
if (cnt_done)
begin
c_state <= #1 ST_IDLE;
core_cmd <= #1 `I2C_CMD_NOP;
cmd_ack <= #1 1'b1;
end
else
begin
c_state <= #1 ST_SPI_WRITE; // stay in same state
core_cmd <= #1 `SPI_CMD_WRITE; // write next bit
shift <= #1 1'b1;
end
ST_SPI_READ:
if (core_ack)
begin
if (cnt_done)
begin
c_state <= #1 ST_IDLE;
core_cmd <= #1 `I2C_CMD_NOP;
cmd_ack <= #1 1'b1;
end
else
begin
c_state <= #1 ST_SPI_READ; // stay in same state
core_cmd <= #1 `SPI_CMD_READ; // read next bit
end
shift <= #1 1'b1;
core_txd <= #1 ack_in;
end
endcase
end
endmodule

View File

@ -0,0 +1,66 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE rev.B2 compliant I2C Master controller defines ////
//// ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: i2c_master_defines.v,v 1.3 2001/11/05 11:59:25 rherveille Exp $
//
// $Date: 2001/11/05 11:59:25 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: i2c_master_defines.v,v $
// Revision 1.3 2001/11/05 11:59:25 rherveille
// Fixed wb_ack_o generation bug.
// Fixed bug in the byte_controller statemachine.
// Added headers.
//
// I2C registers wishbone addresses
// bitcontroller states
`define I2C_CMD_NOP 6'b000000
`define I2C_CMD_START 6'b000001
`define I2C_CMD_STOP 6'b000010
`define I2C_CMD_WRITE 6'b000100
`define I2C_CMD_READ 6'b001000
`define SPI_CMD_WRITE 6'b010000
`define SPI_CMD_READ 6'b100000

View File

@ -0,0 +1,300 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE revB.2 compliant I2C Master controller Top-level ////
//// ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: i2c_master_top.v,v 1.10 2003/09/01 10:34:38 rherveille Exp $
//
// $Date: 2003/09/01 10:34:38 $
// $Revision: 1.10 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: i2c_master_top.v,v $
// Revision 1.10 2003/09/01 10:34:38 rherveille
// Fix a blocking vs. non-blocking error in the wb_dat output mux.
//
// Revision 1.9 2003/01/09 16:44:45 rherveille
// Fixed a bug in the Command Register declaration.
//
// Revision 1.8 2002/12/26 16:05:12 rherveille
// Small code simplifications
//
// Revision 1.7 2002/12/26 15:02:32 rherveille
// Core is now a Multimaster I2C controller
//
// Revision 1.6 2002/11/30 22:24:40 rherveille
// Cleaned up code
//
// Revision 1.5 2001/11/10 10:52:55 rherveille
// Changed PRER reset value from 0x0000 to 0xffff, conform specs.
//
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
`include "i2c_master_defines.v"
module i2c_master_top(
wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o,
wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o,
scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o );
// parameters
parameter ARST_LVL = 1'b0; // asynchronous reset level
//
// inputs & outputs
//
// wishbone signals
input wb_clk_i; // master clock input
input wb_rst_i; // synchronous active high reset
input arst_i; // asynchronous reset
input [2:0] wb_adr_i; // lower address bits
input [7:0] wb_dat_i; // databus input
output [7:0] wb_dat_o; // databus output
input wb_we_i; // write enable input
input wb_stb_i; // stobe/core select signal
input wb_cyc_i; // valid bus cycle input
output wb_ack_o; // bus cycle acknowledge output
output wb_inta_o; // interrupt request signal output
reg [7:0] wb_dat_o;
reg wb_ack_o;
reg wb_inta_o;
// I2C signals
// i2c clock line
input scl_pad_i; // SCL-line input
output scl_pad_o; // SCL-line output (always 1'b0)
output scl_padoen_o; // SCL-line output enable (active low)
// i2c data line
input sda_pad_i; // SDA-line input
output sda_pad_o; // SDA-line output (always 1'b0)
output sda_padoen_o; // SDA-line output enable (active low)
//
// variable declarations
//
// registers
reg [15:0] prer; // clock prescale register
reg [ 7:0] ctr; // control register
reg [ 7:0] txr; // transmit register
wire [ 7:0] rxr; // receive register
reg [ 7:0] cr; // command register
wire [ 7:0] sr; // status register
// done signal: command completed, clear command register
wire done;
// core enable signal
wire core_en;
wire ien;
// status register signals
wire irxack;
reg rxack; // received aknowledge from slave
reg tip; // transfer in progress
reg irq_flag; // interrupt pending flag
wire i2c_busy; // bus busy (start signal detected)
wire i2c_al; // i2c bus arbitration lost
reg al; // status register arbitration lost bit
//
// module body
//
// generate internal reset
wire rst_i = arst_i ^ ARST_LVL;
// generate wishbone signals
wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i;
// generate acknowledge output signal
always @(posedge wb_clk_i)
wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored
// assign DAT_O
always @(posedge wb_clk_i)
begin
case (wb_adr_i) // synopsis full_case parallel_case
3'b000: wb_dat_o <= #1 prer[ 7:0];
3'b001: wb_dat_o <= #1 prer[15:8];
3'b010: wb_dat_o <= #1 ctr;
3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr)
3'b100: wb_dat_o <= #1 sr; // write is command register (cr)
3'b101: wb_dat_o <= #1 txr;
3'b110: wb_dat_o <= #1 cr;
3'b111: wb_dat_o <= #1 0; // reserved
endcase
end
// generate registers
always @(posedge wb_clk_i or negedge rst_i)
if (!rst_i)
begin
prer <= #1 16'hffff;
ctr <= #1 8'h0;
txr <= #1 8'h0;
end
else if (wb_rst_i)
begin
prer <= #1 16'hffff;
ctr <= #1 8'h0;
txr <= #1 8'h0;
end
else
if (wb_wacc)
case (wb_adr_i) // synopsis full_case parallel_case
3'b000 : prer [ 7:0] <= #1 wb_dat_i;
3'b001 : prer [15:8] <= #1 wb_dat_i;
3'b010 : ctr <= #1 wb_dat_i;
3'b011 : txr <= #1 wb_dat_i;
endcase
// generate command register (special case)
always @(posedge wb_clk_i or negedge rst_i)
if (~rst_i)
cr <= #1 8'h0;
else if (wb_rst_i)
cr <= #1 8'h0;
else if (wb_wacc)
begin
if (core_en & (wb_adr_i == 3'b100) )
cr <= #1 wb_dat_i;
end
else
begin
if (done | i2c_al)
begin
cr[7:4] <= #1 4'h0; // clear command bits when done
cr[2] <= #1 1'b0; // or when aribitration lost
end
cr[1] <= #1 1'b0; // reserved bit
cr[0] <= #1 1'b0; // clear IRQ_ACK bit
end
// decode command register
wire sta = cr[7];
wire sto = cr[6];
wire rd = cr[5];
wire wr = cr[4];
wire ack = cr[3];
wire spi = cr[2];
wire iack = cr[0];
// decode control register
assign core_en = ctr[7];
assign ien = ctr[6];
// hookup byte controller block
i2c_master_byte_ctrl byte_controller (
.clk ( wb_clk_i ),
.rst ( wb_rst_i ),
.nReset ( rst_i ),
.ena ( core_en ),
.clk_cnt ( prer ),
.start ( sta ),
.stop ( sto ),
.read ( rd ),
.write ( wr ),
.ack_in ( ack ),
.spi_mode ( spi ),
.din ( txr ),
.cmd_ack ( done ),
.ack_out ( irxack ),
.dout ( rxr ),
.i2c_busy ( i2c_busy ),
.i2c_al ( i2c_al ),
.scl_i ( scl_pad_i ),
.scl_o ( scl_pad_o ),
.scl_oen ( scl_padoen_o ),
.sda_i ( sda_pad_i ),
.sda_o ( sda_pad_o ),
.sda_oen ( sda_padoen_o )
);
// status register block + interrupt request signal
always @(posedge wb_clk_i or negedge rst_i)
if (!rst_i)
begin
al <= #1 1'b0;
rxack <= #1 1'b0;
tip <= #1 1'b0;
irq_flag <= #1 1'b0;
end
else if (wb_rst_i)
begin
al <= #1 1'b0;
rxack <= #1 1'b0;
tip <= #1 1'b0;
irq_flag <= #1 1'b0;
end
else
begin
al <= #1 i2c_al | (al & ~sta);
rxack <= #1 irxack;
tip <= #1 (rd | wr);
irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated
end
// generate interrupt request signals
always @(posedge wb_clk_i or negedge rst_i)
if (!rst_i)
wb_inta_o <= #1 1'b0;
else if (wb_rst_i)
wb_inta_o <= #1 1'b0;
else
wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set)
// assign status register bits
assign sr[7] = rxack;
assign sr[6] = i2c_busy;
assign sr[5] = al;
assign sr[4:2] = 3'h0; // reserved
assign sr[1] = tip;
assign sr[0] = irq_flag;
endmodule

View File

@ -0,0 +1,72 @@
//
// fixed for 9.1 jan 21 2010 cruben
//
`include "timescale.v"
`include "i2c_master_defines.v"
module i2c_opencores
(
wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o,
wb_we_i, wb_stb_i, /*wb_cyc_i,*/ wb_ack_o, wb_inta_o,
scl_pad_io, sda_pad_io
);
// Common bus signals
input wb_clk_i; // WISHBONE clock
input wb_rst_i; // WISHBONE reset
// Slave signals
input [2:0] wb_adr_i; // WISHBONE address input
input [7:0] wb_dat_i; // WISHBONE data input
output [7:0] wb_dat_o; // WISHBONE data output
input wb_we_i; // WISHBONE write enable input
input wb_stb_i; // WISHBONE strobe input
//input wb_cyc_i; // WISHBONE cycle input
output wb_ack_o; // WISHBONE acknowledge output
output wb_inta_o; // WISHBONE interrupt output
// I2C signals
inout scl_pad_io; // I2C clock io
inout sda_pad_io; // I2C data io
wire wb_cyc_i; // WISHBONE cycle input
// Wire tri-state scl/sda
wire scl_pad_i;
wire scl_pad_o;
wire scl_pad_io;
wire scl_padoen_o;
assign wb_cyc_i = wb_stb_i;
assign scl_pad_i = scl_pad_io;
assign scl_pad_io = scl_padoen_o ? 1'bZ : scl_pad_o;
wire sda_pad_i;
wire sda_pad_o;
wire sda_pad_io;
wire sda_padoen_o;
assign sda_pad_i = sda_pad_io;
assign sda_pad_io = sda_padoen_o ? 1'bZ : sda_pad_o;
// Avalon doesn't have an asynchronous reset
// set it to be inactive and just use synchronous reset
// reset level is a parameter, 0 is the default (active-low reset)
wire arst_i;
assign arst_i = 1'b1;
// Connect the top level I2C core
i2c_master_top i2c_master_top_inst
(
.wb_clk_i(wb_clk_i), .wb_rst_i(wb_rst_i), .arst_i(arst_i),
.wb_adr_i(wb_adr_i), .wb_dat_i(wb_dat_i), .wb_dat_o(wb_dat_o),
.wb_we_i(wb_we_i), .wb_stb_i(wb_stb_i), .wb_cyc_i(wb_cyc_i),
.wb_ack_o(wb_ack_o), .wb_inta_o(wb_inta_o),
.scl_pad_i(scl_pad_i), .scl_pad_o(scl_pad_o), .scl_padoen_o(scl_padoen_o),
.sda_pad_i(sda_pad_i), .sda_pad_o(sda_pad_o), .sda_padoen_o(sda_padoen_o)
);
endmodule

View File

@ -0,0 +1,166 @@
# TCL File Generated by Component Editor 13.1
# Sat May 17 17:29:02 EEST 2014
# DO NOT MODIFY
#
# i2c_opencores "I2C Master (opencores.org)" v13.0
# 2014.05.17.17:29:02
# I2C Master Peripheral from opencores.org
#
#
# request TCL package from ACDS 13.1
#
package require -exact qsys 13.1
#
# module i2c_opencores
#
set_module_property DESCRIPTION "I2C Master Peripheral from opencores.org"
set_module_property NAME i2c_opencores
set_module_property VERSION 13.0
set_module_property INTERNAL false
set_module_property OPAQUE_ADDRESS_MAP true
set_module_property GROUP "Interface Protocols/Serial"
set_module_property AUTHOR ""
set_module_property DISPLAY_NAME "I2C Master (opencores.org)"
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property EDITABLE true
set_module_property ANALYZE_HDL AUTO
set_module_property REPORT_TO_TALKBACK false
set_module_property ALLOW_GREYBOX_GENERATION false
#
# file sets
#
add_fileset quartus_synth QUARTUS_SYNTH "" "Quartus Synthesis"
set_fileset_property quartus_synth TOP_LEVEL i2c_opencores
set_fileset_property quartus_synth ENABLE_RELATIVE_INCLUDE_PATHS false
add_fileset_file i2c_opencores.v VERILOG PATH i2c_opencores.v
add_fileset_file i2c_master_top.v VERILOG PATH i2c_master_top.v
add_fileset_file i2c_master_defines.v VERILOG PATH i2c_master_defines.v
add_fileset_file i2c_master_byte_ctrl.v VERILOG PATH i2c_master_byte_ctrl.v
add_fileset_file i2c_master_bit_ctrl.v VERILOG PATH i2c_master_bit_ctrl.v
add_fileset sim_verilog SIM_VERILOG "" "Verilog Simulation"
set_fileset_property sim_verilog TOP_LEVEL i2c_opencores
set_fileset_property sim_verilog ENABLE_RELATIVE_INCLUDE_PATHS false
add_fileset_file i2c_opencores.v VERILOG PATH i2c_opencores.v
add_fileset_file i2c_master_top.v VERILOG PATH i2c_master_top.v
add_fileset_file i2c_master_defines.v VERILOG PATH i2c_master_defines.v
add_fileset_file i2c_master_byte_ctrl.v VERILOG PATH i2c_master_byte_ctrl.v
add_fileset_file i2c_master_bit_ctrl.v VERILOG PATH i2c_master_bit_ctrl.v
add_fileset_file timescale.v VERILOG PATH timescale.v
#
# parameters
#
#
# display items
#
#
# connection point clock
#
add_interface clock clock end
set_interface_property clock clockRate 0
set_interface_property clock ENABLED true
set_interface_property clock EXPORT_OF ""
set_interface_property clock PORT_NAME_MAP ""
set_interface_property clock CMSIS_SVD_VARIABLES ""
set_interface_property clock SVD_ADDRESS_GROUP ""
add_interface_port clock wb_clk_i clk Input 1
#
# connection point clock_reset
#
add_interface clock_reset reset end
set_interface_property clock_reset associatedClock clock
set_interface_property clock_reset synchronousEdges DEASSERT
set_interface_property clock_reset ENABLED true
set_interface_property clock_reset EXPORT_OF ""
set_interface_property clock_reset PORT_NAME_MAP ""
set_interface_property clock_reset CMSIS_SVD_VARIABLES ""
set_interface_property clock_reset SVD_ADDRESS_GROUP ""
add_interface_port clock_reset wb_rst_i reset Input 1
#
# connection point export
#
add_interface export conduit end
set_interface_property export associatedClock ""
set_interface_property export associatedReset ""
set_interface_property export ENABLED true
set_interface_property export EXPORT_OF ""
set_interface_property export PORT_NAME_MAP ""
set_interface_property export CMSIS_SVD_VARIABLES ""
set_interface_property export SVD_ADDRESS_GROUP ""
add_interface_port export scl_pad_io export Bidir 1
add_interface_port export sda_pad_io export Bidir 1
#
# connection point avalon_slave_0
#
add_interface avalon_slave_0 avalon end
set_interface_property avalon_slave_0 addressAlignment NATIVE
set_interface_property avalon_slave_0 addressUnits WORDS
set_interface_property avalon_slave_0 associatedClock clock
set_interface_property avalon_slave_0 associatedReset clock_reset
set_interface_property avalon_slave_0 bitsPerSymbol 8
set_interface_property avalon_slave_0 burstOnBurstBoundariesOnly false
set_interface_property avalon_slave_0 burstcountUnits WORDS
set_interface_property avalon_slave_0 explicitAddressSpan 0
set_interface_property avalon_slave_0 holdTime 0
set_interface_property avalon_slave_0 linewrapBursts false
set_interface_property avalon_slave_0 maximumPendingReadTransactions 0
set_interface_property avalon_slave_0 readLatency 0
set_interface_property avalon_slave_0 readWaitTime 1
set_interface_property avalon_slave_0 setupTime 0
set_interface_property avalon_slave_0 timingUnits Cycles
set_interface_property avalon_slave_0 writeWaitTime 0
set_interface_property avalon_slave_0 ENABLED true
set_interface_property avalon_slave_0 EXPORT_OF ""
set_interface_property avalon_slave_0 PORT_NAME_MAP ""
set_interface_property avalon_slave_0 CMSIS_SVD_VARIABLES ""
set_interface_property avalon_slave_0 SVD_ADDRESS_GROUP ""
add_interface_port avalon_slave_0 wb_adr_i address Input 3
add_interface_port avalon_slave_0 wb_dat_i writedata Input 8
add_interface_port avalon_slave_0 wb_dat_o readdata Output 8
add_interface_port avalon_slave_0 wb_we_i write Input 1
add_interface_port avalon_slave_0 wb_stb_i chipselect Input 1
add_interface_port avalon_slave_0 wb_ack_o waitrequest_n Output 1
set_interface_assignment avalon_slave_0 embeddedsw.configuration.isFlash 0
set_interface_assignment avalon_slave_0 embeddedsw.configuration.isMemoryDevice 0
set_interface_assignment avalon_slave_0 embeddedsw.configuration.isNonVolatileStorage 0
set_interface_assignment avalon_slave_0 embeddedsw.configuration.isPrintableDevice 0
#
# connection point interrupt_sender
#
add_interface interrupt_sender interrupt end
set_interface_property interrupt_sender associatedAddressablePoint avalon_slave_0
set_interface_property interrupt_sender associatedClock clock
set_interface_property interrupt_sender associatedReset clock_reset
set_interface_property interrupt_sender ENABLED true
set_interface_property interrupt_sender EXPORT_OF ""
set_interface_property interrupt_sender PORT_NAME_MAP ""
set_interface_property interrupt_sender CMSIS_SVD_VARIABLES ""
set_interface_property interrupt_sender SVD_ADDRESS_GROUP ""
add_interface_port interrupt_sender wb_inta_o irq Output 1

View File

@ -0,0 +1,56 @@
#
# opencores_i2c_sw.tcl
#
# Create a new driver
create_driver i2c_opencores_driver
# Associate it with some hardware known as "opencores_i2c"
set_sw_property hw_class_name i2c_opencores
# The version of this driver
set_sw_property version 11.0
# This driver may be incompatible with versions of hardware less
# than specified below. Updates to hardware and device drivers
# rendering the driver incompatible with older versions of
# hardware are noted with this property assignment.
#
# Multiple-Version compatibility was introduced in version 7.1;
# prior versions are therefore excluded.
set_sw_property min_compatible_hw_version 7.1
# Initialize the driver in alt_sys_init()
set_sw_property auto_initialize true
# Location in generated BSP that above sources will be copied into
set_sw_property bsp_subdirectory drivers
# Interrupt properties:
# This peripheral has an IRQ output but the driver doesn't currently
# have any interrupt service routine. To ensure that the BSP tools
# do not otherwise limit the BSP functionality for users of the
# Nios II enhanced interrupt port, these settings advertise
# compliance with both legacy and enhanced interrupt APIs, and to state
# that any driver ISR supports preemption. If an interrupt handler
# is added to this driver, these must be re-examined for validity.
set_sw_property isr_preemption_supported true
set_sw_property supported_interrupt_apis "legacy_interrupt_api enhanced_interrupt_api"
#
# Source file listings...
#
# C/C++ source files
add_sw_property c_source HAL/src/i2c_opencores.c
# Include files
add_sw_property include_source HAL/inc/i2c_opencores.h
add_sw_property include_source inc/i2c_opencores_regs.h
# This driver supports HAL & UCOSII BSP (OS) types
add_sw_property supported_bsp_type HAL
add_sw_property supported_bsp_type UCOSII
# End of file

View File

@ -0,0 +1,77 @@
#ifndef __I2C_OPENCORES_REGS_H__
#define __I2C_OPENCORES_REGS_H__
#include <io.h>
/* prescal clock/(5*desired_SCL) */
/* all registers are 8 bits wide but on 32 bit address boundaries.*/
/* reg definitions take from i2c_specs.pdf in the docs folder */
#define IOADDR_I2C_OPENCORES_PRERLO(base) __IO_CALC_ADDRESS_NATIVE(base, 0)
#define IORD_I2C_OPENCORES_PRERLO(base) IORD(base, 0)
#define IOWR_I2C_OPENCORES_PRERLO(base, data) IOWR(base, 0, data)
#define IOADDR_I2C_OPENCORES_PRERHI(base) __IO_CALC_ADDRESS_NATIVE(base, 0)
#define IORD_I2C_OPENCORES_PRERHI(base) IORD(base, 1)
#define IOWR_I2C_OPENCORES_PRERHI(base, data) IOWR(base, 1, data)
#define IOADDR_I2C_OPENCORES_CTR(base) __IO_CALC_ADDRESS_NATIVE(base, 2)
#define IORD_I2C_OPENCORES_CTR(base) IORD(base, 2)
#define IOWR_I2C_OPENCORES_CTR(base, data) IOWR(base, 2, data)
/* bit definitions*/
#define I2C_OPENCORES_CTR_EN_MSK (0x80)
#define I2C_OPENCORES_CTR_EN_OFST (7)
#define I2C_OPENCORES_CTR_IEN_MSK (0x40)
#define I2C_OPENCORES_CTR_IEN_OFST (6)
#define IOADDR_I2C_OPENCORES_TXR(base) __IO_CALC_ADDRESS_NATIVE(base, 3)
#define IOWR_I2C_OPENCORES_TXR(base, data) IOWR(base, 3, data)
/* bit definitions*/
#define I2C_OPENCORES_TXR_RD_MSK (0x1)
#define I2C_OPENCORES_TXR_RD_OFST (0)
#define I2C_OPENCORES_TXR_WR_MSK (0x0)
#define I2C_OPENCORES_TXR_WR_OFST (0)
#define IOADDR_I2C_OPENCORES_RXR(base) __IO_CALC_ADDRESS_NATIVE(base, 3)
#define IORD_I2C_OPENCORES_RXR(base) IORD(base, 3)
#define IOADDR_I2C_OPENCORES_CR(base) __IO_CALC_ADDRESS_NATIVE(base, 4)
#define IOWR_I2C_OPENCORES_CR(base, data) IOWR(base, 4, data)
/* bit definitions*/
#define I2C_OPENCORES_CR_STA_MSK (0x80)
#define I2C_OPENCORES_CR_STA_OFST (7)
#define I2C_OPENCORES_CR_STO_MSK (0x40)
#define I2C_OPENCORES_CR_STO_OFST (6)
#define I2C_OPENCORES_CR_RD_MSK (0x20)
#define I2C_OPENCORES_CR_RD_OFST (5)
#define I2C_OPENCORES_CR_WR_MSK (0x10)
#define I2C_OPENCORES_CR_WR_OFST (4)
#define I2C_OPENCORES_CR_NACK_MSK (0x8)
#define I2C_OPENCORES_CR_NACK_OFST (3)
#define I2C_OPENCORES_CR_SPIM_MSK (0x4)
#define I2C_OPENCORES_CR_SPIM_OFST (2)
#define I2C_OPENCORES_CR_IACK_MSK (0x1)
#define I2C_OPENCORES_CR_IACK_OFST (0)
#define IOADDR_I2C_OPENCORES_SR(base) __IO_CALC_ADDRESS_NATIVE(base, 4)
#define IORD_I2C_OPENCORES_SR(base) IORD(base, 4)
/* bit definitions*/
#define I2C_OPENCORES_SR_RXNACK_MSK (0x80)
#define I2C_OPENCORES_SR_RXNACK_OFST (7)
#define I2C_OPENCORES_SR_BUSY_MSK (0x40)
#define I2C_OPENCORES_SR_BUSY_OFST (6)
#define I2C_OPENCORES_SR_AL_MSK (0x20)
#define I2C_OPENCORES_SR_AL_OFST (5)
#define I2C_OPENCORES_SR_TIP_MSK (0x2)
#define I2C_OPENCORES_SR_TIP_OFST (1)
#define I2C_OPENCORES_SR_IF_MSK (0x1)
#define I2C_OPENCORES_SR_IF_OFST (0)
#endif /* __I2C_OPENCORES_REGS_H__ */

View File

@ -0,0 +1,2 @@
`timescale 1ns / 10ps

View File

@ -0,0 +1,224 @@
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* Altera does not recommend, suggest or require that this reference design *
* file be used in conjunction or combination with any other product. *
******************************************************************************/
/******************************************************************************
* Author - JCJB *
* *
* This design uses the following CRC-32 implementations: *
* *
* --> Software - Uses modulo 2 division to perform the remainder calculation. *
* --> Optimized Software - Uses a lookup table of all possible division *
* values. The calculation operates on 8 bit data. *
* --> Custom Instruction - Uses a parallel hardware CRC circuit to calculate *
* the remainder. The calculation operates on 8, *
* 16, 24, or 32 bit data. *
* *
* The software implementations can be changed to CRC-16 or CRC-CCITT however *
* the custom instruction must be modified as well to support the same *
* standard. Simply use the values defined in crc.h to change the standard *
* used (using the same values in the hardware parameterization) or define *
* your own standard. *
*******************************************************************************/
#include "system.h"
#include "stdio.h"
#include "crc.h"
#include "ci_crc.h"
#include "sys/alt_timestamp.h"
#include "stdlib.h"
/* Modify these values to adjust the test being performed */
#define NUMBER_OF_BUFFERS 32
#define BUFFER_SIZE 256 /* in bytes */
/* Change the name of memory device according to what you are using
* e.g.: DDR_SDRAM_0 ##_SPAN
* SSRAM_0 ##_SPAN
*/
#define MEMORY_DEVICE_SIZE 32768
/* Make sure there is room left for Nios II text, rodata, rwdata, stack,
* and heap. This software and the buffer space must fit within the
* size of memory device. A total of 1.5 MBytes is reserved. If BUFFER_SIZE
* is a multiple of four then exactly 256kB will be left, otherwise is
* amount will be less since the column dimension needs some padding to
* stay 32 bit aligned
*/
#if ((BUFFER_SIZE * NUMBER_OF_BUFFERS) >= MEMORY_DEVICE_SIZE - 10000)
#error Your buffer space has exceeded the maximum allowable space. Please\
reduce the buffer space so that there is enough room to hold Nios II\
code.
#endif
/* This will line up the data onto a 32 bit (or greater) boundary. A 2d array
* is being used here for simplicity. The first dimension represents a byte
* of data and the second dimension represents an individual buffer
*/
#if ((BUFFER_SIZE & 0x3) == 0)
unsigned char data_buffer_region[NUMBER_OF_BUFFERS][BUFFER_SIZE] __attribute__ ((aligned(4)));
#else /* need to allocate extra bytes so that all buffers start on a 32 bit
boundaries by rounding up the column dimension to the next power of 4
*/
unsigned char data_buffer_region[NUMBER_OF_BUFFERS][BUFFER_SIZE + 4 - (BUFFER_SIZE&0x3)] __attribute__ ((aligned(4)));
#endif
int main()
{
unsigned long buffer_counter, data_counter;
unsigned long sw_slow_results[NUMBER_OF_BUFFERS];
unsigned long sw_fast_results[NUMBER_OF_BUFFERS];
unsigned long ci_results[NUMBER_OF_BUFFERS];
unsigned char random_data = 0x5A;
//unsigned long sw_slow_timeA, sw_slow_timeB;
// unsigned long sw_fast_timeA, sw_fast_timeB;
// unsigned long ci_timeA, ci_timeB;
alt_u32 sw_slow_timeA, sw_slow_timeB;
alt_u32 sw_fast_timeA, sw_fast_timeB;
alt_u32 ci_timeA, ci_timeB;
printf("+-----------------------------------------------------------+\n");
printf("| Comparison between software and custom instruction CRC32 |\n");
printf("+-----------------------------------------------------------+\n\n\n");
printf("System specification\n");
printf("--------------------\n");
printf("System clock speed = %lu MHz\n", (unsigned long)ALT_CPU_FREQ /(unsigned long)1000000);
printf("Number of buffer locations = %d\n", NUMBER_OF_BUFFERS);
printf("Size of each buffer = %d bytes\n\n\n", BUFFER_SIZE);
/* Initializing the data buffers */
printf("Initializing all of the buffers with pseudo-random data\n");
printf("-------------------------------------------------------\n");
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
for(data_counter = 0; data_counter < BUFFER_SIZE; data_counter++)
{
data_buffer_region[buffer_counter][data_counter] = random_data;
random_data = (random_data >> 4) + (random_data << 4) + (data_counter & 0xFF);
}
}
printf("Initialization completed\n\n\n");
if(alt_timestamp_start() < 0) // starts the timestamp timer
{
printf("Please add the high resolution timer to the timestamp timer setting in the syslib properties page.\n");
exit(1);
}
/* Slow software CRC based on a modulo 2 division implementation */
printf("Running the software CRC\n");
printf("------------------------\n");
sw_slow_timeA = alt_timestamp();
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
sw_slow_results[buffer_counter] = crcSlow(data_buffer_region[buffer_counter], BUFFER_SIZE);
}
sw_slow_timeB = alt_timestamp();
printf("Completed\n\n\n");
/* Fast software CRC based on a lookup table implementation */
crcInit();
printf("Running the optimized software CRC\n");
printf("----------------------------------\n");
sw_fast_timeA = alt_timestamp();
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
sw_fast_results[buffer_counter] = crcFast(data_buffer_region[buffer_counter], BUFFER_SIZE);
}
sw_fast_timeB = alt_timestamp();
printf("Completed\n\n\n");
/* Custom instruction CRC */
printf("Running the custom instruction CRC\n");
printf("----------------------------------\n");
ci_timeA = alt_timestamp();
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
ci_results[buffer_counter] = crcCI(data_buffer_region[buffer_counter], BUFFER_SIZE);
}
ci_timeB = alt_timestamp();
printf("Completed\n\n\n");
/* Validation of results */
printf("Validating the CRC results from all implementations\n");
printf("----------------------------------------------------\n");
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
/* Test every combination of results to make sure they are consistant */
if((sw_slow_results[buffer_counter] != ci_results[buffer_counter]) |
(sw_fast_results[buffer_counter] != ci_results[buffer_counter]))
{
printf("FAILURE! Software CRC = 0x%lx, Optimized Software CRC = 0x%lx, Custom Instruction CRC = 0x%lx,\n",
sw_slow_results[buffer_counter], sw_fast_results[buffer_counter], ci_results[buffer_counter]);
exit(1);
}
}
printf("All CRC implementations produced the same results\n\n\n");
// Report processing times
printf("Processing time for each implementation\n");
printf("---------------------------------------\n");
printf("Software CRC = %.2lu ms\n", 1000*((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)alt_timestamp_freq()));
printf("Optimized software CRC = %.2lu ms\n", 1000*((unsigned long)(sw_fast_timeB-sw_fast_timeA))/((unsigned long)alt_timestamp_freq()));
printf("Custom instruction CRC = %.2lu ms\n\n\n", 1000*((unsigned long)(ci_timeB-ci_timeA))/((unsigned long)alt_timestamp_freq()));
printf("Processing throughput for each implementation\n"); // throughput = total bits / (time(s) * 1000000)
printf("---------------------------------------------\n");
printf("Software CRC = %.2lu Mbps\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(sw_slow_timeB-sw_slow_timeA)/((unsigned long)alt_timestamp_freq())));
printf("Optimized software CRC = %.2lu Mbps\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(sw_fast_timeB-sw_fast_timeA)/((unsigned long)alt_timestamp_freq())));
printf("Custom instruction CRC = %.2lu Mbps\n\n\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(ci_timeB-ci_timeA)/((unsigned long)alt_timestamp_freq())));
printf("Speedup ratio\n");
printf("-------------\n");
printf("Custom instruction CRC vs software CRC = %lu\n", ((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)(ci_timeB-ci_timeA)));
printf("Custom instruction CRC vs optimized software CRC = %lu\n", ((unsigned long)(sw_fast_timeB-sw_fast_timeA))/((unsigned long)(ci_timeB-ci_timeA)));
printf("Optimized software CRC vs software CRC= %lu\n", ((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)(sw_fast_timeB-sw_fast_timeA)));
return 0;
}

View File

@ -0,0 +1,38 @@
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* Altera does not recommend, suggest or require that this reference design *
* file be used in conjunction or combination with any other product. *
******************************************************************************/
#ifndef _CRCCI_H_
#define _CRCCI_H_
unsigned long crcCI(unsigned char * input_data, unsigned long input_data_length, int do_initialize);
#endif //_CRCCI_H_

View File

@ -0,0 +1,109 @@
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* Altera does not recommend, suggest or require that this reference design *
* file be used in conjunction or combination with any other product. *
******************************************************************************/
/**********************************************************************
*
* Filename: crc.h
*
* Description: A header file describing the various CRC standards.
*
* Notes:
*
*
* Copyright (c) 2000 by Michael Barr. This software is placed into
* the public domain and may be used for any purpose. However, this
* notice must not be changed or removed and no warranty is either
* expressed or implied by its publication or distribution.
**********************************************************************/
#ifndef _crc_h
#define _crc_h
#define FALSE 0
#define TRUE !FALSE
/*
* Select the CRC standard from the list that follows.
*/
#define CRC32
#if defined(CRC_CCITT)
typedef unsigned short crc;
#define CRC_NAME "CRC-CCITT"
#define POLYNOMIAL 0x1021
#define INITIAL_REMAINDER 0xFFFF
#define FINAL_XOR_VALUE 0x0000
#define REFLECT_DATA FALSE
#define REFLECT_REMAINDER FALSE
#define CHECK_VALUE 0x29B1
#elif defined(CRC16)
typedef unsigned short crc;
#define CRC_NAME "CRC-16"
#define POLYNOMIAL 0x8005
#define INITIAL_REMAINDER 0x0000
#define FINAL_XOR_VALUE 0x0000
#define REFLECT_DATA TRUE
#define REFLECT_REMAINDER TRUE
#define CHECK_VALUE 0xBB3D
#elif defined(CRC32)
typedef unsigned long crc;
#define CRC_NAME "CRC-32"
#define POLYNOMIAL 0x04C11DB7
#define INITIAL_REMAINDER 0xFFFFFFFF
#define FINAL_XOR_VALUE 0xFFFFFFFF
#define REFLECT_DATA TRUE
#define REFLECT_REMAINDER TRUE
#define CHECK_VALUE 0xCBF43926
#else
#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd."
#endif
void crcInit(void);
crc crcSlow(unsigned char const message[], int nBytes);
crc crcFast(unsigned char const message[], int nBytes);
#endif /* _crc_h */

View File

@ -0,0 +1,97 @@
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* Altera does not recommend, suggest or require that this reference design *
* file be used in conjunction or combination with any other product. *
******************************************************************************/
/**********************************************************************
*
* Filename: ci_crc.c
*
* Description: Custom instruction implementations of the CRC.
*
* Notes: A macro is defined that is used to access the CRC custom
* instruction.
*********************************************************************/
#include "system.h"
/*The n values and their corresponding operation are as follow:
* n = 0, Initialize the custom instruction to the initial remainder value
* n = 1, Write 8 bits data to custom instruction
* n = 2, Write 16 bits data to custom instruction
* n = 3, Write 32 bits data to custom instruction
* n = 4, Read 32 bits data from the custom instruction
* n = 5, Read 64 bits data from the custom instruction
* n = 6, Read 96 bits data from the custom instruction
* n = 7, Read 128 bits data from the custom instruction*/
#define CRC_CI_MACRO(n, A) __builtin_custom_ini(ALT_CI_NIOS2_HW_CRC32_0_N + (n & 0x7), (A))
unsigned long crcCI(unsigned char * input_data, unsigned long input_data_length, int do_initialize)
{
unsigned long index;
/* copy of the data buffer pointer so that it can advance by different widths */
void * input_data_copy = (void *)input_data;
/* The custom instruction CRC will initialize to the inital remainder value */
if (do_initialize)
CRC_CI_MACRO(0,0);
/* Write 32 bit data to the custom instruction. If the buffer does not end
* on a 32 bit boundary then the remaining data will be sent to the custom
* instruction in the 'if' statement below.
*/
for(index = 0; index < (input_data_length & 0xFFFFFFFC); index+=4)
{
CRC_CI_MACRO(3, *(unsigned long *)input_data_copy);
input_data_copy += 4; /* void pointer, must move by 4 for each word */
}
/* Write the remainder of the buffer if it does not end on a word boundary */
if((input_data_length & 0x3) == 0x3) /* 3 bytes left */
{
CRC_CI_MACRO(2, *(unsigned short *)input_data_copy);
input_data_copy += 2;
CRC_CI_MACRO(1, *(unsigned char *)input_data_copy);
}
else if((input_data_length & 0x3) == 0x2) /* 2 bytes left */
{
CRC_CI_MACRO(2, *(unsigned short *)input_data_copy);
}
else if((input_data_length & 0x3) == 0x1) /* 1 byte left */
{
CRC_CI_MACRO(1, *(unsigned char *)input_data_copy);
}
/* There are 4 registers in the CRC custom instruction. Since
* this example uses CRC-32 only the first register must be read
* in order to receive the full result.
*/
return CRC_CI_MACRO(4, 0);
}

View File

@ -0,0 +1,265 @@
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* Altera does not recommend, suggest or require that this reference design *
* file be used in conjunction or combination with any other product. *
******************************************************************************/
/**********************************************************************
*
* Filename: crc.c
*
* Description: Slow and fast implementations of the CRC standards.
*
* Notes: The parameters for each supported CRC standard are
* defined in the header file crc.h. The implementations
* here should stand up to further additions to that list.
*
*
* Copyright (c) 2000 by Michael Barr. This software is placed into
* the public domain and may be used for any purpose. However, this
* notice must not be changed or removed and no warranty is either
* expressed or implied by its publication or distribution.
**********************************************************************/
#include "crc.h"
/*
* Derive parameters from the standard-specific parameters in crc.h.
*/
#define WIDTH (8 * sizeof(crc))
#define TOPBIT (1 << (WIDTH - 1))
#if (REFLECT_DATA == TRUE)
#undef REFLECT_DATA
#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8))
#else
#undef REFLECT_DATA
#define REFLECT_DATA(X) (X)
#endif
#if (REFLECT_REMAINDER == TRUE)
#undef REFLECT_REMAINDER
#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH))
#else
#undef REFLECT_REMAINDER
#define REFLECT_REMAINDER(X) (X)
#endif
/*********************************************************************
*
* Function: reflect()
*
* Description: Reorder the bits of a binary sequence, by reflecting
* them about the middle position.
*
* Notes: No checking is done that nBits <= 32.
*
* Returns: The reflection of the original data.
*
*********************************************************************/
static unsigned long
reflect(unsigned long data, unsigned char nBits)
{
unsigned long reflection = 0x00000000;
unsigned char bit;
/*
* Reflect the data about the center bit.
*/
for (bit = 0; bit < nBits; ++bit)
{
/*
* If the LSB bit is set, set the reflection of it.
*/
if (data & 0x01)
{
reflection |= (1 << ((nBits - 1) - bit));
}
data = (data >> 1);
}
return (reflection);
} /* reflect() */
/*********************************************************************
*
* Function: crcSlow()
*
* Description: Compute the CRC of a given message.
*
* Notes:
*
* Returns: The CRC of the message.
*
*********************************************************************/
crc
crcSlow(unsigned char const message[], int nBytes)
{
crc remainder = INITIAL_REMAINDER;
int byte;
unsigned char bit;
/*
* Perform modulo-2 division, a byte at a time.
*/
for (byte = 0; byte < nBytes; ++byte)
{
/*
* Bring the next byte into the remainder.
*/
remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8));
/*
* Perform modulo-2 division, a bit at a time.
*/
for (bit = 8; bit > 0; --bit)
{
/*
* Try to divide the current data bit.
*/
if (remainder & TOPBIT)
{
remainder = (remainder << 1) ^ POLYNOMIAL;
}
else
{
remainder = (remainder << 1);
}
}
}
/*
* The final remainder is the CRC result.
*/
return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
} /* crcSlow() */
crc crcTable[256];
/*********************************************************************
*
* Function: crcInit()
*
* Description: Populate the partial CRC lookup table.
*
* Notes: This function must be rerun any time the CRC standard
* is changed. If desired, it can be run "offline" and
* the table results stored in an embedded system's ROM.
*
* Returns: None defined.
*
*********************************************************************/
void
crcInit(void)
{
crc remainder;
int dividend;
unsigned char bit;
/*
* Compute the remainder of each possible dividend.
*/
for (dividend = 0; dividend < 256; ++dividend)
{
/*
* Start with the dividend followed by zeros.
*/
remainder = dividend << (WIDTH - 8);
/*
* Perform modulo-2 division, a bit at a time.
*/
for (bit = 8; bit > 0; --bit)
{
/*
* Try to divide the current data bit.
*/
if (remainder & TOPBIT)
{
remainder = (remainder << 1) ^ POLYNOMIAL;
}
else
{
remainder = (remainder << 1);
}
}
/*
* Store the result into the table.
*/
crcTable[dividend] = remainder;
}
} /* crcInit() */
/*********************************************************************
*
* Function: crcFast()
*
* Description: Compute the CRC of a given message.
*
* Notes: crcInit() must be called first.
*
* Returns: The CRC of the message.
*
*********************************************************************/
crc
crcFast(unsigned char const message[], int nBytes)
{
crc remainder = INITIAL_REMAINDER;
unsigned char data;
int byte;
/*
* Divide the message by the polynomial, a byte at a time.
*/
for (byte = 0; byte < nBytes; ++byte)
{
data = REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8));
remainder = crcTable[data] ^ (remainder << 8);
}
/*
* The final remainder is the CRC.
*/
return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
} /* crcFast() */

View File

@ -0,0 +1,314 @@
/*
Legal Notice: (C)2006 Altera Corporation. All rights reserved. Your
use of Altera Corporation's design tools, logic functions and other
software and tools, and its AMPP partner logic functions, and any
output files any of the foregoing (including device programming or
simulation files), and any associated documentation or information are
expressly subject to the terms and conditions of the Altera Program
License Subscription Agreement or other applicable license agreement,
including, without limitation, that your use is for the sole purpose
of programming logic devices manufactured by Altera and sold by Altera
or its authorized distributors. Please refer to the applicable
agreement for further details.
*/
/*
This component supports 8, 16, 24, and 32 bit little endian data
and any CRC standard between 1 to 128 bits. Through parameterization
you can change the CRC standard which will take effect after you
regenerate your system in SOPC Builder.
Register Map:
000 -> reset the CRC peripheral to the inital value (data and byte enables ignored)
001 -> data write between 1-32 bits
010 -> reserved
011 -> reserved
100 -> read bits 1-32 of the crc result
101 -> read bits 33-64 of the crc result (where applicable)
110 -> read bits 65-96 of the crc result (where applicable)
111 -> read bits 97-128 of the crc result (where applicable)
Write latency = 0
Read latency = 1
Note: This component uses four blocks of eight bits of data in cascade.
To improve the timing of logic you can create seperate cascades
for 8, 16, 24, and 32 bit data which will allow for smaller area
and a shorter combinational depth. Since CRC logic consumes power
even when not in use you can also add a logic disable feature using
the chipselect signal. Even though the registered CRC value is
held constant when the circuit is not in use the input data will
change during this time and cause the CRC cascade logic to react.
*/
module CRC_Component (clk,
reset,
address,
writedata,
byteenable,
write,
read,
chipselect,
readdata);
/*
Using these parameters you can create any CRC ranging from one bit (parity checker)
up to 128 bits. The following list describes the function of each parameter:
crc_width:
The width of the registered CRC result, this value is typically apart of
the name of the standard (CRC32 is 32 bits wide). Adjusting this value
will impact the logic resource usage.
polynomial_initial:
The initial value set for the CRC result register. By writing any data to address 0
this value will be stored in the result register thereby clearing any previously existing
value. This value must be the same width as 'crc_width'
polynomial:
This is the divisor value used on the input data. Typically shown in polynomial format
the value symbolizes the placement of xor operation on the input data. In synthesis, the
polynomial bits that are '1' will create a not gate, whereas the bits that are '0' will
simply create a wire. Even with 32 stages of these operations cascaded, the simple logic
will not become a significant factor on logic utilization or fmax. This value must be the
same width as 'crc_width'
reflected_input:
Some CRC standards require that all the input bits be reflected around the center point.
This option is enabled with '1' and disabled with '0'. Typically this option is enabled
or disabled with 'reflected_output'.
reflected_output:
Some CRC standards require that all the output bits be reflected around the center point.
This operation occurs before the final optional xor output step. This option is enabled
with '1' and disabled with '0'. Typically this option is enabled or disabled with
'reflected_input' (to undo the input reversal typically).
xor_output:
This is the value used to bitwise xor the CRC result. Most standards use either all zeros
or all ones for this value. When zeros are used the CRC result is passed directly and when
ones are used the CRC result is inverted. Since it's no mandatory that this value be all
ones or zeros, this operation occurs before the output reflection when applicable.
*/
parameter crc_width = 32;
parameter polynomial_inital = 32'hFFFFFFFF;
parameter polynomial = 32'h04C11DB7;
parameter reflected_input = 1;
parameter reflected_output = 1;
parameter xor_output = 32'hFFFFFFFF;
input clk;
input reset;
input [2:0] address;
input [31:0] writedata;
input [3:0] byteenable;
input write;
input read;
input chipselect;
output [31:0] readdata;
reg [crc_width-1:0] crc_value;
wire [crc_width-1:0] poly = polynomial;
wire [crc_width-1:0] cascade [3:0];
wire [7:0] block0_data, block1_data, block2_data, block3_data;
wire [crc_width-1:0] result, result_xored;
wire [31:0] mux_result;
reg [31:0] readdata;
/*
Some standards like CRC16 and CRC32 require this bitreversal for serial
devices like ethernet, uarts, usb, etc...
*/
genvar index;
generate if (reflected_input == 1)
begin
for(index = 0; index < 8; index = index + 1)
begin: input_reflection
assign block0_data[index] = writedata[7-index];
assign block1_data[index] = writedata[15-index];
assign block2_data[index] = writedata[23-index];
assign block3_data[index] = writedata[31-index];
end
end
else
begin
assign block0_data = writedata[7:0];
assign block1_data = writedata[15:8];
assign block2_data = writedata[23:16];
assign block3_data = writedata[31:24];
end
endgenerate
/*
Control for the registered events. It assumes that either 8, 16, 24, or 32
bit data is being written using byte enables. It is important that the data
be in little endian format and no gaps of byte enables be present (like
1011 or 1101 for example)
*/
always @ (posedge clk or posedge reset)
begin
if(reset == 1)
begin
crc_value <= 0;
end
else
begin
if(write && chipselect && (address == 3'b000))
begin
crc_value <= polynomial_inital; // reset the crc to the initial value
end
else if(write && chipselect && (address == 3'b001))
begin
if(byteenable == 4'b0001) // 8 bit data input
begin
crc_value <= cascade[0];
end
else if(byteenable == 4'b0011) // 16 bit data input
begin
crc_value <= cascade[1];
end
else if(byteenable == 4'b0111) // 24 bit data input
begin
crc_value <= cascade[2];
end
else if(byteenable == 4'b1111) // 32 bit data input
begin
crc_value <= cascade[3];
end
end
end
end
/* four stages of cascade blocks (each block is crc_width x 8 bits) */
XOR_Shift_Block cascade_block0(.block_input(crc_value), .poly(poly), .data_input(block0_data), .block_output(cascade[0]));
defparam cascade_block0.crc_width = crc_width;
XOR_Shift_Block cascade_block1(.block_input(cascade[0]), .poly(poly), .data_input(block1_data), .block_output(cascade[1]));
defparam cascade_block1.crc_width = crc_width;
XOR_Shift_Block cascade_block2(.block_input(cascade[1]), .poly(poly), .data_input(block2_data), .block_output(cascade[2]));
defparam cascade_block2.crc_width = crc_width;
XOR_Shift_Block cascade_block3(.block_input(cascade[2]), .poly(poly), .data_input(block3_data), .block_output(cascade[3]));
defparam cascade_block3.crc_width = crc_width;
/*
Some standards like CRC16 and CRC32 require this bitreversal.
This is to better support serial devices like uarts, ethernet, usb, etc...)
*/
generate if (reflected_output == 1)
begin
for(index = 0; index < crc_width; index = index + 1)
begin: output_reflection32
assign result[index] = crc_value[(crc_width-1)-index];
end
end
else
begin
assign result = crc_value;
end
endgenerate
/* This final xor operation occurs after the bit swap */
assign result_xored = result ^ xor_output;
/* Generates the appropriate MUX logic depending on the CRC width */
generate if((crc_width > 32) && (crc_width < 65))
begin
assign mux_result = (address == 3'b100)? result_xored[31:0] : result_xored[crc_width-1:32];
end
else if((crc_width > 64) && (crc_width < 97))
begin
assign mux_result = (address == 3'b100)? result_xored[31:0] :
((address == 3'b101)? result_xored[63:32] : result_xored[crc_width-1:64]);
end
else if((crc_width > 96) && (crc_width < 129))
begin
assign mux_result = (address == 3'b100)? result_xored[31:0] :
((address == 3'b101)? result_xored[63:32] :
((address == 3'b110)? result_xored[95:64] : result_xored[crc_width-1:96]));
end
else
begin
assign mux_result = result_xored;
end
endgenerate
/* Registering the return path of the CRC data (32 bits of it) */
always @ (posedge clk or posedge reset)
begin
if(reset == 1)
begin
readdata <= 0;
end
else if((read == 1) && (chipselect == 1))
begin
readdata <= mux_result;
end
end
endmodule
/* a single cascade block of width: crc_width and a length of eight input bits */
module XOR_Shift_Block(block_input,
poly,
data_input,
block_output);
parameter crc_width = 32;
input [(crc_width-1):0] block_input;
input [(crc_width-1):0] poly;
input [7:0] data_input;
output [(crc_width-1):0] block_output;
wire [(crc_width-1):0] cascade [7:0];
XOR_Shift bit_0(.stage_input(block_input), .poly(poly), .new_bit(data_input[7]), .stage_output(cascade[0]));
defparam bit_0.crc_width = crc_width;
XOR_Shift bit_1(.stage_input(cascade[0]), .poly(poly), .new_bit(data_input[6]), .stage_output(cascade[1]));
defparam bit_1.crc_width = crc_width;
XOR_Shift bit_2(.stage_input(cascade[1]), .poly(poly), .new_bit(data_input[5]), .stage_output(cascade[2]));
defparam bit_2.crc_width = crc_width;
XOR_Shift bit_3(.stage_input(cascade[2]), .poly(poly), .new_bit(data_input[4]), .stage_output(cascade[3]));
defparam bit_3.crc_width = crc_width;
XOR_Shift bit_4(.stage_input(cascade[3]), .poly(poly), .new_bit(data_input[3]), .stage_output(cascade[4]));
defparam bit_4.crc_width = crc_width;
XOR_Shift bit_5(.stage_input(cascade[4]), .poly(poly), .new_bit(data_input[2]), .stage_output(cascade[5]));
defparam bit_5.crc_width = crc_width;
XOR_Shift bit_6(.stage_input(cascade[5]), .poly(poly), .new_bit(data_input[1]), .stage_output(cascade[6]));
defparam bit_6.crc_width = crc_width;
XOR_Shift bit_7(.stage_input(cascade[6]), .poly(poly), .new_bit(data_input[0]), .stage_output(cascade[7]));
defparam bit_7.crc_width = crc_width;
assign block_output = cascade[7];
endmodule
/* performs the 'new_bit' stuffing, shifting, and XOR operations for a single input bit */
module XOR_Shift (stage_input,
poly,
new_bit,
stage_output);
parameter crc_width = 32;
input [crc_width-1:0] stage_input;
input [crc_width-1:0] poly;
input new_bit;
output [crc_width-1:0] stage_output;
assign stage_output[0] = new_bit ^ stage_input[crc_width-1];
assign stage_output[crc_width-1:1] = stage_input[crc_width-2:0] ^ ({crc_width-1{stage_output[0]}} & poly[crc_width-1:1]);
endmodule

View File

@ -0,0 +1,101 @@
/*
Legal Notice: (C)2006 Altera Corporation. All rights reserved. Your
use of Altera Corporation's design tools, logic functions and other
software and tools, and its AMPP partner logic functions, and any
output files any of the foregoing (including device programming or
simulation files), and any associated documentation or information are
expressly subject to the terms and conditions of the Altera Program
License Subscription Agreement or other applicable license agreement,
including, without limitation, that your use is for the sole purpose
of programming logic devices manufactured by Altera and sold by Altera
or its authorized distributors. Please refer to the applicable
agreement for further details.
*/
/*
This thin wrapper re-uses the CRC Avalon component as a Nios II
custom instruction. The n port of custom instruction is used as
control to the CRC Avalon component. Below are the values of n and
the corresponding operations perform by the custom instruction:
n = 0, Initialize the custom instruction to the initial remainder value
n = 1, Write 8 bits data to custom instruction
n = 2, Write 16 bits data to custom instruction
n = 3, Write 32 bits data to custom instruction
n = 4, Read 32 bits data from the custom instruction
n = 5, Read 64 bits data from the custom instruction
n = 6, Read 96 bits data from the custom instruction
n = 7, Read 128 bits data from the custom instruction
*/
module CRC_Custom_Instruction(clk,
reset,
dataa,
n,
clk_en,
start,
done,
result);
/*
See the Avalon CRC component for details on the meaning of each
parameter listed below.
*/
parameter crc_width = 32;
parameter polynomial_inital = 32'hFFFFFFFF;
parameter polynomial = 32'h04C11DB7;
parameter reflected_input = 1;
parameter reflected_output = 1;
parameter xor_output = 32'hFFFFFFFF;
input clk;
input reset;
input [31:0] dataa;
input [2:0] n;
input clk_en;
input start;
output done;
output [31:0] result;
wire [2:0] address;
wire [3:0] byteenable;
wire write;
wire read;
reg done_delay;
assign write = (n<4);
assign read = (n>3);
assign byteenable = (n==1)?4'b0001 : (n==2)?4'b0011 : (n==3)?4'b1111 : 4'b0000;
assign address = (n==0)?3'b000 : ((n==1)|(n==2)|(n==3))?3'b001 : (n==4)?3'b100 : (n==5)?3'b101 : (n==6)?3'b110 : 3'b111;
assign done = (n>3)? done_delay : start;
always @ (posedge clk or posedge reset)
begin
if (reset)
done_delay <= 0;
else
done_delay <= start;
end
/*
Instantiating the Avalon CRC component and wiring it to be
custom instruction compilant
*/
CRC_Component wrapper_wiring(.clk(clk),
.reset(reset),
.address(address),
.writedata(dataa),
.byteenable(byteenable),
.write(write & start),
.read(read),
.chipselect(clk_en),
.readdata(result));
defparam wrapper_wiring.crc_width = crc_width;
defparam wrapper_wiring.polynomial_inital = polynomial_inital;
defparam wrapper_wiring.polynomial = polynomial;
defparam wrapper_wiring.reflected_input = reflected_input;
defparam wrapper_wiring.reflected_output = reflected_output;
defparam wrapper_wiring.xor_output = xor_output;
endmodule

View File

@ -0,0 +1,116 @@
# TCL File Generated by Component Editor 15.1
# Tue Dec 22 18:46:40 EET 2015
# DO NOT MODIFY
#
# nios2_hw_crc32 "nios2_hw_crc32" v1.0
# 2015.12.22.18:46:40
#
#
#
# request TCL package from ACDS 15.1
#
package require -exact qsys 15.1
#
# module nios2_hw_crc32
#
set_module_property DESCRIPTION ""
set_module_property NAME nios2_hw_crc32
set_module_property VERSION 1.0
set_module_property INTERNAL false
set_module_property OPAQUE_ADDRESS_MAP true
set_module_property GROUP "Custom Instruction Modules"
set_module_property AUTHOR ""
set_module_property DISPLAY_NAME nios2_hw_crc32
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property EDITABLE true
set_module_property REPORT_TO_TALKBACK false
set_module_property ALLOW_GREYBOX_GENERATION false
set_module_property REPORT_HIERARCHY false
#
# file sets
#
add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" ""
set_fileset_property QUARTUS_SYNTH TOP_LEVEL CRC_Custom_Instruction
set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false
add_fileset_file CRC_Component.v VERILOG PATH hdl/CRC_Component.v
add_fileset_file CRC_Custom_Instruction.v VERILOG PATH hdl/CRC_Custom_Instruction.v TOP_LEVEL_FILE
#
# parameters
#
add_parameter crc_width INTEGER 32
set_parameter_property crc_width DEFAULT_VALUE 32
set_parameter_property crc_width DISPLAY_NAME crc_width
set_parameter_property crc_width TYPE INTEGER
set_parameter_property crc_width UNITS None
set_parameter_property crc_width HDL_PARAMETER true
add_parameter polynomial_inital STD_LOGIC_VECTOR 4294967295
set_parameter_property polynomial_inital DEFAULT_VALUE 4294967295
set_parameter_property polynomial_inital DISPLAY_NAME polynomial_inital
set_parameter_property polynomial_inital TYPE STD_LOGIC_VECTOR
set_parameter_property polynomial_inital UNITS None
set_parameter_property polynomial_inital ALLOWED_RANGES 0:17179869183
set_parameter_property polynomial_inital HDL_PARAMETER true
add_parameter polynomial STD_LOGIC_VECTOR 79764919
set_parameter_property polynomial DEFAULT_VALUE 79764919
set_parameter_property polynomial DISPLAY_NAME polynomial
set_parameter_property polynomial TYPE STD_LOGIC_VECTOR
set_parameter_property polynomial UNITS None
set_parameter_property polynomial ALLOWED_RANGES 0:17179869183
set_parameter_property polynomial HDL_PARAMETER true
add_parameter reflected_input INTEGER 1
set_parameter_property reflected_input DEFAULT_VALUE 1
set_parameter_property reflected_input DISPLAY_NAME reflected_input
set_parameter_property reflected_input TYPE INTEGER
set_parameter_property reflected_input UNITS None
set_parameter_property reflected_input HDL_PARAMETER true
add_parameter reflected_output INTEGER 1
set_parameter_property reflected_output DEFAULT_VALUE 1
set_parameter_property reflected_output DISPLAY_NAME reflected_output
set_parameter_property reflected_output TYPE INTEGER
set_parameter_property reflected_output UNITS None
set_parameter_property reflected_output HDL_PARAMETER true
add_parameter xor_output STD_LOGIC_VECTOR 4294967295
set_parameter_property xor_output DEFAULT_VALUE 4294967295
set_parameter_property xor_output DISPLAY_NAME xor_output
set_parameter_property xor_output TYPE STD_LOGIC_VECTOR
set_parameter_property xor_output UNITS None
set_parameter_property xor_output ALLOWED_RANGES 0:17179869183
set_parameter_property xor_output HDL_PARAMETER true
#
# display items
#
#
# connection point nios_custom_instruction_slave
#
add_interface nios_custom_instruction_slave nios_custom_instruction end
set_interface_property nios_custom_instruction_slave clockCycle 0
set_interface_property nios_custom_instruction_slave operands 1
set_interface_property nios_custom_instruction_slave ENABLED true
set_interface_property nios_custom_instruction_slave EXPORT_OF ""
set_interface_property nios_custom_instruction_slave PORT_NAME_MAP ""
set_interface_property nios_custom_instruction_slave CMSIS_SVD_VARIABLES ""
set_interface_property nios_custom_instruction_slave SVD_ADDRESS_GROUP ""
add_interface_port nios_custom_instruction_slave clk clk Input 1
add_interface_port nios_custom_instruction_slave clk_en clk_en Input 1
add_interface_port nios_custom_instruction_slave dataa dataa Input 32
add_interface_port nios_custom_instruction_slave done done Output 1
add_interface_port nios_custom_instruction_slave n n Input 3
add_interface_port nios_custom_instruction_slave reset reset Input 1
add_interface_port nios_custom_instruction_slave result result Output 32
add_interface_port nios_custom_instruction_slave start start Input 1

View File

@ -0,0 +1,58 @@
# (C) 2001-2015 Altera Corporation. All rights reserved.
# Your use of Altera Corporation's design tools, logic functions and other
# software and tools, and its AMPP partner logic functions, and any output
# files any of the foregoing (including device programming or simulation
# files), and any associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License Subscription
# Agreement, Altera MegaCore Function License Agreement, or other applicable
# license agreement, including, without limitation, that your use is for the
# sole purpose of programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the applicable
# agreement for further details.
# TCL File Generated by Altera University Program
# DO NOT MODIFY
set aup_version 15.1
# Create a new driver - this name must be different than the
# hardware component name
create_driver nios2_hw_crc32_driver
# Associate it with some hardware
set_sw_property hw_class_name nios2_hw_crc32
# The version of this driver
set_sw_property version $aup_version
# This driver is proclaimed to be compatible with 'component'
# as old as version "1.0". The component hardware version is set in the
# _hw.tcl file - If the hardware component version number is not equal
# or greater than the min_compatable_hw_version number, the driver
# source files will not be copied over to the BSP driver directory
set_sw_property min_compatible_hw_version 1.0
# Initialize the driver in alt_sys_init()
set_sw_property auto_initialize false
# Location in generated BSP that sources will be copied into
set_sw_property bsp_subdirectory drivers
#
# Source file listings...
#
# C/C++ source files
add_sw_property c_source HAL/src/ci_crc.c
add_sw_property c_source HAL/src/crc.c
# Include files
add_sw_property include_source HAL/inc/ci_crc.h
add_sw_property include_source HAL/inc/crc.h
# This driver supports HAL type
add_sw_property supported_bsp_type HAL
# End of file

30
ossc.qpf Normal file
View File

@ -0,0 +1,30 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2013 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II 64-Bit
# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition
# Date created = 17:27:03 May 17, 2014
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "13.1"
DATE = "17:27:03 May 17, 2014"
# Revisions
PROJECT_REVISION = "ossc"

235
ossc.qsf Normal file
View File

@ -0,0 +1,235 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2013 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II 64-Bit
# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition
# Date created = 17:27:03 May 17, 2014
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# ossc_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus II software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
set_global_assignment -name FAMILY "Cyclone IV E"
set_global_assignment -name DEVICE EP4CE15E22C8
set_global_assignment -name TOP_LEVEL_ENTITY ossc
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:27:03 MAY 17, 2014"
set_global_assignment -name LAST_QUARTUS_VERSION 15.1.0
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
set_global_assignment -name EDA_SIMULATION_TOOL "<None>"
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT NONE -section_id eda_simulation
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_location_assignment PIN_25 -to clk27
set_location_assignment PIN_99 -to reset_n
set_location_assignment PIN_23 -to ir_rx
#============================================================
# TVP7002
#============================================================
set_location_assignment PIN_52 -to R_in[0]
set_location_assignment PIN_53 -to R_in[1]
set_location_assignment PIN_54 -to R_in[2]
set_location_assignment PIN_55 -to R_in[3]
set_location_assignment PIN_58 -to R_in[4]
set_location_assignment PIN_59 -to R_in[5]
set_location_assignment PIN_60 -to R_in[6]
set_location_assignment PIN_61 -to R_in[7]
set_location_assignment PIN_88 -to B_in[7]
set_location_assignment PIN_87 -to B_in[6]
set_location_assignment PIN_86 -to B_in[5]
set_location_assignment PIN_85 -to B_in[4]
set_location_assignment PIN_83 -to B_in[3]
set_location_assignment PIN_80 -to B_in[2]
set_location_assignment PIN_77 -to B_in[1]
set_location_assignment PIN_89 -to PCLK_in
set_location_assignment PIN_76 -to B_in[0]
set_location_assignment PIN_90 -to HSYNC_in
set_location_assignment PIN_91 -to VSYNC_in
set_location_assignment PIN_98 -to FID_in
set_location_assignment PIN_72 -to G_in[7]
set_location_assignment PIN_71 -to G_in[6]
set_location_assignment PIN_69 -to G_in[5]
set_location_assignment PIN_68 -to G_in[4]
set_location_assignment PIN_67 -to G_in[3]
set_location_assignment PIN_66 -to G_in[2]
set_location_assignment PIN_65 -to G_in[1]
set_location_assignment PIN_64 -to G_in[0]
#============================================================
# HDMITX
#============================================================
set_location_assignment PIN_113 -to HDMI_TX_PCLK
set_location_assignment PIN_111 -to HDMI_TX_BD[3]
set_location_assignment PIN_112 -to HDMI_TX_BD[4]
set_location_assignment PIN_110 -to HDMI_TX_BD[2]
set_location_assignment PIN_106 -to HDMI_TX_BD[1]
set_location_assignment PIN_105 -to HDMI_TX_BD[0]
set_location_assignment PIN_104 -to HDMI_TX_DE
set_location_assignment PIN_103 -to HDMI_TX_HS
set_location_assignment PIN_101 -to HDMI_TX_VS
set_location_assignment PIN_114 -to HDMI_TX_BD[5]
set_location_assignment PIN_115 -to HDMI_TX_BD[6]
set_location_assignment PIN_119 -to HDMI_TX_BD[7]
set_location_assignment PIN_120 -to HDMI_TX_GD[0]
set_location_assignment PIN_121 -to HDMI_TX_GD[1]
set_location_assignment PIN_125 -to HDMI_TX_GD[2]
set_location_assignment PIN_132 -to HDMI_TX_GD[3]
set_location_assignment PIN_133 -to HDMI_TX_GD[4]
set_location_assignment PIN_134 -to HDMI_TX_GD[5]
set_location_assignment PIN_135 -to HDMI_TX_GD[6]
set_location_assignment PIN_136 -to HDMI_TX_GD[7]
set_location_assignment PIN_137 -to HDMI_TX_RD[0]
set_location_assignment PIN_141 -to HDMI_TX_RD[1]
set_location_assignment PIN_142 -to HDMI_TX_RD[2]
set_location_assignment PIN_143 -to HDMI_TX_RD[3]
set_location_assignment PIN_144 -to HDMI_TX_RD[4]
set_location_assignment PIN_7 -to HDMI_TX_RD[5]
set_location_assignment PIN_10 -to HDMI_TX_RD[6]
set_location_assignment PIN_11 -to HDMI_TX_RD[7]
set_location_assignment PIN_100 -to HDMI_TX_INT_N
set_location_assignment PIN_127 -to HDMI_TX_MODE
#============================================================
# SD card
#============================================================
set_location_assignment PIN_32 -to SD_CLK
set_location_assignment PIN_31 -to SD_CMD
set_location_assignment PIN_33 -to SD_DAT[0]
set_location_assignment PIN_39 -to SD_DAT[1]
set_location_assignment PIN_28 -to SD_DAT[2]
set_location_assignment PIN_30 -to SD_DAT[3]
#============================================================
# Leds
#============================================================
set_location_assignment PIN_44 -to LED_G
set_location_assignment PIN_46 -to LED_R
#============================================================
# I2C
#============================================================
set_location_assignment PIN_49 -to sda
set_location_assignment PIN_50 -to scl
#============================================================
# Char LCD
#============================================================
set_location_assignment PIN_42 -to LCD_RS
set_location_assignment PIN_43 -to LCD_CS_N
set_location_assignment PIN_51 -to LCD_BL
#============================================================
# Buttons
#============================================================
set_location_assignment PIN_129 -to btn[1]
set_location_assignment PIN_128 -to btn[0]
set_instance_assignment -name PLL_COMPENSATE ON -to G_in
set_instance_assignment -name PLL_COMPENSATE ON -to FID_in
set_instance_assignment -name PLL_COMPENSATE ON -to HSYNC_in
set_instance_assignment -name PLL_COMPENSATE ON -to R_in
set_instance_assignment -name PLL_COMPENSATE ON -to VSYNC_in
set_instance_assignment -name PLL_COMPENSATE ON -to B_in
set_global_assignment -name USE_CONFIGURATION_DEVICE ON
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
set_global_assignment -name SEARCH_PATH rtl
set_global_assignment -name CYCLONEIII_CONFIGURATION_DEVICE EPCS16
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
set_global_assignment -name SMART_RECOMPILE OFF
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC OFF
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF
set_global_assignment -name OPTIMIZATION_MODE BALANCED
set_global_assignment -name ALLOW_REGISTER_RETIMING OFF
set_global_assignment -name ENABLE_OCT_DONE OFF
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP"
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE 50%
#set_location_assignment PLL_4 -to "scanconverter:scanconverter_inst|pll_3x:pll_linetriple|altpll:altpll_component|pll_3x_altpll:auto_generated|pll1"
#set_location_assignment PLL_3 -to "scanconverter:scanconverter_inst|pll_3x_lowfreq:pll_linetriple_lowfreq|altpll:altpll_component|pll_3x_lowfreq_altpll:auto_generated|pll1"
#set_location_assignment PLL_1 -to "scanconverter:scanconverter_inst|pll_2x:pll_linedouble|altpll:altpll_component|pll_2x_altpll:auto_generated|pll1"
set_global_assignment -name VERILOG_FILE rtl/videogen.v
set_global_assignment -name QIP_FILE software/sys_controller/mem_init/meminit.qip
set_global_assignment -name VERILOG_FILE rtl/ir_rcv.v
set_global_assignment -name SDC_FILE ossc.sdc
set_global_assignment -name QSYS_FILE sys.qsys
set_global_assignment -name VERILOG_FILE rtl/ossc.v
set_global_assignment -name VERILOG_FILE rtl/scanconverter.v
set_global_assignment -name QIP_FILE rtl/linebuf.qip
set_global_assignment -name QIP_FILE rtl/pll_2x.qip
set_global_assignment -name QIP_FILE rtl/pll_3x.qip
set_global_assignment -name QIP_FILE rtl/pll_3x_lowfreq.qip
set_global_assignment -name CDF_FILE output_files/Chain1.cdf
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

102
ossc.sdc Normal file
View File

@ -0,0 +1,102 @@
### CPU clock constraints ###
create_clock -period 27MHz -name clk27 [get_ports clk27]
set_input_delay -clock clk27 0 [get_ports {sda scl ir_rx HDMI_TX_INT_N SD_CMD SD_DAT* btn* *ALTERA_DATA0}]
set_false_path -to {sys:sys_inst|sys_pio_1:pio_1|readdata*}
### Scanconverter clock constraints ###
create_clock -period 108MHz -name pclk_hdtv [get_ports PCLK_in]
create_clock -period 27MHz -name pclk_ldtv_hs_M0 [get_ports PCLK_in] -add
create_clock -period 20MHz -name pclk_ldtv_hs_M1 [get_ports PCLK_in] -add
create_clock -period 13.5MHz -name pclk_sdtv [get_ports PCLK_in] -add
create_clock -period 6.7MHz -name pclk_ldtv_M2 [get_ports PCLK_in] -add
create_clock -period 5.4MHz -name pclk_ldtv_M3 [get_ports PCLK_in] -add
#derive_pll_clocks
create_generated_clock -master_clock pclk_sdtv -source {scanconverter_inst|pll_linedouble|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 2 -duty_cycle 50.00 -name pclk_2x {scanconverter_inst|pll_linedouble|altpll_component|auto_generated|pll1|clk[0]}
create_generated_clock -master_clock pclk_ldtv_hs_M0 -source {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 3 -duty_cycle 50.00 -name pclk_3x_M0 {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|clk[0]}
create_generated_clock -master_clock pclk_ldtv_hs_M1 -source {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 3 -duty_cycle 50.00 -name pclk_3x_M1 {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|clk[0]} -add
create_generated_clock -master_clock pclk_ldtv_hs_M1 -source {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 4 -duty_cycle 50.00 -name pclk_4x_M1 {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|clk[1]}
create_generated_clock -master_clock pclk_ldtv_M2 -source {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 3 -duty_cycle 50.00 -name pclk_3x_h1x_M2 {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|clk[0]}
create_generated_clock -master_clock pclk_ldtv_M2 -source {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 12 -duty_cycle 50.00 -name pclk_3x_h4x_M2 {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|clk[1]}
create_generated_clock -master_clock pclk_ldtv_M3 -source {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 3 -duty_cycle 50.00 -name pclk_3x_h1x_M3 {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|clk[0]} -add
create_generated_clock -master_clock pclk_ldtv_M3 -source {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 15 -duty_cycle 50.00 -name pclk_3x_h5x_M3 {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|clk[2]}
derive_clock_uncertainty
# input delay constraints
set critinputs [get_ports {R_in* G_in* B_in* FID_in HSYNC_in VSYNC_in}]
set_input_delay -clock pclk_sdtv -min 0 $critinputs
set_input_delay -clock pclk_sdtv -max 1.5 $critinputs
set_input_delay -clock pclk_hdtv -min 0 $critinputs -add_delay
set_input_delay -clock pclk_hdtv -max 1.5 $critinputs -add_delay
set_input_delay -clock pclk_ldtv_M2 -min 0 $critinputs -add_delay
set_input_delay -clock pclk_ldtv_M2 -max 1.5 $critinputs -add_delay
set_input_delay -clock pclk_ldtv_M3 -min 0 $critinputs -add_delay
set_input_delay -clock pclk_ldtv_M3 -max 1.5 $critinputs -add_delay
set_input_delay -clock pclk_ldtv_hs_M0 -min 0 $critinputs -add_delay
set_input_delay -clock pclk_ldtv_hs_M0 -max 1.5 $critinputs -add_delay
set_input_delay -clock pclk_ldtv_hs_M1 -min 0 $critinputs -add_delay
set_input_delay -clock pclk_ldtv_hs_M1 -max 1.5 $critinputs -add_delay
# output delay constraints (TODO: add vsync)
set critoutputs_hdmi {HDMI_TX_RD* HDMI_TX_GD* HDMI_TX_BD* HDMI_TX_DE HDMI_TX_HS}
set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_hdtv 0 $critoutputs_hdmi
set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_2x 0 $critoutputs_hdmi -add_delay
set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_3x_M0 0 $critoutputs_hdmi -add_delay
set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_4x_M1 0 $critoutputs_hdmi -add_delay
set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_3x_h4x_M2 0 $critoutputs_hdmi -add_delay
set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_3x_h5x_M3 0 $critoutputs_hdmi -add_delay
set_false_path -to [remove_from_collection [all_outputs] $critoutputs_hdmi]
### CPU/scanconverter clock relations ###
# Set pixel clocks as exclusive clocks
set_clock_groups -exclusive \
-group {pclk_hdtv} \
-group {pclk_sdtv pclk_2x} \
-group {pclk_ldtv_hs_M0 pclk_3x_M0} \
-group {pclk_ldtv_hs_M1 pclk_3x_M1 pclk_4x_M1} \
-group {pclk_ldtv_M2 pclk_3x_h1x_M2 pclk_3x_h4x_M2} \
-group {pclk_ldtv_M3 pclk_3x_h1x_M3 pclk_3x_h5x_M3}
# Treat CPU clock asynchronous to pixel clocks
set_clock_groups -asynchronous -group {clk27}
# Filter out impossible output mux combinations
set clkmuxregs [get_cells {scanconverter:scanconverter_inst|R_out[*] scanconverter:scanconverter_inst|G_out[*] scanconverter:scanconverter_inst|B_out[*] scanconverter:scanconverter_inst|HSYNC_out scanconverter:scanconverter_inst|DATA_enable scanconverter:scanconverter_inst|*_pp1*}]
set clkmuxnodes [get_pins {scanconverter_inst|linebuf_*|altsyncram_*|auto_generated|ram_*|portbaddr*}]
set_false_path -from [get_clocks {pclk_ldtv* pclk_sdtv}] -through $clkmuxregs
set_false_path -from pclk_3x_M1 -through [remove_from_collection $clkmuxregs {scanconverter:scanconverter_inst|DATA_enable_pp1* scanconverter:scanconverter_inst|HSYNC_pp1*}] -to pclk_4x_M1
set_false_path -from pclk_3x_M1 -through $clkmuxnodes -to pclk_4x_M1
# Ignore paths from registers which are updated only at the end of vsync
set_false_path -from [get_cells {scanconverter_inst|H_* scanconverter_inst|V_* scanconverter:scanconverter_inst|lines_*}]
# Ignore paths from registers which are updated only at the end of hsync
set_false_path -from [get_cells {scanconverter:scanconverter_inst|vcnt_* scanconverter:scanconverter_inst|line_idx}]
# Ignore following clock transfers
set_false_path -from [get_clocks pclk_2x] -to [get_clocks pclk_sdtv]
set_false_path -from [get_clocks pclk_3x_M*] -to [get_clocks {pclk_ldtv_hs_M*}]
set_false_path -from [get_clocks pclk_4x_M1] -to [get_clocks {pclk_ldtv_hs_M1 pclk_3x_M1}]
set_false_path -from [get_clocks pclk_3x_h4x_M2] -to [get_clocks {pclk_ldtv_M2 pclk_3x_h1x_M2}]
set_false_path -from [get_clocks pclk_3x_h5x_M3] -to [get_clocks {pclk_ldtv_M3 pclk_3x_h1x_M3}]
set_false_path -from [get_clocks pclk_3x_h1x_M*] -to [get_clocks {pclk_ldtv_M*}]
### JTAG Signal Constraints ###
#constrain the TCK port
#create_clock -name tck -period "10MHz" [get_ports altera_reserved_tck]
#cut all paths to and from tck
set_clock_groups -exclusive -group [get_clocks altera_reserved_tck]
#constrain the TDI port
set_input_delay -clock altera_reserved_tck 20 [get_ports altera_reserved_tdi]
#constrain the TMS port
set_input_delay -clock altera_reserved_tck 20 [get_ports altera_reserved_tms]
#constrain the TDO port
#set_output_delay -clock altera_reserved_tck 20 [get_ports altera_reserved_tdo]

168
rtl/ir_rcv.v Normal file
View File

@ -0,0 +1,168 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
`define STATE_IDLE 2'b00
`define STATE_LEADVERIFY 2'b01
`define STATE_DATARCV 2'b10
module ir_rcv (
input clk27,
input reset_n,
input ir_rx,
output reg [15:0] ir_code,
output reg ir_code_ack
);
// 20ns clock period
parameter LEADCODE_LO_THOLD = 124200; //4.60ms
parameter LEADCODE_HI_THOLD = 113400; //4.20ms
parameter LEADCODE_HI_RPT_THOLD = 56700; //2.1ms
parameter RPT_RELEASE_THOLD = 3240000; //120ms
parameter BIT_ONE_THOLD = 22410; //0.83ms
parameter BIT_DETECT_THOLD = 10800; //0.4ms
parameter IDLE_THOLD = 141557; //5.24ms
reg [1:0] state; // 3 states
reg [31:0] databuf; // temp. buffer
reg [5:0] bits_detected; // max. 63, effectively between 0 and 33
reg [17:0] act_cnt; // max. 5.2ms
reg [17:0] leadvrf_cnt; // max. 5.2ms
reg [17:0] datarcv_cnt; // max. 5.2ms
reg [22:0] rpt_cnt; // max. 166ms
// activity when signal is low
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
act_cnt <= 0;
else
begin
if ((state == `STATE_IDLE) & (~ir_rx))
act_cnt <= act_cnt + 1'b1;
else
act_cnt <= 0;
end
end
// lead code verify counter
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
leadvrf_cnt <= 0;
else
begin
if ((state == `STATE_LEADVERIFY) & ir_rx)
leadvrf_cnt <= leadvrf_cnt + 1'b1;
else
leadvrf_cnt <= 0;
end
end
// '0' and '1' are differentiated by high phase duration preceded by constant length low phase
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
begin
datarcv_cnt <= 0;
bits_detected <= 0;
databuf <= 0;
end
else
begin
if (state == `STATE_DATARCV)
begin
if (ir_rx)
datarcv_cnt <= datarcv_cnt + 1'b1;
else
datarcv_cnt <= 0;
if (datarcv_cnt == BIT_DETECT_THOLD)
bits_detected <= bits_detected + 1'b1;
if (datarcv_cnt == BIT_ONE_THOLD)
databuf[32-bits_detected] <= 1'b1;
end
else
begin
datarcv_cnt <= 0;
bits_detected <= 0;
databuf <= 0;
end
end
end
// read and validate data after 32 bits detected (last bit may change to '1' at any time)
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
begin
ir_code_ack <= 1'b0;
ir_code <= 16'h00000000;
end
else
begin
if ((bits_detected == 32) & (databuf[31:24] == ~databuf[23:16]) & (databuf[15:8] == ~databuf[7:0]))
begin
ir_code <= {databuf[31:24], databuf[15:8]};
ir_code_ack <= 1'b1;
end
else if (rpt_cnt >= RPT_RELEASE_THOLD)
begin
ir_code <= 16'h00000000;
ir_code_ack <= 1'b0;
end
else
ir_code_ack <= 1'b0;
end
end
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
begin
state <= `STATE_IDLE;
rpt_cnt <= 0;
end
else
begin
rpt_cnt <= rpt_cnt + 1'b1;
case (state)
`STATE_IDLE:
if (act_cnt >= LEADCODE_LO_THOLD)
state <= `STATE_LEADVERIFY;
`STATE_LEADVERIFY:
begin
if (leadvrf_cnt == LEADCODE_HI_RPT_THOLD)
rpt_cnt <= 0;
if (leadvrf_cnt >= LEADCODE_HI_THOLD)
state <= `STATE_DATARCV;
end
`STATE_DATARCV:
if ((datarcv_cnt >= IDLE_THOLD) | (bits_detected >= 33))
state <= `STATE_IDLE;
default:
state <= `STATE_IDLE;
endcase
end
end
endmodule

6
rtl/linebuf.qip Normal file
View File

@ -0,0 +1,6 @@
set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT"
set_global_assignment -name IP_TOOL_VERSION "15.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "linebuf.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "linebuf_inst.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "linebuf_bb.v"]

216
rtl/linebuf.v Normal file
View File

@ -0,0 +1,216 @@
// megafunction wizard: %RAM: 2-PORT%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altsyncram
// ============================================================
// File Name: linebuf.v
// Megafunction Name(s):
// altsyncram
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 15.1.0 Build 185 10/21/2015 SJ Lite Edition
// ************************************************************
//Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, the Altera Quartus Prime License Agreement,
//the Altera MegaCore Function License Agreement, or other
//applicable license agreement, including, without limitation,
//that your use is for the sole purpose of programming logic
//devices manufactured by Altera and sold by Altera or its
//authorized distributors. Please refer to the applicable
//agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module linebuf (
data,
rdaddress,
rdclock,
wraddress,
wrclock,
wren,
q);
input [23:0] data;
input [11:0] rdaddress;
input rdclock;
input [11:0] wraddress;
input wrclock;
input wren;
output [23:0] q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri1 wrclock;
tri0 wren;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [23:0] sub_wire0;
wire [23:0] q = sub_wire0[23:0];
altsyncram altsyncram_component (
.address_a (wraddress),
.address_b (rdaddress),
.clock0 (wrclock),
.clock1 (rdclock),
.data_a (data),
.wren_a (wren),
.q_b (sub_wire0),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.data_b ({24{1'b1}}),
.eccstatus (),
.q_a (),
.rden_a (1'b1),
.rden_b (1'b1),
.wren_b (1'b0));
defparam
altsyncram_component.address_aclr_b = "NONE",
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 4096,
altsyncram_component.numwords_b = 4096,
altsyncram_component.operation_mode = "DUAL_PORT",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.widthad_a = 12,
altsyncram_component.widthad_b = 12,
altsyncram_component.width_a = 24,
altsyncram_component.width_b = 24,
altsyncram_component.width_byteena_a = 1;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0"
// Retrieval info: PRIVATE: CLRdata NUMERIC "0"
// Retrieval info: PRIVATE: CLRq NUMERIC "0"
// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
// Retrieval info: PRIVATE: CLRrren NUMERIC "0"
// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
// Retrieval info: PRIVATE: CLRwren NUMERIC "0"
// Retrieval info: PRIVATE: Clock NUMERIC "1"
// Retrieval info: PRIVATE: Clock_A NUMERIC "0"
// Retrieval info: PRIVATE: Clock_B NUMERIC "0"
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "0"
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_B"
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
// Retrieval info: PRIVATE: MEMSIZE NUMERIC "98304"
// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0"
// Retrieval info: PRIVATE: MIFfilename STRING ""
// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "2"
// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1"
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3"
// Retrieval info: PRIVATE: REGdata NUMERIC "1"
// Retrieval info: PRIVATE: REGq NUMERIC "1"
// Retrieval info: PRIVATE: REGrdaddress NUMERIC "1"
// Retrieval info: PRIVATE: REGrren NUMERIC "1"
// Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
// Retrieval info: PRIVATE: REGwren NUMERIC "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
// Retrieval info: PRIVATE: VarWidth NUMERIC "0"
// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "24"
// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "24"
// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "24"
// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "24"
// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "0"
// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: enable NUMERIC "0"
// Retrieval info: PRIVATE: rden NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADDRESS_ACLR_B STRING "NONE"
// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1"
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096"
// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "4096"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "DUAL_PORT"
// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK1"
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12"
// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "12"
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "24"
// Retrieval info: CONSTANT: WIDTH_B NUMERIC "24"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
// Retrieval info: USED_PORT: data 0 0 24 0 INPUT NODEFVAL "data[23..0]"
// Retrieval info: USED_PORT: q 0 0 24 0 OUTPUT NODEFVAL "q[23..0]"
// Retrieval info: USED_PORT: rdaddress 0 0 12 0 INPUT NODEFVAL "rdaddress[11..0]"
// Retrieval info: USED_PORT: rdclock 0 0 0 0 INPUT NODEFVAL "rdclock"
// Retrieval info: USED_PORT: wraddress 0 0 12 0 INPUT NODEFVAL "wraddress[11..0]"
// Retrieval info: USED_PORT: wrclock 0 0 0 0 INPUT VCC "wrclock"
// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT GND "wren"
// Retrieval info: CONNECT: @address_a 0 0 12 0 wraddress 0 0 12 0
// Retrieval info: CONNECT: @address_b 0 0 12 0 rdaddress 0 0 12 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 wrclock 0 0 0 0
// Retrieval info: CONNECT: @clock1 0 0 0 0 rdclock 0 0 0 0
// Retrieval info: CONNECT: @data_a 0 0 24 0 data 0 0 24 0
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
// Retrieval info: CONNECT: q 0 0 24 0 @q_b 0 0 24 0
// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf_inst.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf_bb.v TRUE
// Retrieval info: LIB_FILE: altera_mf

197
rtl/ossc.v Normal file
View File

@ -0,0 +1,197 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//`define DEBUG
`define VIDEOGEN
module ossc (
input clk27,
input ir_rx,
inout scl,
inout sda,
input [1:0] btn,
input [7:0] R_in,
input [7:0] G_in,
input [7:0] B_in,
input FID_in,
input VSYNC_in,
input HSYNC_in,
input PCLK_in,
output [7:0] HDMI_TX_RD,
output [7:0] HDMI_TX_GD,
output [7:0] HDMI_TX_BD,
output HDMI_TX_DE,
output HDMI_TX_HS,
output HDMI_TX_VS,
output HDMI_TX_PCLK,
input HDMI_TX_INT_N,
input HDMI_TX_MODE,
output reset_n,
output LED_G,
output LED_R,
output LCD_RS,
output LCD_CS_N,
output LCD_BL,
output SD_CLK,
inout SD_CMD,
inout [3:0] SD_DAT
);
wire cpu_reset_n;
wire [7:0] sys_ctrl;
wire h_unstable;
wire [2:0] pclk_lock;
wire [2:0] pll_lock_lost;
wire [31:0] h_info;
wire [31:0] v_info;
wire [10:0] lines_out;
wire [1:0] fpga_vsyncgen;
wire [15:0] ir_code;
wire [7:0] R_out, G_out, B_out;
wire HSYNC_out;
wire VSYNC_out;
wire PCLK_out;
wire DATA_enable;
wire [7:0] R_out_videogen, G_out_videogen, B_out_videogen;
wire HSYNC_out_videogen;
wire VSYNC_out_videogen;
wire PCLK_out_videogen;
wire DATA_enable_videogen;
wire [7:0] lcd_ctrl;
reg [3:0] reset_n_ctr;
`ifdef DEBUG
assign LED_G = {clk27, PCLK_in};
assign LED_R = {HSYNC_in, VSYNC_in};
`else
//assign LED_G = {(pclk_lock != 3'b000), (ir_code != 0)};
//assign LED_R = {(pll_lock_lost != 3'b000), h_unstable};
assign LED_G = (ir_code == 0);
assign LED_R = (pll_lock_lost != 3'b000)|h_unstable;
`endif
assign LCD_CS_N = lcd_ctrl[0];
assign LCD_RS = lcd_ctrl[1];
assign LCD_BL = sys_ctrl[1]; //reset_n in v1.2 PCB
assign reset_n = sys_ctrl[0]; //HDMI_TX_RST_N in v1.2 PCB
`ifdef VIDEOGEN
wire videogen_sel;
assign videogen_sel = ~sys_ctrl[2];
assign HDMI_TX_RD = videogen_sel ? R_out_videogen : R_out;
assign HDMI_TX_GD = videogen_sel ? G_out_videogen : G_out;
assign HDMI_TX_BD = videogen_sel ? B_out_videogen : B_out;
assign HDMI_TX_HS = videogen_sel ? HSYNC_out_videogen : HSYNC_out;
assign HDMI_TX_VS = videogen_sel ? VSYNC_out_videogen : VSYNC_out;
assign HDMI_TX_PCLK = videogen_sel ? PCLK_out_videogen : PCLK_out;
assign HDMI_TX_DE = videogen_sel ? DATA_enable_videogen : DATA_enable;
`else
assign HDMI_TX_RD = R_out;
assign HDMI_TX_GD = G_out;
assign HDMI_TX_BD = B_out;
assign HDMI_TX_HS = HSYNC_out;
assign HDMI_TX_VS = VSYNC_out;
assign HDMI_TX_PCLK = PCLK_out;
assign HDMI_TX_DE = DATA_enable;
`endif
always @(posedge clk27)
begin
if (reset_n_ctr == 4'b1000)
reset_n_reg <= 1'b1;
else
reset_n_ctr <= reset_n_ctr + 1'b1;
end
assign cpu_reset_n = reset_n_reg;
sys sys_inst(
.clk_clk (clk27),
.reset_reset_n (cpu_reset_n),
.pio_0_sys_ctrl_out_export (sys_ctrl),
.pio_1_controls_in_export ({13'b00000000000000, HDMI_TX_MODE, btn, ir_code}),
.pio_2_horizontal_info_out_export (h_info),
.pio_3_vertical_info_out_export (v_info),
`ifdef DEBUG
.pio_4_linecount_in_export ({8'h00, R_in, G_in, B_in}),
`else
.pio_4_linecount_in_export ({14'h0000, fpga_vsyncgen, 5'h00, lines_out}),
`endif
.pio_5_lcd_ctrl_out_export (lcd_ctrl),
.i2c_opencores_0_export_scl_pad_io (scl),
.i2c_opencores_0_export_sda_pad_io (sda),
.sdcard_0_b_SD_cmd (SD_CMD),
.sdcard_0_b_SD_dat (SD_DAT[0]),
.sdcard_0_b_SD_dat3 (SD_DAT[3]),
.sdcard_0_o_SD_clock (SD_CLK)
);
scanconverter scanconverter_inst (
.HSYNC_in (HSYNC_in),
.VSYNC_in (VSYNC_in),
.PCLK_in (PCLK_in),
.FID_in (FID_in),
.R_in (R_in),
.G_in (G_in),
.B_in (B_in),
.h_info (h_info),
.v_info (v_info),
.R_out (R_out),
.G_out (G_out),
.B_out (B_out),
.HSYNC_out (HSYNC_out),
.VSYNC_out (VSYNC_out),
.PCLK_out (PCLK_out),
.DATA_enable (DATA_enable),
.h_unstable (h_unstable),
.fpga_vsyncgen (fpga_vsyncgen),
.pclk_lock (pclk_lock),
.pll_lock_lost (pll_lock_lost),
.lines_out (lines_out)
);
ir_rcv ir0 (
.clk27 (clk27),
.reset_n (reset_n_reg),
.ir_rx (ir_rx),
.ir_code (ir_code),
.ir_code_ack ()
);
`ifdef VIDEOGEN
videogen vg0 (
.clk27 (clk27),
.reset_n (reset_n_reg & videogen_sel),
.R_out (R_out_videogen),
.G_out (G_out_videogen),
.B_out (B_out_videogen),
.HSYNC_out (HSYNC_out_videogen),
.VSYNC_out (VSYNC_out_videogen),
.PCLK_out (PCLK_out_videogen),
.ENABLE_out (DATA_enable_videogen)
);
`endif
endmodule

11
rtl/pll_2x.ppf Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone IV E" variation_name="pll_2x" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="areset" direction="input" scope="external" />
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="locked" direction="output" scope="external" />
</global>
</pinplan>

6
rtl/pll_2x.qip Normal file
View File

@ -0,0 +1,6 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "15.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll_2x.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_2x_bb.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_2x.ppf"]

320
rtl/pll_2x.v Normal file
View File

@ -0,0 +1,320 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: pll_2x.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
//
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 15.1.0 Build 185 10/21/2015 SJ Lite Edition
// ************************************************************
//Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, the Altera Quartus Prime License Agreement,
//the Altera MegaCore Function License Agreement, or other
//applicable license agreement, including, without limitation,
//that your use is for the sole purpose of programming logic
//devices manufactured by Altera and sold by Altera or its
//authorized distributors. Please refer to the applicable
//agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll_2x (
areset,
inclk0,
c0,
locked);
input areset;
input inclk0;
output c0;
output locked;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri0 areset;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [4:0] sub_wire0;
wire sub_wire2;
wire [0:0] sub_wire5 = 1'h0;
wire [0:0] sub_wire1 = sub_wire0[0:0];
wire c0 = sub_wire1;
wire locked = sub_wire2;
wire sub_wire3 = inclk0;
wire [1:0] sub_wire4 = {sub_wire5, sub_wire3};
altpll altpll_component (
.areset (areset),
.inclk (sub_wire4),
.clk (sub_wire0),
.locked (sub_wire2),
.activeclock (),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "LOW",
altpll_component.clk0_divide_by = 1,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 2,
altpll_component.clk0_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 74074,
altpll_component.intended_device_family = "Cyclone IV E",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll_2x",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "SOURCE_SYNCHRONOUS",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_USED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_UNUSED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.self_reset_on_loss_lock = "OFF",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "27.000000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "13.500"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "2"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_2x.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "74074"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SOURCE_SYNCHRONOUS"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x_bb.v TRUE
// Retrieval info: CBX_MODULE_PREFIX: ON

12
rtl/pll_3x.ppf Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone IV E" variation_name="pll_3x" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="areset" direction="input" scope="external" />
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="c1" direction="output" scope="external" source="clock" />
<pin name="locked" direction="output" scope="external" />
</global>
</pinplan>

5
rtl/pll_3x.qip Normal file
View File

@ -0,0 +1,5 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "15.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll_3x.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_3x.ppf"]

348
rtl/pll_3x.v Normal file
View File

@ -0,0 +1,348 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: pll_3x.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
//
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 15.1.0 Build 185 10/21/2015 SJ Lite Edition
// ************************************************************
//Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, the Altera Quartus Prime License Agreement,
//the Altera MegaCore Function License Agreement, or other
//applicable license agreement, including, without limitation,
//that your use is for the sole purpose of programming logic
//devices manufactured by Altera and sold by Altera or its
//authorized distributors. Please refer to the applicable
//agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll_3x (
areset,
inclk0,
c0,
c1,
locked);
input areset;
input inclk0;
output c0;
output c1;
output locked;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri0 areset;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [4:0] sub_wire0;
wire sub_wire3;
wire [0:0] sub_wire6 = 1'h0;
wire [1:1] sub_wire2 = sub_wire0[1:1];
wire [0:0] sub_wire1 = sub_wire0[0:0];
wire c0 = sub_wire1;
wire c1 = sub_wire2;
wire locked = sub_wire3;
wire sub_wire4 = inclk0;
wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};
altpll altpll_component (
.areset (areset),
.inclk (sub_wire5),
.clk (sub_wire0),
.locked (sub_wire3),
.activeclock (),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "LOW",
altpll_component.clk0_divide_by = 1,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 3,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 1,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 4,
altpll_component.clk1_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 37037,
altpll_component.intended_device_family = "Cyclone IV E",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll_3x",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "SOURCE_SYNCHRONOUS",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_USED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.self_reset_on_loss_lock = "OFF",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "81.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "108.000000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "3"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "4"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_2x.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "3"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "4"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SOURCE_SYNCHRONOUS"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_bb.v FALSE
// Retrieval info: CBX_MODULE_PREFIX: ON

13
rtl/pll_3x_lowfreq.ppf Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone IV E" variation_name="pll_3x_lowfreq" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="areset" direction="input" scope="external" />
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="c1" direction="output" scope="external" source="clock" />
<pin name="c2" direction="output" scope="external" source="clock" />
<pin name="locked" direction="output" scope="external" />
</global>
</pinplan>

6
rtl/pll_3x_lowfreq.qip Normal file
View File

@ -0,0 +1,6 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "15.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll_3x_lowfreq.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_3x_lowfreq_bb.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_3x_lowfreq.ppf"]

376
rtl/pll_3x_lowfreq.v Normal file
View File

@ -0,0 +1,376 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: pll_3x_lowfreq.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
//
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 15.1.0 Build 185 10/21/2015 SJ Lite Edition
// ************************************************************
//Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, the Altera Quartus Prime License Agreement,
//the Altera MegaCore Function License Agreement, or other
//applicable license agreement, including, without limitation,
//that your use is for the sole purpose of programming logic
//devices manufactured by Altera and sold by Altera or its
//authorized distributors. Please refer to the applicable
//agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll_3x_lowfreq (
areset,
inclk0,
c0,
c1,
c2,
locked);
input areset;
input inclk0;
output c0;
output c1;
output c2;
output locked;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri0 areset;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [4:0] sub_wire0;
wire sub_wire4;
wire [0:0] sub_wire7 = 1'h0;
wire [2:2] sub_wire3 = sub_wire0[2:2];
wire [1:1] sub_wire2 = sub_wire0[1:1];
wire [0:0] sub_wire1 = sub_wire0[0:0];
wire c0 = sub_wire1;
wire c1 = sub_wire2;
wire c2 = sub_wire3;
wire locked = sub_wire4;
wire sub_wire5 = inclk0;
wire [1:0] sub_wire6 = {sub_wire7, sub_wire5};
altpll altpll_component (
.areset (areset),
.inclk (sub_wire6),
.clk (sub_wire0),
.locked (sub_wire4),
.activeclock (),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "LOW",
altpll_component.clk0_divide_by = 1,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 3,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 1,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 12,
altpll_component.clk1_phase_shift = "0",
altpll_component.clk2_divide_by = 1,
altpll_component.clk2_duty_cycle = 50,
altpll_component.clk2_multiply_by = 15,
altpll_component.clk2_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 149253,
altpll_component.intended_device_family = "Cyclone IV E",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll_3x_lowfreq",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "SOURCE_SYNCHRONOUS",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_USED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk2 = "PORT_USED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.self_reset_on_loss_lock = "OFF",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "20.100000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "80.400002"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "100.500000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "6.700"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "3"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "12"
// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "15"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_2x.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLK2 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "3"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "12"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "1"
// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "15"
// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "149253"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SOURCE_SYNCHRONOUS"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq_bb.v TRUE
// Retrieval info: CBX_MODULE_PREFIX: ON

682
rtl/scanconverter.v Normal file
View File

@ -0,0 +1,682 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
`define TRUE 1'b1
`define FALSE 1'b0
`define HI 1'b1
`define LO 1'b0
`define LINEMULT_DISABLE 2'h0
`define LINEMULT_DOUBLE 2'h1
`define LINEMULT_TRIPLE 2'h2
`define LINETRIPLE_M0 2'h0
`define LINETRIPLE_M1 2'h1
`define LINETRIPLE_M2 2'h2
`define LINETRIPLE_M3 2'h3
`define VSYNCGEN_LEN 6
`define VSYNCGEN_GENMID_BIT 0
`define VSYNCGEN_CHOPMID_BIT 1
`define FID_EVEN 1'b0
`define FID_ODD 1'b1
`define MIN_VALID_LINES 256 //power of 2 optimization -> ignore lower bits with comparison
`define FALSE_FIELD (fpga_vsyncgen[`VSYNCGEN_CHOPMID_BIT] & (FID_in == `FID_ODD))
`define VSYNC_LEADING_EDGE ((prev_vs == `HI) & (VSYNC_in == `LO))
`define VSYNC_TRAILING_EDGE ((prev_vs == `LO) & (VSYNC_in == `HI))
`define HSYNC_LEADING_EDGE ((prev_hs == `HI) & (HSYNC_in == `LO))
`define HSYNC_TRAILING_EDGE ((prev_hs == `LO) & (HSYNC_in == `HI))
module scanconverter (
input [7:0] R_in,
input [7:0] G_in,
input [7:0] B_in,
input FID_in,
input VSYNC_in,
input HSYNC_in,
input PCLK_in,
input [31:0] h_info,
input [31:0] v_info,
output reg [7:0] R_out,
output reg [7:0] G_out,
output reg [7:0] B_out,
output reg HSYNC_out,
output reg VSYNC_out,
output PCLK_out,
output reg DATA_enable,
output h_unstable,
output reg [1:0] fpga_vsyncgen,
output [2:0] pclk_lock,
output [2:0] pll_lock_lost,
output [10:0] lines_out
);
wire pclk_1x, pclk_2x, pclk_3x, pclk_4x, pclk_3x_h1x, pclk_3x_h4x, pclk_3x_h5x;
wire pclk_out_1x, pclk_out_2x, pclk_out_3x, pclk_out_4x, pclk_out_3x_h4x, pclk_out_3x_h5x;
wire linebuf_rdclock;
wire pclk_act;
wire [1:0] slid_act;
wire pclk_2x_lock, pclk_3x_lock, pclk_3x_lowfreq_lock;
wire HSYNC_act, VSYNC_act;
reg HSYNC_1x, HSYNC_2x, HSYNC_3x, HSYNC_3x_h1x, HSYNC_pp1;
reg VSYNC_1x, VSYNC_2x, VSYNC_pp1;
reg [11:0] HSYNC_start;
reg FID_prev;
wire DATA_enable_act;
reg DATA_enable_pp1;
wire [11:0] linebuf_hoffset; //Offset for line (max. 2047 pixels), MSB indicates which line is read/written
wire [11:0] hcnt_act;
reg [11:0] hcnt_1x, hcnt_2x, hcnt_3x, hcnt_4x, hcnt_3x_h1x, hcnt_3x_h4x, hcnt_3x_h5x;
wire [10:0] vcnt_act;
reg [10:0] vcnt_1x, vcnt_1x_tvp, vcnt_2x, lines_1x, lines_2x; //max. 2047
reg [9:0] vcnt_3x, vcnt_3x_h1x, lines_3x, lines_3x_h1x; //max. 1023
reg h_enable_3x_prev4x, h_enable_3x_prev3x_h4x, h_enable_3x_prev3x_h5x;
reg [1:0] hcnt_3x_h4x_ctr;
reg [1:0] hcnt_3x_h5x_ctr;
reg pclk_1x_prev3x, pclk_1x_prev3x_h1x, pclk_1x_prev3x_h4x;
reg [1:0] pclk_3x_cnt, pclk_3x_h1x_cnt;
reg [3:0] pclk_3x_h4x_cnt;
// Data enable
reg h_enable_1x, v_enable_1x;
reg h_enable_2x, v_enable_2x;
reg h_enable_3x, h_enable_3x_h1x, v_enable_3x, v_enable_3x_h1x;
reg prev_hs, prev_vs;
reg [11:0] hmax[0:1];
reg line_idx;
reg [23:0] warn_h_unstable, warn_pll_lock_lost, warn_pll_lock_lost_3x, warn_pll_lock_lost_3x_lowfreq;
reg [10:0] H_ACTIVE; //max. 2047
reg [7:0] H_BACKPORCH; //max. 255
reg [10:0] V_ACTIVE; //max. 2047
reg [5:0] V_BACKPORCH; //max. 63
reg V_SCANLINES;
reg V_SCANLINEDIR;
reg V_SCANLINEID;
reg [7:0] V_SCANLINESTR;
reg [5:0] V_MASK;
reg [1:0] H_LINEMULT;
reg [1:0] H_L3MODE;
reg [5:0] H_MASK;
//8 bits per component -> 16.7M colors
reg [7:0] R_1x, G_1x, B_1x, R_pp1, G_pp1, B_pp1;
wire [7:0] R_lbuf, G_lbuf, B_lbuf;
wire [7:0] R_act, G_act, B_act;
assign pclk_1x = PCLK_in;
assign pclk_lock = {pclk_2x_lock, pclk_3x_lock, pclk_3x_lowfreq_lock};
//Output sampled at the rising edge of active pclk
assign pclk_out_1x = PCLK_in;
assign pclk_out_2x = pclk_2x;
assign pclk_out_3x = pclk_3x;
assign pclk_out_4x = pclk_4x;
assign pclk_out_3x_h4x = pclk_3x_h4x;
assign pclk_out_3x_h5x = pclk_3x_h5x;
//Scanline generation
function [8:0] apply_scanlines;
input enable;
input dir;
input [8:0] data;
input [8:0] str;
input [1:0] actid;
input [1:0] lineid;
input pixid;
begin
if (enable & (dir == 1'b0) & (actid == lineid))
apply_scanlines = (data > str) ? (data-str) : 8'h00;
else if (enable & (dir == 1'b1) & (actid == pixid))
apply_scanlines = (data > str) ? (data-str) : 8'h00;
else
apply_scanlines = data;
end
endfunction
//Border masking
function [8:0] apply_mask;
input enable;
input [8:0] data;
input [11:0] hoffset;
input [11:0] hstart;
input [11:0] hend;
input [10:0] voffset;
input [10:0] vstart;
input [10:0] vend;
begin
if (enable & ((hoffset < hstart) | (hoffset >= hend) | (voffset < vstart) | (voffset >= vend)))
apply_mask = 8'h00;
else
apply_mask = data;
//apply_mask = (hoffset[0] ^ voffset[0]) ? 8'b11111111 : 8'b00000000;
end
endfunction
//Mux for active data selection
//
//Possible clock transfers:
//
// L3_MODE1: pclk_3x -> pclk_4x
// L3_MODE2: pclk_3x_h1x -> pclk_3x_h4x
// L3_MODE3: pclk_3x_h1x -> pclk_3x_h5x
//
//List of critical signals:
// DATA_enable_act, HSYNC_act
//
//Non-critical signals and inactive clock combinations filtered out in SDC
always @(*)
begin
case (H_LINEMULT)
`LINEMULT_DISABLE: begin
R_act = R_1x;
G_act = G_1x;
B_act = B_1x;
DATA_enable_act = (h_enable_1x & v_enable_1x);
PCLK_out = pclk_out_1x;
HSYNC_act = HSYNC_1x;
VSYNC_act = VSYNC_1x;
lines_out = lines_1x;
linebuf_rdclock = 0;
linebuf_hoffset = 0;
pclk_act = pclk_1x;
slid_act = {1'b0, vcnt_1x[0]};
hcnt_act = hcnt_1x;
vcnt_act = vcnt_1x;
end
`LINEMULT_DOUBLE: begin
R_act = R_lbuf;
G_act = G_lbuf;
B_act = B_lbuf;
DATA_enable_act = (h_enable_2x & v_enable_2x);
PCLK_out = pclk_out_2x;
HSYNC_act = HSYNC_2x;
VSYNC_act = VSYNC_2x;
lines_out = lines_2x;
linebuf_rdclock = pclk_2x;
linebuf_hoffset = hcnt_2x;
pclk_act = pclk_2x;
slid_act = {1'b0, vcnt_2x[0]};
hcnt_act = hcnt_2x;
vcnt_act = vcnt_2x>>1;
end
`LINEMULT_TRIPLE: begin
R_act = R_lbuf;
G_act = G_lbuf;
B_act = B_lbuf;
VSYNC_act = VSYNC_1x;
case (H_L3MODE)
`LINETRIPLE_M0: begin
DATA_enable_act = (h_enable_3x & v_enable_3x);
PCLK_out = pclk_out_3x;
HSYNC_act = HSYNC_3x;
lines_out = {1'b0, lines_3x};
linebuf_rdclock = pclk_3x;
linebuf_hoffset = hcnt_3x;
pclk_act = pclk_3x;
hcnt_act = hcnt_3x;
vcnt_act = vcnt_3x/2'h3; //divider generated
slid_act = (vcnt_3x % 2'h3);
end
`LINETRIPLE_M1: begin
DATA_enable_act = (h_enable_3x & v_enable_3x);
PCLK_out = pclk_out_4x;
HSYNC_act = HSYNC_3x;
lines_out = {1'b0, lines_3x};
linebuf_rdclock = pclk_4x;
linebuf_hoffset = hcnt_4x;
pclk_act = pclk_4x;
hcnt_act = hcnt_4x;
vcnt_act = vcnt_3x/2'h3; //divider generated
slid_act = (vcnt_3x % 2'h3);
end
`LINETRIPLE_M2: begin
DATA_enable_act = (h_enable_3x_h1x & v_enable_3x_h1x);
PCLK_out = pclk_out_3x_h4x;
HSYNC_act = HSYNC_3x_h1x;
lines_out = {1'b0, lines_3x_h1x};
linebuf_rdclock = pclk_3x_h4x;
linebuf_hoffset = hcnt_3x_h4x;
pclk_act = pclk_3x_h4x;
hcnt_act = hcnt_3x_h4x;
vcnt_act = vcnt_3x_h1x/2'h3; //divider generated
slid_act = (vcnt_3x_h1x % 2'h3);
end
`LINETRIPLE_M3: begin
DATA_enable_act = (h_enable_3x_h1x & v_enable_3x_h1x);
PCLK_out = pclk_out_3x_h5x;
HSYNC_act = HSYNC_3x_h1x;
lines_out = {1'b0, lines_3x_h1x};
linebuf_rdclock = pclk_3x_h5x;
linebuf_hoffset = hcnt_3x_h5x;
pclk_act = pclk_3x_h5x;
hcnt_act = hcnt_3x_h5x;
vcnt_act = vcnt_3x_h1x/2'h3; //divider generated
slid_act = (vcnt_3x_h1x % 2'h3);
end
endcase
end
default: begin
R_act = 0;
G_act = 0;
B_act = 0;
DATA_enable_act = 0;
PCLK_out = 0;
HSYNC_act = 0;
VSYNC_act = VSYNC_1x;
lines_out = 0;
linebuf_rdclock = 0;
linebuf_hoffset = 0;
pclk_act = 0;
slid_act = 0;
hcnt_act = 0;
vcnt_act = 0;
end
endcase
end
pll_2x pll_linedouble (
.areset ( (H_LINEMULT != `LINEMULT_DOUBLE) ),
.inclk0 ( PCLK_in ),
.c0 ( pclk_2x ),
.locked ( pclk_2x_lock )
);
pll_3x pll_linetriple (
.areset ( ((H_LINEMULT != `LINEMULT_TRIPLE) | H_L3MODE[1]) ),
.inclk0 ( PCLK_in ),
.c0 ( pclk_3x ), // sampling clock for 240p: 1280 or 960 samples & MODE0: 1280 output pixels from 1280 input samples (16:9)
.c1 ( pclk_4x ), // MODE1: 1280 output pixels from 960 input samples (960 drawn -> 4:3 aspect)
.locked ( pclk_3x_lock )
);
pll_3x_lowfreq pll_linetriple_lowfreq (
.areset ( (H_LINEMULT != `LINEMULT_TRIPLE) | ~H_L3MODE[1]),
.inclk0 ( PCLK_in ),
.c0 ( pclk_3x_h1x ), // sampling clock for 240p: 320 or 256 samples
.c1 ( pclk_3x_h4x ), // MODE2: 1280 output pixels from 320 input samples (960 drawn -> 4:3 aspect)
.c2 ( pclk_3x_h5x ), // MODE3: 1280 output pixels from 256 input samples (1024 drawn -> 5:4 aspect)
.locked ( pclk_3x_lowfreq_lock )
);
//TODO: add secondary buffers for interlaced signals with alternative field order
linebuf linebuf_rgb (
.data ( {R_1x, G_1x, B_1x} ), //or *_in?
.rdaddress ( linebuf_hoffset + (~line_idx << 11) ),
.rdclock ( linebuf_rdclock ),
.wraddress ( hcnt_1x + (line_idx << 11) ),
.wrclock ( pclk_1x ),
.wren ( 1'b1 ),
.q ( {R_lbuf, G_lbuf, B_lbuf} )
);
//Postprocess pipeline
always @(posedge pclk_act /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
R_pp1 <= apply_mask(1, R_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK);
G_pp1 <= apply_mask(1, G_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK);
B_pp1 <= apply_mask(1, B_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK);
HSYNC_pp1 <= HSYNC_act;
VSYNC_pp1 <= VSYNC_act;
DATA_enable_pp1 <= DATA_enable_act;
R_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, R_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]);
G_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, G_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]);
B_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, B_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]);
HSYNC_out <= HSYNC_pp1;
VSYNC_out <= VSYNC_pp1;
DATA_enable <= DATA_enable_pp1;
end
end
//Generate a warning signal from horizontal instability or PLL sync loss
always @(posedge pclk_1x /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
if (hmax[0] != hmax[1])
warn_h_unstable <= 1;
else if (warn_h_unstable != 0)
warn_h_unstable <= warn_h_unstable + 1'b1;
if ((H_LINEMULT == `LINEMULT_DOUBLE) & ~pclk_2x_lock)
warn_pll_lock_lost <= 1;
else if (warn_pll_lock_lost != 0)
warn_pll_lock_lost <= warn_pll_lock_lost + 1'b1;
if ((H_LINEMULT == `LINEMULT_TRIPLE) & ~H_L3MODE[1] & ~pclk_3x_lock)
warn_pll_lock_lost_3x <= 1;
else if (warn_pll_lock_lost_3x != 0)
warn_pll_lock_lost_3x <= warn_pll_lock_lost_3x + 1'b1;
if ((H_LINEMULT == `LINEMULT_TRIPLE) & H_L3MODE[1] & ~pclk_3x_lowfreq_lock)
warn_pll_lock_lost_3x_lowfreq <= 1;
else if (warn_pll_lock_lost_3x_lowfreq != 0)
warn_pll_lock_lost_3x_lowfreq <= warn_pll_lock_lost_3x_lowfreq + 1'b1;
end
end
assign h_unstable = (warn_h_unstable != 0);
assign pll_lock_lost = {(warn_pll_lock_lost != 0), (warn_pll_lock_lost_3x != 0), (warn_pll_lock_lost_3x_lowfreq != 0)};
//Buffer the inputs using input pixel clock and generate 1x signals
always @(posedge pclk_1x /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
if (`HSYNC_TRAILING_EDGE)
begin
hcnt_1x <= 0;
hmax[line_idx] <= hcnt_1x;
line_idx <= line_idx ^ 1'b1;
vcnt_1x <= vcnt_1x + 1'b1;
vcnt_1x_tvp <= vcnt_1x_tvp + 1'b1;
end
else
begin
hcnt_1x <= hcnt_1x + 1'b1;
end
if (`VSYNC_TRAILING_EDGE) //should be checked at every pclk_1x?
begin
vcnt_1x_tvp <= 0;
FID_prev <= FID_in;
// detect non-interlaced signal with odd-odd field signaling (TVP7002 detects it as interlaced with analog sync inputs).
// FID is updated at leading edge of VSYNC, so trailing edge has the status of current field.
if (FID_in == FID_prev)
fpga_vsyncgen[`VSYNCGEN_CHOPMID_BIT] <= `FALSE;
else if (FID_in == `FID_ODD) // TVP7002 falsely indicates field change with (vcnt < active_lines)
fpga_vsyncgen[`VSYNCGEN_CHOPMID_BIT] <= (vcnt_1x_tvp < `MIN_VALID_LINES);
if (!(`FALSE_FIELD))
begin
vcnt_1x <= 0;
lines_1x <= vcnt_1x;
end
//Read configuration data from CPU
H_ACTIVE <= h_info[26:16]; // Horizontal active length from by the CPU - 11bits (0...2047)
H_BACKPORCH <= h_info[7:0]; // Horizontal backporch length from by the CPU - 8bits (0...255)
H_LINEMULT <= h_info[31:30]; // Horizontal line multiply mode
H_L3MODE <= h_info[29:28]; // Horizontal line triple mode
H_MASK <= {h_info[11:8], 2'b00};
V_ACTIVE <= v_info[23:13]; // Vertical active length from by the CPU, 11bits (0...2047)
V_BACKPORCH <= v_info[5:0]; // Vertical backporch length from by the CPU, 6bits (0...64)
V_SCANLINES <= v_info[29];
V_SCANLINEDIR <= v_info[28];
V_SCANLINEID <= v_info[27];
V_SCANLINESTR <= ((v_info[26:24]+8'h01)<<5)-1'b1;
V_MASK <= {v_info[9:6], 2'b00};
end
prev_hs <= HSYNC_in;
prev_vs <= VSYNC_in;
// record start position of HSYNC
if (`HSYNC_LEADING_EDGE)
HSYNC_start <= hcnt_1x;
R_1x <= R_in;
G_1x <= G_in;
B_1x <= B_in;
HSYNC_1x <= HSYNC_in;
// Ignore possible invalid vsyncs generated by TVP7002
if (vcnt_1x > V_ACTIVE)
VSYNC_1x <= VSYNC_in;
// Check if extra vsync needed
fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] <= (lines_1x > ({1'b0, V_ACTIVE} << 1)) ? 1'b1 : 1'b0;
h_enable_1x <= ((hcnt_1x >= H_BACKPORCH) & (hcnt_1x < H_BACKPORCH + H_ACTIVE));
v_enable_1x <= ((vcnt_1x >= V_BACKPORCH) & (vcnt_1x < V_BACKPORCH + V_ACTIVE)); //- FID_in ???
/*HSYNC_out_debug <= HSYNC_in;
VSYNC_out_debug <= VSYNC_in;*/
end
end
//Generate 2x signals for linedouble
always @(posedge pclk_2x /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
if ((pclk_1x == 1'b0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x
hcnt_2x <= 0;
else if (hcnt_2x == hmax[~line_idx]) //line_idx_prev?
hcnt_2x <= 0;
else
hcnt_2x <= hcnt_2x + 1'b1;
if (hcnt_2x == 0)
vcnt_2x <= vcnt_2x + 1'b1;
if ((pclk_1x == 1'b0) & (fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] == 1'b1))
begin
if (`VSYNC_TRAILING_EDGE)
vcnt_2x <= 0;
else if (vcnt_2x == lines_1x)
begin
vcnt_2x <= 0;
lines_2x <= vcnt_2x;
end
end
else if ((pclk_1x == 1'b0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x
begin
vcnt_2x <= 0;
lines_2x <= vcnt_2x;
end
if (pclk_1x == 1'b0)
begin
if (fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] == 1'b1)
VSYNC_2x <= (vcnt_2x >= lines_1x - `VSYNCGEN_LEN) ? 1'b0 : 1'b1;
else if (vcnt_1x > V_ACTIVE)
VSYNC_2x <= VSYNC_in;
end
HSYNC_2x <= ~(hcnt_2x >= HSYNC_start);
//TODO: VSYNC_2x
h_enable_2x <= ((hcnt_2x >= H_BACKPORCH) & (hcnt_2x < H_BACKPORCH + H_ACTIVE));
v_enable_2x <= ((vcnt_2x >= (V_BACKPORCH<<1)) & (vcnt_2x < ((V_BACKPORCH + V_ACTIVE)<<1)));
end
end
//Generate 3x signals for linetriple M0
always @(posedge pclk_3x /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
if ((pclk_3x_cnt == 0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x
hcnt_3x <= 0;
else if (hcnt_3x == hmax[~line_idx]) //line_idx_prev?
hcnt_3x <= 0;
else
hcnt_3x <= hcnt_3x + 1'b1;
if (hcnt_3x == 0)
vcnt_3x <= vcnt_3x + 1'b1;
if ((pclk_3x_cnt == 0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x
begin
vcnt_3x <= 0;
lines_3x <= vcnt_3x;
end
HSYNC_3x <= ~(hcnt_3x >= HSYNC_start);
//TODO: VSYNC_3x
h_enable_3x <= ((hcnt_3x >= H_BACKPORCH) & (hcnt_3x < H_BACKPORCH + H_ACTIVE));
v_enable_3x <= ((vcnt_3x >= (3*V_BACKPORCH)) & (vcnt_3x < (3*(V_BACKPORCH + V_ACTIVE)))); //multiplier generated!!!
//read pclk_1x to examine when edges are synced (pclk_1x=1 @ 120deg & pclk_1x=0 @ 240deg)
if (((pclk_1x_prev3x == 1'b1) & (pclk_1x == 1'b0)) | (pclk_3x_cnt == 2'h2))
pclk_3x_cnt <= 0;
else
pclk_3x_cnt <= pclk_3x_cnt + 1'b1;
pclk_1x_prev3x <= pclk_1x;
end
end
//Generate 4x signals for linetriple M1
always @(posedge pclk_4x /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
// Can we sync reliably to h_enable_3x???
if ((h_enable_3x == 1) & (h_enable_3x_prev4x == 0))
hcnt_4x <= hcnt_3x - 160;
else
hcnt_4x <= hcnt_4x + 1'b1;
h_enable_3x_prev4x <= h_enable_3x;
end
end
//Generate 3x_h1x signals for linetriple M2 and M3
always @(posedge pclk_3x_h1x /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
if ((pclk_3x_h1x_cnt == 0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x
hcnt_3x_h1x <= 0;
else if (hcnt_3x_h1x == hmax[~line_idx]) //line_idx_prev?
hcnt_3x_h1x <= 0;
else
hcnt_3x_h1x <= hcnt_3x_h1x + 1'b1;
if (hcnt_3x_h1x == 0)
vcnt_3x_h1x <= vcnt_3x_h1x + 1'b1;
if ((pclk_3x_h1x_cnt == 0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x
begin
vcnt_3x_h1x <= 0;
lines_3x_h1x <= vcnt_3x_h1x;
end
HSYNC_3x_h1x <= ~(hcnt_3x_h1x >= HSYNC_start);
//TODO: VSYNC_3x_h1x
h_enable_3x_h1x <= ((hcnt_3x_h1x >= H_BACKPORCH) & (hcnt_3x_h1x < H_BACKPORCH + H_ACTIVE));
v_enable_3x_h1x <= ((vcnt_3x_h1x >= (3*V_BACKPORCH)) & (vcnt_3x_h1x < (3*(V_BACKPORCH + V_ACTIVE)))); //multiplier generated!!!
//read pclk_1x to examine when edges are synced (pclk_1x=1 @ 120deg & pclk_1x=0 @ 240deg)
if (((pclk_1x_prev3x_h1x == 1'b1) & (pclk_1x == 1'b0)) | (pclk_3x_h1x_cnt == 2'h2))
pclk_3x_h1x_cnt <= 0;
else
pclk_3x_h1x_cnt <= pclk_3x_h1x_cnt + 1'b1;
pclk_1x_prev3x_h1x <= pclk_1x;
end
end
//Generate 3x_h4x signals for for linetriple M2
always @(posedge pclk_3x_h4x /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
// Can we sync reliably to h_enable_3x???
if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h4x == 0))
hcnt_3x_h4x <= hcnt_3x_h1x - (160/3);
else if (hcnt_3x_h4x_ctr == 2'h0)
hcnt_3x_h4x <= hcnt_3x_h4x + 1'b1;
if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h4x == 0))
hcnt_3x_h4x_ctr <= 2'h1;
else if (hcnt_3x_h4x_ctr == 2'h2)
hcnt_3x_h4x_ctr <= 2'h0;
else
hcnt_3x_h4x_ctr <= hcnt_3x_h4x_ctr + 1'b1;
h_enable_3x_prev3x_h4x <= h_enable_3x_h1x;
end
end
//Generate 3x_h5x signals for for linetriple M3
always @(posedge pclk_3x_h5x /*or negedge reset_n*/)
begin
/*if (!reset_n)
begin
end
else*/
begin
// Can we sync reliably to h_enable_3x???
if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h5x == 0))
hcnt_3x_h5x <= hcnt_3x_h1x - (128/4);
else if (hcnt_3x_h5x_ctr == 2'h0)
hcnt_3x_h5x <= hcnt_3x_h5x + 1'b1;
if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h5x == 0))
hcnt_3x_h5x_ctr <= 2'h2;
else
hcnt_3x_h5x_ctr <= hcnt_3x_h5x_ctr + 1'b1;
h_enable_3x_prev3x_h5x <= h_enable_3x_h1x;
end
end
endmodule

2
rtl/timescale.v Normal file
View File

@ -0,0 +1,2 @@
`timescale 1ns / 10ps

150
rtl/videogen.v Normal file
View File

@ -0,0 +1,150 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module videogen (
input clk27,
input reset_n,
output [7:0] R_out,
output [7:0] G_out,
output [7:0] B_out,
output reg HSYNC_out,
output reg VSYNC_out,
output PCLK_out,
output reg ENABLE_out
);
//Parameters for 720x480@60Hz (858dots x 525lines), dotclk 27MHz -> 59.94Hz
parameter H_SYNCLEN = 62;
parameter H_BACKPORCH = 60;
parameter H_ACTIVE = 720;
parameter H_FRONTPORCH = 16;
parameter H_TOTAL = 858;
parameter V_SYNCLEN = 6;
parameter V_BACKPORCH = 30;
parameter V_ACTIVE = 480;
parameter V_FRONTPORCH = 9;
parameter V_TOTAL = 525;
parameter H_OVERSCAN = 40; //at both sides
parameter V_OVERSCAN = 16; //top and bottom
parameter H_AREA = 640;
parameter V_AREA = 448;
parameter H_BORDER = (H_AREA-512)/2;
parameter V_BORDER = (V_AREA-256)/2;
parameter X_START = H_SYNCLEN + H_BACKPORCH;
parameter Y_START = V_SYNCLEN + V_BACKPORCH;
//Counters
reg [9:0] h_cnt; //max. 1024
reg [9:0] v_cnt; //max. 1024
reg [9:0] xpos;
reg [9:0] ypos;
assign PCLK_out = clk27;
//R, G and B should be 0 outside of active area
assign R_out = ENABLE_out ? V_gen : 8'h00;
assign G_out = ENABLE_out ? V_gen : 8'h00;
assign B_out = ENABLE_out ? V_gen : 8'h00;
reg [7:0] V_gen;
//HSYNC gen (negative polarity)
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
begin
h_cnt <= 0;
HSYNC_out <= 0;
end
else
begin
//Hsync counter
if (h_cnt < H_TOTAL-1 )
h_cnt <= h_cnt + 1;
else
h_cnt <= 0;
//Hsync signal
HSYNC_out <= (h_cnt < H_SYNCLEN) ? 0 : 1;
end
end
//VSYNC gen (negative polarity)
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
begin
v_cnt <= 0;
VSYNC_out <= 0;
end
else
begin
if (h_cnt == 0)
begin
//Vsync counter
if (v_cnt < V_TOTAL-1 )
v_cnt <= v_cnt + 1;
else
v_cnt <= 0;
//Vsync signal
VSYNC_out <= (v_cnt < V_SYNCLEN) ? 0 : 1;
end
end
end
//Data gen
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
begin
V_gen <= 8'h00;
end
else
begin
if ((h_cnt < X_START+H_OVERSCAN) || (h_cnt >= X_START+H_OVERSCAN+H_AREA) || (v_cnt < Y_START+V_OVERSCAN) || (v_cnt >= Y_START+V_OVERSCAN+V_AREA))
V_gen <= (h_cnt[0] ^ v_cnt[0]) ? 8'hff : 8'h00;
else if ((h_cnt < X_START+H_OVERSCAN+H_BORDER) || (h_cnt >= X_START+H_OVERSCAN+H_AREA-H_BORDER) || (v_cnt < Y_START+V_OVERSCAN+V_BORDER) || (v_cnt >= Y_START+V_OVERSCAN+V_AREA-V_BORDER))
V_gen <= 8'h50;
else
V_gen <= (h_cnt - (X_START+H_OVERSCAN+H_BORDER)) >> 1;
/*else
V_gen <= 8'h00;*/
end
end
//Enable gen
always @(posedge clk27 or negedge reset_n)
begin
if (!reset_n)
begin
ENABLE_out <= 8'h00;
end
else
begin
ENABLE_out <= (h_cnt >= X_START && h_cnt < X_START + H_ACTIVE && v_cnt >= Y_START && v_cnt < Y_START + V_ACTIVE);
end
end
endmodule

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,196 @@
#include "hdmitx.h"
#include "edid.h"
#ifdef SUPPORT_EDID
static SYS_STATUS EDIDCheckSum(BYTE *pEDID) ;
static SYS_STATUS
EDIDCheckSum(BYTE *pEDID)
{
BYTE CheckSum ;
int i ;
if( !pEDID )
{
return ER_FAIL ;
}
for( i = 0, CheckSum = 0 ; i < 128 ; i++ )
{
CheckSum += pEDID[i] ; CheckSum &= 0xFF ;
}
return (CheckSum == 0)?ER_SUCCESS:ER_FAIL ;
}
SYS_STATUS
ParseVESAEDID(BYTE *pEDID)
{
if( ER_SUCCESS != EDIDCheckSum(pEDID) ) return ER_FAIL ;
if( pEDID[0] != 0 ||
pEDID[7] != 0 ||
pEDID[1] != 0xFF ||
pEDID[2] != 0xFF ||
pEDID[3] != 0xFF ||
pEDID[4] != 0xFF ||
pEDID[5] != 0xFF ||
pEDID[6] != 0xFF )
{
return ER_FAIL ; // not a EDID 1.3 standard block.
}
/////////////////////////////////////////////////////////
// if need to parse EDID property , put here.
/////////////////////////////////////////////////////////
return ER_SUCCESS ;
}
SYS_STATUS
ParseCEAEDID(BYTE *pCEAEDID, RX_CAP *pRxCap)
{
BYTE offset,End ;
BYTE count ;
BYTE tag ;
int i ;
if( !pCEAEDID || !pRxCap ) return ER_FAIL ;
pRxCap->ValidCEA = FALSE ;
if( ER_SUCCESS != EDIDCheckSum(pCEAEDID) ) return ER_FAIL ;
if( pCEAEDID[0] != 0x02 || pCEAEDID[1] != 0x03 ) return ER_SUCCESS ; // not a CEA BLOCK.
End = pCEAEDID[2] ; // CEA description.
pRxCap->VideoMode = pCEAEDID[3] ;
if (pRxCap->VideoMode & CEA_SUPPORT_YUV444)
OS_PRINTF("Support Color: YUV444\n");
if (pRxCap->VideoMode & CEA_SUPPORT_YUV422)
OS_PRINTF("Support Color: YUV422\n");
for( offset = 0 ; offset < 0x80 ; offset ++ )
{
if( (offset % 0x10) == 0 )
{
ErrorF("[%02X]", offset ) ;
}
else if((offset%0x10)==0x08)
{
ErrorF( " -" ) ;
}
ErrorF(" %02X",pCEAEDID[offset]) ;
if((offset%0x10)==0x0f)
{
ErrorF("\n") ;
}
}
pRxCap->VDOModeCount = 0 ;
pRxCap->idxNativeVDOMode = 0xff ;
for( offset = 4 ; offset < End ; )
{
tag = pCEAEDID[offset] >> 5 ;
count = pCEAEDID[offset] & 0x1f ;
switch( tag )
{
case 0x01: // Audio Data Block ;
pRxCap->AUDDesCount = count/3 ;
offset++ ;
for( i = 0 ; i < pRxCap->AUDDesCount ; i++ )
{
pRxCap->AUDDes[i].uc[0] = pCEAEDID[offset++] ;
pRxCap->AUDDes[i].uc[1] = pCEAEDID[offset++] ;
pRxCap->AUDDes[i].uc[2] = pCEAEDID[offset++] ;
}
break ;
case 0x02: // Video Data Block ;
//pRxCap->VDOModeCount = 0 ;
offset ++ ;
for( i = 0,pRxCap->idxNativeVDOMode = 0xff ; i < count ; i++, offset++ )
{
BYTE VIC ;
VIC = pCEAEDID[offset] & (~0x80) ;
OS_PRINTF("HDMI Sink VIC(Video Identify Code)=%d\n", VIC);
// if( FindModeTableEntryByVIC(VIC) != -1 )
{
pRxCap->VDOMode[pRxCap->VDOModeCount] = VIC ;
if( pCEAEDID[offset] & 0x80 )
{
pRxCap->idxNativeVDOMode = (BYTE)pRxCap->VDOModeCount ;
// iVideoModeSelect = pRxCap->VDOModeCount ;
}
pRxCap->VDOModeCount++ ;
}
}
break ;
case 0x03: // Vendor Specific Data Block ;
offset ++ ;
pRxCap->IEEEOUI = (ULONG)pCEAEDID[offset+2] ;
pRxCap->IEEEOUI <<= 8 ;
pRxCap->IEEEOUI += (ULONG)pCEAEDID[offset+1] ;
pRxCap->IEEEOUI <<= 8 ;
pRxCap->IEEEOUI += (ULONG)pCEAEDID[offset] ;
///////////////////////////////////////////////////////////
// For HDMI 1.3 extension handling.
///////////////////////////////////////////////////////////
pRxCap->dc.uc = 0 ;
pRxCap->MaxTMDSClock = 0 ;
pRxCap->lsupport.uc = 0 ;
pRxCap->ValidHDMI = (pRxCap->IEEEOUI==HDMI_IEEEOUI)? TRUE:FALSE ;
if( (pRxCap->ValidHDMI) && (count > 5 ))
{
// HDMI 1.3 extension
pRxCap->dc.uc = pCEAEDID[offset+5] ;
pRxCap->MaxTMDSClock = pCEAEDID[offset+6] ;
pRxCap->lsupport.uc = pCEAEDID[offset+7] ;
if(pRxCap->lsupport.info.Latency_Present)
{
pRxCap->V_Latency = pCEAEDID[offset+9] ;
pRxCap->A_Latency = pCEAEDID[offset+10] ;
}
if(pRxCap->lsupport.info.I_Latency_Present)
{
pRxCap->V_I_Latency = pCEAEDID[offset+11] ;
pRxCap->A_I_Latency = pCEAEDID[offset+12] ;
}
}
offset += count ; // ignore the remaind.
break ;
case 0x04: // Speaker Data Block ;
offset ++ ;
pRxCap->SpeakerAllocBlk.uc[0] = pCEAEDID[offset] ;
pRxCap->SpeakerAllocBlk.uc[1] = pCEAEDID[offset+1] ;
pRxCap->SpeakerAllocBlk.uc[2] = pCEAEDID[offset+2] ;
offset += 3 ;
break ;
case 0x05: // VESA Data Block ;
offset += count+1 ;
break ;
case 0x07: // Extended Data Block ;
offset += count+1 ; //ignore
break ;
default:
offset += count+1 ; // ignore
}
}
pRxCap->ValidCEA = TRUE ;
return ER_SUCCESS ;
}
#endif // SUPPORT_EDID

View File

@ -0,0 +1,11 @@
#ifndef HDMI_COMMON_H_
#define HDMI_COMMON_H_
typedef enum{
COLOR_RGB444 = 0,
COLOR_YUV422,
COLOR_YUV444,
COLOR_MODE_NUM
}COLOR_TYPE;
#endif /*HDMI_COMMON_H_*/

View File

@ -0,0 +1,314 @@
//#include "terasic_includes.h"
//#include "mcu.h"
#include "it6613_sys.h"
#include "hdmitx.h"
#include "HDMI_TX.h"
#include "edid.h"
int TX_HDP = FALSE;
extern BYTE bOutputColorMode;
extern BYTE bInputColorMode;
extern BOOL bChangeMode;
extern RX_CAP RxCapability;
extern BOOL bHDMIMode;
extern BOOL bAudioEnable;
BOOL ParseEDID();
INSTANCE InitInstanceData =
{
0,0, //I2C_DEV, I2C_ADDR
0, //bIntType (TxCLK active, Push-Pull Mode, INT active low)
0,/* | T_MODE_CCIR656 | T_MODE_SYNCEMB | T_MODE_INDDR */ // bInputVideoSignalType
B_AUDFMT_STD_I2S, // bOutputAudioMode, 0x00, standard i2s, rising edge to sample ws/i2s, not full packet mode REG[0xE1]
0,// bAudioChannelSwap
B_AUD_EN_I2S0 | B_AUD_I2S | M_AUD_16BIT, // bAudioChannelEnable, 0x01, REG[0xE0], defined in it6613_drv.h
AUDFS_48KHz, //0, //bAudFs,
0, // TMDSClock
TRUE,//bAuthenticated
TRUE,// bHDMIMode
FALSE,// bIntPOL
FALSE // bHPD
} ;
bool HDMITX_ChipVerify(void){
bool bPass = FALSE;
alt_u8 szID[4];
int i;
for(i=0;i<4;i++)
szID[i] = HDMITX_ReadI2C_Byte(i);
// if (szID[0] == 0x00 && szID[1] == 0xCA && szID[1] == 0x13 && szID[1] == 0x06) szID[0] ???
if ((szID[1] == 0xCA && szID[2] == 0x13 && szID[3] == 0x06) || (szID[1] == 0xCA && szID[2] == 0x13 && szID[3] == 0x16)){
bPass = TRUE;
printf("TX Chip Revision ID: %d\n", szID[0]);
}else{
printf("NG, Read TX Chip ID:%02X%02X%02X%02Xh (expected:00CA1306h)\n", szID[0], szID[1], szID[2], szID[3]);
}
return bPass;
}
bool HDMITX_Init(void){
bool bSuccess = TRUE;
HDMITX_Reset();
usleep(500*1000);
if (!HDMITX_ChipVerify()){
OS_PRINTF("Failed to find IT6613 HDMI-TX Chip.\n");
bSuccess = FALSE;
//return 0;
}
HDMITX_InitInstance(&InitInstanceData) ;
InitIT6613() ;
return bSuccess;
}
bool HDMITX_HPD(void){
if (TX_HDP)
return TRUE;
return FALSE;
}
void HDMITX_SetAVIInfoFrame(alt_u8 VIC, alt_u8 OutputColorMode, bool b16x9, bool ITU709)
{
AVI_InfoFrame AviInfo;
alt_u8 pixelrep = 0;
OS_PRINTF("HDMITX_SetAVIInfoFrame, VIC=%d, ColorMode=%d, Aspect-Ratio=%s, ITU709=%s\n",
VIC, OutputColorMode, b16x9?"16:9":"4:3", ITU709?"Yes":"No");
AviInfo.pktbyte.AVI_HB[0] = AVI_INFOFRAME_TYPE|0x80 ;
AviInfo.pktbyte.AVI_HB[1] = AVI_INFOFRAME_VER ;
AviInfo.pktbyte.AVI_HB[2] = AVI_INFOFRAME_LEN ;
switch(OutputColorMode)
{
case F_MODE_YUV444:
// AviInfo.info.ColorMode = 2 ;
AviInfo.pktbyte.AVI_DB[0] = (2<<5)|(1<<4) ;
break ;
case F_MODE_YUV422:
// AviInfo.info.ColorMode = 1 ;
AviInfo.pktbyte.AVI_DB[0] = (1<<5)|(1<<4) ;
break ;
case F_MODE_RGB444:
default:
// AviInfo.info.ColorMode = 0 ;
AviInfo.pktbyte.AVI_DB[0] = (0<<5)|(1<<4) ;
break ;
}
AviInfo.pktbyte.AVI_DB[0] |= 2; // indicate "no overscan"
AviInfo.pktbyte.AVI_DB[1] = 8 ;
AviInfo.pktbyte.AVI_DB[1] |= (!b16x9)?(1<<4):(2<<4) ; // 4:3 or 16:9
AviInfo.pktbyte.AVI_DB[1] |= (!ITU709)?(1<<6):(2<<6) ; // ITU709 or ITU601
AviInfo.pktbyte.AVI_DB[2] = (1<<3) ; // indicate "full-range RGB"
AviInfo.pktbyte.AVI_DB[3] = VIC ;
AviInfo.pktbyte.AVI_DB[4] = pixelrep & 3 ;
AviInfo.pktbyte.AVI_DB[5] = 0 ;
AviInfo.pktbyte.AVI_DB[6] = 0 ;
AviInfo.pktbyte.AVI_DB[7] = 0 ;
AviInfo.pktbyte.AVI_DB[8] = 0 ;
AviInfo.pktbyte.AVI_DB[9] = 0 ;
AviInfo.pktbyte.AVI_DB[10] = 0 ;
AviInfo.pktbyte.AVI_DB[11] = 0 ;
AviInfo.pktbyte.AVI_DB[12] = 0 ;
EnableAVIInfoFrame(TRUE, (unsigned char *)&AviInfo) ;
}
void HDMITX_ChangeVideoTiming(int VIC){
int OutputVideoTiming = VIC;
int HdmiColorMode;
switch(bOutputColorMode)
{
case F_MODE_YUV444:
HdmiColorMode = HDMI_YUV444;
break ;
case F_MODE_YUV422:
HdmiColorMode = HDMI_YUV422;
break ;
case F_MODE_RGB444:
default:
HdmiColorMode = HDMI_RGB444;
break ;
}
HDMITX_ChangeDisplayOption(OutputVideoTiming, HdmiColorMode); // just modify variable. Take effect when HDMITX_SetOutput is called in HDMITX_DevLoopProc
}
void HDMITX_ChangeVideoTimingAndColor(int VIC, COLOR_TYPE Color){
int OutputVideoTiming = VIC;
int HdmiColorMode;
switch(Color)
{
case COLOR_YUV444:
HdmiColorMode = HDMI_YUV444;
break ;
case COLOR_YUV422:
HdmiColorMode = HDMI_YUV422;
break ;
case COLOR_RGB444:
default:
HdmiColorMode = HDMI_RGB444;
break ;
}
HDMITX_ChangeDisplayOption(OutputVideoTiming, HdmiColorMode);
}
void HDMITX_DisableVideoOutput(void){
DisableVideoOutput();
}
void HDMITX_EnableVideoOutput(void){
HDMITX_SetOutput();
}
void HDMITX_SetColorSpace(COLOR_TYPE InputColor, COLOR_TYPE OutputColor){
// DisableVideoOutput();
bInputColorMode = InputColor;
bOutputColorMode = OutputColor;
// HDMITX_SetOutput();
}
bool HDMITX_IsSinkSupportYUV444(void){
bool bSupport = FALSE;
if (RxCapability.Valid && RxCapability.ValidHDMI && RxCapability.ValidCEA &&
(RxCapability.VideoMode & CEA_SUPPORT_YUV444))
bSupport = TRUE;
return bSupport;
}
bool HDMITX_IsSinkSupportYUV422(void){
bool bSupport = FALSE;
if (RxCapability.Valid && RxCapability.ValidHDMI && RxCapability.ValidCEA &&
(RxCapability.VideoMode & CEA_SUPPORT_YUV422))
bSupport = TRUE;
return bSupport;
}
bool HDMITX_IsSinkSupportColorDepth36(void){
bool bSupport = FALSE;
if (RxCapability.Valid && RxCapability.ValidHDMI && RxCapability.ValidCEA &&
RxCapability.dc.info.DC_36Bit)
bSupport = TRUE;
return bSupport;
}
bool HDMITX_IsSinkSupportColorDepth30(void){
bool bSupport = FALSE;
if (RxCapability.Valid && RxCapability.ValidHDMI && RxCapability.ValidCEA &&
RxCapability.dc.info.DC_30Bit)
bSupport = TRUE;
return bSupport;
}
void HDMITX_SetOutputColorDepth(int ColorDepth){
SetOutputColorDepthPhase(ColorDepth, 0);
}
bool HDMITX_DevLoopProc()
{
static BYTE PreHPDChange = 0;
static BYTE PreHPD = 0;
BYTE HPD, HPDChange ;
// Richard CheckHDMI(&HPD,&HPDChange) ;
CheckHDMITX(&HPD,&HPDChange) ;
if (HPD == PreHPD && HPDChange) // richard add
return FALSE;
TX_HDP = HPD;
PreHPD = HPD;
PreHPDChange = HPDChange;
if( HPDChange )
{
OS_PRINTF("HPDChange\n");
if( HPD )
{
OS_PRINTF("HPD=ON\n");
RxCapability.Valid = ParseEDID() ;
//bOutputColorMode = F_MODE_YUV444; //F_MODE_RGB444; // richard node. users can change color space here according to HDMI sink
if( RxCapability.Valid && RxCapability.ValidHDMI )
{
OS_PRINTF("HDMI Display found\n");
bHDMIMode = TRUE ;
if(RxCapability.VideoMode & (1<<6))
{
bAudioEnable = TRUE ;
}
#if 0 // richard, don't care edid, the output always RGB444
if( RxCapability.VideoMode & (1<<5))
{
bOutputColorMode &= ~F_MODE_CLRMOD_MASK ;
bOutputColorMode |= F_MODE_YUV444;
}
else if (RxCapability.VideoMode & (1<<4))
{
bOutputColorMode &= ~F_MODE_CLRMOD_MASK ;
bOutputColorMode |= F_MODE_YUV422 ;
}
#endif
}
else if (!RxCapability.Valid)
{
OS_PRINTF("Failed to read EDID\n");
// enable it when edid fail
bHDMIMode = TRUE ;
bAudioEnable = TRUE ;
}
else
{
OS_PRINTF("Invalid HDMI Display\n");
bHDMIMode = FALSE ;
bAudioEnable = FALSE ;
}
OS_PRINTF("HDMITX_SetOutput\n");
//HDMITX_SetOutput() ;
}
else
{
OS_PRINTF("HPD=OFF\n");
// unplug mode, ...
OS_PRINTF("DisableVideoOutput\n");
//DisableVideoOutput() ;
RxCapability.Valid = FALSE; // richard add
RxCapability.ValidHDMI = FALSE; // richard add
RxCapability.ValidCEA = FALSE; // richard add
}
}
else // no stable but need to process mode change procedure
{
if(bChangeMode && HPD)
{
OS_PRINTF("HDMITX_SetOutput\n");
HDMITX_SetOutput() ;
}
}
return HPDChange;
}

View File

@ -0,0 +1,29 @@
#ifndef HDMI_TX_H_
#define HDMI_TX_H_
#include "HDMI_COMMON.h"
#include "alt_types.h"
#include "hdmitx.h"
bool HDMITX_Init(void);
bool HDMITX_ChipVerify(void);
bool HDMITX_HPD(void);
void HDMITX_ChangeVideoTiming(int VIC);
void HDMITX_ChangeVideoTimingAndColor(int VIC, COLOR_TYPE Color);
void HDMITX_SetAVIInfoFrame(alt_u8 VIC, alt_u8 OutputColorMode, bool b16x9, bool ITU709);
void HDMITX_DisableVideoOutput(void);
void HDMITX_EnableVideoOutput(void);
void HDMITX_SetColorSpace(COLOR_TYPE InputColor, COLOR_TYPE OutputColor);
bool HDMITX_DevLoopProc(void);
bool HDMITX_IsSinkSupportYUV444(void);
bool HDMITX_IsSinkSupportYUV422(void);
bool HDMITX_IsSinkSupportColorDepth36(void);
bool HDMITX_IsSinkSupportColorDepth30(void);
void HDMITX_SetOutputColorDepth(int ColorDepth);
#endif /*HDMI_TX_H_*/

View File

@ -0,0 +1,129 @@
#ifndef _EDID_H_
#define _EDID_H_
#include "hdmitx.h"
#ifdef SUPPORT_EDID
/////////////////////////////////////////
// RX Capability.
/////////////////////////////////////////
typedef struct {
BYTE b16bit:1 ;
BYTE b20bit:1 ;
BYTE b24bit:1 ;
BYTE Rsrv:5 ;
} LPCM_BitWidth ;
typedef enum {
AUD_RESERVED_0 = 0 ,
AUD_LPCM,
AUD_AC3,
AUD_MPEG1,
AUD_MP3,
AUD_MPEG2,
AUD_AAC,
AUD_DTS,
AUD_ATRAC,
AUD_ONE_BIT_AUDIO,
AUD_DOLBY_DIGITAL_PLUS,
AUD_DTS_HD,
AUD_MAT_MLP,
AUD_DST,
AUD_WMA_PRO,
AUD_RESERVED_15
} AUDIO_FORMAT_CODE ;
typedef union {
struct {
BYTE channel:3 ;
BYTE AudioFormatCode:4 ;
BYTE Rsrv1:1 ;
BYTE b32KHz:1 ;
BYTE b44_1KHz:1 ;
BYTE b48KHz:1 ;
BYTE b88_2KHz:1 ;
BYTE b96KHz:1 ;
BYTE b176_4KHz:1 ;
BYTE b192KHz:1 ;
BYTE Rsrv2:1 ;
BYTE ucCode ;
} s ;
BYTE uc[3] ;
} AUDDESCRIPTOR ;
typedef union {
struct {
BYTE FL_FR:1 ;
BYTE LFE:1 ;
BYTE FC:1 ;
BYTE RL_RR:1 ;
BYTE RC:1 ;
BYTE FLC_FRC:1 ;
BYTE RLC_RRC:1 ;
BYTE Reserve:1 ;
BYTE Unuse[2] ;
} s ;
BYTE uc[3] ;
} SPK_ALLOC ;
#define CEA_SUPPORT_UNDERSCAN (1<<7)
#define CEA_SUPPORT_AUDIO (1<<6)
#define CEA_SUPPORT_YUV444 (1<<5)
#define CEA_SUPPORT_YUV422 (1<<4)
#define CEA_NATIVE_MASK 0xF
typedef union _tag_DCSUPPORT {
struct {
BYTE DVI_Dual:1 ;
BYTE Rsvd:2 ;
BYTE DC_Y444:1 ;
BYTE DC_30Bit:1 ;
BYTE DC_36Bit:1 ;
BYTE DC_48Bit:1 ;
BYTE SUPPORT_AI:1 ;
} info ;
BYTE uc ;
} DCSUPPORT ; // Richard Note: Color Depth
typedef union _LATENCY_SUPPORT{
struct {
BYTE Rsvd:6 ;
BYTE I_Latency_Present:1 ;
BYTE Latency_Present:1 ;
} info ;
BYTE uc ;
} LATENCY_SUPPORT ;
#define HDMI_IEEEOUI 0x0c03
typedef struct _RX_CAP{
BYTE Valid; // richard add
BYTE VideoMode ;
BYTE VDOModeCount ;
BYTE idxNativeVDOMode ;
BYTE VDOMode[128] ;
BYTE AUDDesCount ;
AUDDESCRIPTOR AUDDes[32] ;
ULONG IEEEOUI ;
DCSUPPORT dc ;
BYTE MaxTMDSClock ;
LATENCY_SUPPORT lsupport ;
BYTE V_Latency ;
BYTE A_Latency ;
BYTE V_I_Latency ;
BYTE A_I_Latency ;
SPK_ALLOC SpeakerAllocBlk ;
BYTE ValidCEA:1 ;
BYTE ValidHDMI:1 ;
} RX_CAP ;
SYS_STATUS ParseVESAEDID(BYTE *pEDID) ;
SYS_STATUS ParseCEAEDID(BYTE *pCEAEDID, RX_CAP *pRxCap) ;
#endif // SUPPORT_EDID
#endif // _EDID_H_

View File

@ -0,0 +1,119 @@
#ifndef _HDMITX_H_
#define _HDMITX_H_
#ifdef EXTERN_HDCPROM
#pragma message("Defined EXTERN_HDCPROM")
#endif // EXTERN_HDCPROM
#define SUPPORT_EDID
//#define SUPPORT_HDCP
#define SUPPORT_INPUTRGB
//#define SUPPORT_INPUTYUV444
//#define SUPPORT_INPUTYUV422
//#define SUPPORT_SYNCEMBEDDED
//#define SUPPORT_DEGEN
//#define SUPPORT_INPUTYUV // richard add
//#define INVERT_VID_LATCHEDGE //latch at falling edge
#ifdef SUPPORT_SYNCEMBEDDED
#pragma message("defined SUPPORT_SYNCEMBEDDED for Sync Embedded timing input or CCIR656 input.")
#endif
#ifndef _MCU_ // DSSSHA need large computation data rather than 8051 supported.
#define SUPPORT_DSSSHA
#endif
#if defined(SUPPORT_INPUTYUV444) || defined(SUPPORT_INPUTYUV422)
#define SUPPORT_INPUTYUV
#endif
/*#ifdef _MCU_
#include "mcu.h"
#else // not MCU
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "ioaccess.h"
#include "install.h"
#include "pc.h"
#endif // MCU*/
#include "typedef.h"
#include "HDMI_COMMON.h"
/*typedef unsigned char BYTE;
#define _CODE const
#define SYS_STATUS unsigned int
#define TRUE 1
#define FALSE 0*/
//#define NULL 0
//typedef unsigned char bool;
#include "Altera_UP_SD_Card_Avalon_Interface_mod.h"
#include "sysconfig.h"
// Hardwired to CPU reset
#define HDMITX_Reset(x)
#ifndef SUPPORT_HDCP
static SYS_STATUS
HDCP_Authenticate()
{
return ER_SUCCESS;
}
static void
HDCP_ResetAuth()
{
return;
}
static void
HDCP_ResumeAuthentication()
{
return;
}
#endif
//#include "edid.h"
// #include "dss_sha.h"
#include "it6613_drv.h"
#define HDMITX_INSTANCE_MAX 1
#define SIZEOF_CSCMTX 18
#define SIZEOF_CSCGAIN 6
#define SIZEOF_CSCOFFSET 3
///////////////////////////////////////////////////////////////////////
// Output Mode Type
///////////////////////////////////////////////////////////////////////
#define RES_ASPEC_4x3 0
#define RES_ASPEC_16x9 1
#define F_MODE_REPT_NO 0
#define F_MODE_REPT_TWICE 1
#define F_MODE_REPT_QUATRO 3
#define F_MODE_CSC_ITU601 0
#define F_MODE_CSC_ITU709 1
///////////////////////////////////////////////////////////////////////
// ROM OFFSET
///////////////////////////////////////////////////////////////////////
#define ROMOFF_INT_TYPE 0
#define ROMOFF_INPUT_VIDEO_TYPE 1
#define ROMOFF_OUTPUT_AUDIO_MODE 8
#define ROMOFF_AUDIO_CH_SWAP 9
#define TIMER_LOOP_LEN 10
#define MS(x) (((x)+(TIMER_LOOP_LEN-1))/TIMER_LOOP_LEN) ; // for timer loop
#endif // _HDMITX_H_

View File

@ -0,0 +1,82 @@
#include <stdio.h>
#include <unistd.h>
#include "system.h"
#include "i2c_opencores.h"
#include "hdmitx.h"
#include "it6613.h"
inline alt_u32 read_it2(alt_u32 regaddr) {
I2C_start(I2CA_BASE, IT_BASE, 0);
I2C_write(I2CA_BASE, regaddr, 0);
I2C_start(I2CA_BASE, IT_BASE, 1);
return I2C_read(I2CA_BASE,1);
}
inline void write_it2(alt_u32 regaddr, alt_u8 data) {
I2C_start(I2CA_BASE, IT_BASE, 0);
I2C_write(I2CA_BASE, regaddr, 0);
I2C_write(I2CA_BASE, data, 1);
}
BYTE I2C_Read_Byte(BYTE Addr,BYTE RegAddr) {
I2C_start(I2CA_BASE, Addr, 0);
I2C_write(I2CA_BASE, RegAddr, 0);
I2C_start(I2CA_BASE, Addr, 1);
return I2C_read(I2CA_BASE,1);
}
SYS_STATUS I2C_Write_Byte(BYTE Addr,BYTE RegAddr,BYTE Data) {
I2C_start(I2CA_BASE, Addr, 0);
I2C_write(I2CA_BASE, RegAddr, 0);
I2C_write(I2CA_BASE, Data, 1);
return 0;
}
SYS_STATUS I2C_Read_ByteN(BYTE Addr,BYTE RegAddr,BYTE *pData,int N) {
int i;
for (i=0; i<N; i++)
pData[i] = I2C_Read_Byte(Addr, RegAddr+i);
return 0;
}
SYS_STATUS I2C_Write_ByteN(BYTE Addr,BYTE RegAddr,BYTE *pData,int N) {
int i;
for (i=0; i<N; i++)
I2C_Write_Byte(Addr, RegAddr+i, pData[i]);
return 0;
}
BYTE HDMITX_ReadI2C_Byte(BYTE RegAddr) {
return read_it2(RegAddr);
}
SYS_STATUS HDMITX_WriteI2C_Byte(BYTE RegAddr,BYTE val) {
write_it2(RegAddr, val);
return 0;
}
SYS_STATUS HDMITX_ReadI2C_ByteN(BYTE RegAddr,BYTE *pData,int N) {
int i;
for (i=0; i<N; i++)
pData[i] = HDMITX_ReadI2C_Byte(RegAddr+i);
return 0;
}
SYS_STATUS HDMITX_WriteI2C_ByteN(BYTE RegAddr,BYTE *pData,int N) {
int i;
for (i=0; i<N; i++)
HDMITX_WriteI2C_Byte(RegAddr+i, pData[i]);
return 0;
}
void DelayMS(unsigned int ms) {
usleep(1000*ms);
}

View File

@ -0,0 +1,83 @@
#include <stdio.h>
#include <unistd.h>
#include "system.h"
#include "i2c_opencores.h"
#include "it6613.h"
volatile alt_u8 cur_bank;
inline void select_bank_it(alt_u8 bank) {
cur_bank = bank;
I2C_start(I2CA_BASE, IT_BASE, 0);
I2C_write(I2CA_BASE, IT_CURBANK, 0);
I2C_write(I2CA_BASE, cur_bank, 1);
}
inline alt_u32 read_it(alt_u32 regaddr) {
if ((regaddr > 0xFF) && (cur_bank == 0))
select_bank_it(1);
else if ((regaddr <= 0xFF) && (cur_bank == 1))
select_bank_it(0);
I2C_start(I2CA_BASE, IT_BASE, 0);
I2C_write(I2CA_BASE, (regaddr & 0xFF), 1);
I2C_start(I2CA_BASE, IT_BASE, 1);
return I2C_read(I2CA_BASE,1);
}
inline void write_it(alt_u32 regaddr, alt_u8 data) {
if ((regaddr > 0xFF) && (cur_bank == 0))
select_bank_it(1);
else if ((regaddr <= 0xFF) && (cur_bank == 1))
select_bank_it(0);
I2C_start(I2CA_BASE, IT_BASE, 0);
I2C_write(I2CA_BASE, (regaddr & 0xFF), 0);
I2C_write(I2CA_BASE, data, 1);
}
/*inline void reset_it() {
usleep(100000);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00);
usleep(100000);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x01);
usleep(100000);
}*/
int init_it() {
alt_u32 vendor_id, device_id;
alt_u32 i;
cur_bank = 0;
select_bank_it(cur_bank);
vendor_id = read_it(IT_VENDORID);
device_id = read_it(IT_DEVICEID);
printf("VEN: 0x%.2X, DEV: 0x%.2X\n", vendor_id, device_id);
if (!((vendor_id == IT6613_VENDORID) && (device_id == IT6613_DEVICEID)))
return -1;
write_it(REG_TX_SW_RST,B_REF_RST|B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ;
usleep(1000);
write_it(REG_TX_SW_RST,B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ;
write_it(IT_DRIVECTRL, 0x10);
write_it(IT_HDMIMODE, 0);
for (i=0xC1; i<=0xD0; i++)
write_it(i, 0);
write_it(IT_OUTCOLOR, 0);
// enable video
//HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ;
write_it(REG_TX_SW_RST, B_AUD_RST|B_AREF_RST|B_HDCP_RST) ;
usleep(1000);
return 0;
}

View File

@ -0,0 +1,29 @@
#ifndef IT6613_H_
#define IT6613_H_
//#define I2C_DEBUG
//#define I2CA_HDMI_BASE I2C_OPENCORES_1_BASE
#define I2CA_BASE I2C_OPENCORES_0_BASE
#define IT6613_VENDORID 0xCA
#define IT6613_DEVICEID 0x13
#define IT_BASE (0x98>>1)
#define IT_VENDORID 0x01
#define IT_DEVICEID 0x02
#define IT_RESET 0x04
#define IT_CURBANK 0x0F
#define IT_DRIVECTRL 0x61
#define IT_HDMIMODE 0xC0
#define IT_OUTCOLOR 0x158
#define REG_TX_SW_RST 0x04
#define B_ENTEST (1<<7)
#define B_REF_RST (1<<5)
#define B_AREF_RST (1<<4)
#define B_VID_RST (1<<3)
#define B_AUD_RST (1<<2)
#define B_HDMI_RST (1<<1)
#define B_HDCP_RST (1<<0)
#endif /* IT6613_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,844 @@
#ifndef _IT6613_H_
#define _IT6613_H_
//#define EXTERN_HDCPROM
/////////////////////////////////////////
// DDC Address
/////////////////////////////////////////
#define DDC_HDCP_ADDRESS 0x74
#define DDC_EDID_ADDRESS 0xA0
#define DDC_FIFO_MAXREQ 0x20
// I2C address
#define _80MHz 80000000
#define HDMI_TX_I2C_SLAVE_ADDR 0x98 // PCADR is ground, if PCADR=1, address=0x9A
///////////////////////////////////////////////////////////////////////
// Register offset
///////////////////////////////////////////////////////////////////////
#define REG_TX_VENDOR_ID0 0x00
#define REG_TX_VENDOR_ID1 0x01
#define REG_TX_DEVICE_ID0 0x02
#define REG_TX_DEVICE_ID1 0x03
#define O_DEVID 0
#define M_DEVID 0xF
#define O_REVID 4
#define M_REVID 0xF
#define REG_TX_SW_RST 0x04
#define B_ENTEST (1<<7)
#define B_REF_RST (1<<5)
#define B_AREF_RST (1<<4)
#define B_VID_RST (1<<3)
#define B_AUD_RST (1<<2)
#define B_HDMI_RST (1<<1)
#define B_HDCP_RST (1<<0)
#define REG_TX_INT_CTRL 0x05
#define B_INTPOL_ACTL 0
#define B_INTPOL_ACTH (1<<7)
#define B_INT_PUSHPULL 0
#define B_INT_OPENDRAIN (1<<6)
#define REG_TX_INT_STAT1 0x06
#define B_INT_AUD_OVERFLOW (1<<7)
#define B_INT_ROMACQ_NOACK (1<<6)
#define B_INT_RDDC_NOACK (1<<5)
#define B_INT_DDCFIFO_ERR (1<<4)
#define B_INT_ROMACQ_BUS_HANG (1<<3)
#define B_INT_DDC_BUS_HANG (1<<2)
#define B_INT_RX_SENSE (1<<1)
#define B_INT_HPD_PLUG (1<<0)
#define REG_TX_INT_STAT2 0x07
#define B_INT_HDCP_SYNC_DET_FAIL (1<<7)
#define B_INT_VID_UNSTABLE (1<<6)
#define B_INT_PKTACP (1<<5)
#define B_INT_PKTNULL (1<<4)
#define B_INT_PKTGENERAL (1<<3)
#define B_INT_KSVLIST_CHK (1<<2)
#define B_INT_AUTH_DONE (1<<1)
#define B_INT_AUTH_FAIL (1<<0)
#define REG_TX_INT_STAT3 0x08
#define B_INT_AUD_CTS (1<<6)
#define B_INT_VSYNC (1<<5)
#define B_INT_VIDSTABLE (1<<4)
#define B_INT_PKTMPG (1<<3)
#define B_INT_PKTSPD (1<<2)
#define B_INT_PKTAUD (1<<1)
#define B_INT_PKTAVI (1<<0)
#define REG_TX_INT_MASK1 0x09
#define B_AUDIO_OVFLW_MASK (1<<7)
#define B_DDC_NOACK_MASK (1<<5)
#define B_DDC_FIFO_ERR_MASK (1<<4)
#define B_DDC_BUS_HANG_MASK (1<<2)
#define B_RXSEN_MASK (1<<1)
#define B_HPD_MASK (1<<0)
#define REG_TX_INT_MASK2 0x0A
#define B_PKT_AVI_MASK (1<<7)
#define B_PKT_VID_UNSTABLE_MASK (1<<6)
#define B_PKT_ACP_MASK (1<<5)
#define B_PKT_NULL_MASK (1<<4)
#define B_PKT_GEN_MASK (1<<3)
#define B_KSVLISTCHK_MASK (1<<2)
#define B_T_AUTH_DONE_MASK (1<<1)
#define B_AUTH_FAIL_MASK (1<<0)
#define REG_TX_INT_MASK3 0x0B
#define B_HDCP_SYNC_DET_FAIL_MASK (1<<6)
#define B_AUDCTS_MASK (1<<5)
#define B_VSYNC_MASK (1<<4)
#define B_VIDSTABLE_MASK (1<<3)
#define B_PKT_MPG_MASK (1<<2)
#define B_PKT_SPD_MASK (1<<1)
#define B_PKT_AUD_MASK (1<<0)
#define REG_TX_INT_CLR0 0x0C
#define B_CLR_PKTACP (1<<7)
#define B_CLR_PKTNULL (1<<6)
#define B_CLR_PKTGENERAL (1<<5)
#define B_CLR_KSVLISTCHK (1<<4)
#define B_CLR_AUTH_DONE (1<<3)
#define B_CLR_AUTH_FAIL (1<<2)
#define B_CLR_RXSENSE (1<<1)
#define B_CLR_HPD (1<<0)
#define REG_TX_INT_CLR1 0x0D
#define B_CLR_VSYNC (1<<7)
#define B_CLR_VIDSTABLE (1<<6)
#define B_CLR_PKTMPG (1<<5)
#define B_CLR_PKTSPD (1<<4)
#define B_CLR_PKTAUD (1<<3)
#define B_CLR_PKTAVI (1<<2)
#define B_CLR_HDCP_SYNC_DET_FAIL (1<<1)
#define B_CLR_VID_UNSTABLE (1<<0)
#define REG_TX_SYS_STATUS 0x0E
// readonly
#define B_INT_ACTIVE (1<<7)
#define B_HPDETECT (1<<6)
#define B_RXSENDETECT (1<<5)
#define B_TXVIDSTABLE (1<<4)
// read/write
#define O_CTSINTSTEP 2
#define M_CTSINTSTEP (3<<2)
#define B_CLR_AUD_CTS (1<<1)
#define B_INTACTDONE (1<<0)
#define REG_TX_BANK_CTRL 0x0F
#define B_BANK0 0
#define B_BANK1 1
// DDC
#define REG_TX_DDC_MASTER_CTRL 0x10
#define B_MASTERROM (1<<1)
#define B_MASTERDDC (0<<1)
#define B_MASTERHOST (1<<0)
#define B_MASTERHDCP (0<<0)
#define REG_TX_DDC_HEADER 0x11
#define REG_TX_DDC_REQOFF 0x12
#define REG_TX_DDC_REQCOUNT 0x13
#define REG_TX_DDC_EDIDSEG 0x14
#define REG_TX_DDC_CMD 0x15
#define CMD_DDC_SEQ_BURSTREAD 0
#define CMD_LINK_CHKREAD 2
#define CMD_EDID_READ 3
#define CMD_FIFO_CLR 9
#define CMD_GEN_SCLCLK 0xA
#define CMD_DDC_ABORT 0xF
#define REG_TX_DDC_STATUS 0x16
#define B_DDC_DONE (1<<7)
#define B_DDC_ACT (1<<6)
#define B_DDC_NOACK (1<<5)
#define B_DDC_WAITBUS (1<<4)
#define B_DDC_ARBILOSE (1<<3)
#define B_DDC_ERROR (B_DDC_NOACK|B_DDC_WAITBUS|B_DDC_ARBILOSE)
#define B_DDC_FIFOFULL (1<<2)
#define B_DDC_FIFOEMPTY (1<<1)
#define REG_TX_DDC_READFIFO 0x17
#define REG_TX_ROM_STARTADDR 0x18
#define REG_TX_HDCP_HEADER 0x19
#define REG_TX_ROM_HEADER 0x1A
#define REG_TX_BUSHOLD_T 0x1B
#define REG_TX_ROM_STAT 0x1C
#define B_ROM_DONE (1<<7)
#define B_ROM_ACTIVE (1<<6)
#define B_ROM_NOACK (1<<5)
#define B_ROM_WAITBUS (1<<4)
#define B_ROM_ARBILOSE (1<<3)
#define B_ROM_BUSHANG (1<<2)
// HDCP
#define REG_TX_AN_GENERATE 0x1F
#define B_START_CIPHER_GEN 1
#define B_STOP_CIPHER_GEN 0
#define REG_TX_HDCP_DESIRE 0x20
#define B_ENABLE_HDPC11 (1<<1)
#define B_CPDESIRE (1<<0)
#define REG_TX_AUTHFIRE 0x21
#define REG_TX_LISTCTRL 0x22
#define B_LISTFAIL (1<<1)
#define B_LISTDONE (1<<0)
#define REG_TX_AKSV 0x23
#define REG_TX_AKSV0 0x23
#define REG_TX_AKSV1 0x24
#define REG_TX_AKSV2 0x25
#define REG_TX_AKSV3 0x26
#define REG_TX_AKSV4 0x27
#define REG_TX_AN 0x28
#define REG_TX_AN_GEN 0x30
#define REG_TX_ARI 0x38
#define REG_TX_ARI0 0x38
#define REG_TX_ARI1 0x39
#define REG_TX_APJ 0x3A
#define REG_TX_BKSV 0x3B
#define REG_TX_BRI 0x40
#define REG_TX_BRI0 0x40
#define REG_TX_BRI1 0x41
#define REG_TX_BPJ 0x42
#define REG_TX_BCAP 0x43
#define B_CAP_HDMI_REPEATER (1<<6)
#define B_CAP_KSV_FIFO_RDY (1<<5)
#define B_CAP_HDMI_FAST_MODE (1<<4)
#define B_CAP_HDCP_1p1 (1<<1)
#define B_CAP_FAST_REAUTH (1<<0)
#define REG_TX_BSTAT 0x44
#define REG_TX_BSTAT0 0x44
#define REG_TX_BSTAT1 0x45
#define B_CAP_HDMI_MODE (1<<12)
#define B_CAP_DVI_MODE (0<<12)
#define B_MAX_CASCADE_EXCEEDED (1<<11)
#define M_REPEATER_DEPTH (0x7<<8)
#define O_REPEATER_DEPTH 8
#define B_DOWNSTREAM_OVER (1<<7)
#define M_DOWNSTREAM_COUNT 0x7F
#define REG_TX_AUTH_STAT 0x46
#define B_T_AUTH_DONE (1<<7)
#define REG_TX_CLK_CTRL0 0x58
#define O_OSCLK_SEL 5
#define M_OSCLK_SEL 3
#define B_AUTO_OVER_SAMPLING_CLOCK (1<<4)
#define O_EXT_MCLK_SEL 2
#define M_EXT_MCLK_SEL (3<<O_EXT_MCLK_SEL)
#define B_EXT_128FS (0<<O_EXT_MCLK_SEL)
#define B_EXT_256FS (1<<O_EXT_MCLK_SEL)
#define B_EXT_512FS (2<<O_EXT_MCLK_SEL)
#define B_EXT_1024FS (3<<O_EXT_MCLK_SEL)
#define REG_TX_SHA_SEL 0x50
#define REG_TX_SHA_RD_BYTE1 0x51
#define REG_TX_SHA_RD_BYTE2 0x52
#define REG_TX_SHA_RD_BYTE3 0x53
#define REG_TX_SHA_RD_BYTE4 0x54
#define REG_TX_AKSV_RD_BYTE5 0x55
#define REG_TX_CLK_CTRL1 0x59
#define B_EN_TXCLK_COUNT (1<<5)
#define B_VDO_LATCH_EDGE (1<<3)
#define M_AUD_DIV 3
#define B_AUD_NODIV 0
#define B_AUD_DIV2 1
#define B_AUD_DIV4 3
#define B_AUD_NODEF 2
#define REG_TX_CLK_STATUS1 0x5E
#define REG_TX_CLK_STATUS2 0x5F
#define B_IP_LOCK (1<<7)
#define B_XP_LOCK (1<<6)
#define B_OSF_LOCK (1<<5)
#define REG_TX_AFE_DRV_CTRL 0x61
#define B_AFE_DRV_PWD (1<<5)
#define B_AFE_DRV_RST (1<<4)
#define B_AFE_DRV_PDRXDET (1<<2)
#define B_AFE_DRV_TERMON (1<<1)
#define B_AFE_DRV_ENCAL (1<<0)
#define REG_TX_AFE_XP_CTRL 0x62
#define B_AFE_XP_GAINBIT (1<<7)
#define B_AFE_XP_PWDPLL (1<<6)
#define B_AFE_XP_ENI (1<<5)
#define B_AFE_XP_ER0 (1<<4)
#define B_AFE_XP_RESETB (1<<3)
#define B_AFE_XP_PWDI (1<<2)
#define B_AFE_XP_DEI (1<<1)
#define B_AFE_XP_DER (1<<0)
#define REG_TX_AFE_ISW_CTRL 0x63
#define B_AFE_RTERM_SEL (1<<7)
#define B_AFE_IP_BYPASS (1<<6)
#define M_AFE_DRV_ISW (7<<3)
#define O_AFE_DRV_ISW 3
#define B_AFE_DRV_ISWK 7
#define REG_TX_AFE_IP_CTRL 0x64
#define B_AFE_IP_GAINBIT (1<<7)
#define B_AFE_IP_PWDPLL (1<<6)
#define M_AFE_IP_CKSEL (3<<4)
#define O_AFE_IP_CKSEL 4
#define B_AFE_IP_ER0 (1<<3)
#define B_AFE_IP_RESETB (1<<2)
#define B_AFE_IP_ENC (1<<1)
#define B_AFE_IP_EC1 (1<<0)
#define REG_TX_AFE_RING 0x65
#define B_AFE_CAL_UPDATE (1<<7)
#define B_AFE_CAL_MANUAL (1<<6)
#define M_AFE_CAL_CLK_MODE (3<<4)
#define O_AFE_CAL_CLK_MODE 4
#define O_AFE_DRV_VSW 2
#define M_AFE_DRV_VSW (3<<2)
#define B_AFE_RING_SLOW (1<<1)
#define B_AFE_RING_FAST (1<<0)
#define REG_TX_AFE_TEST 0x66
#define B_AFE_AFE_ENTEST (1<<6)
#define B_AFE_AFE_ENBIST (1<<5)
#define M_AFE_CAL_RTERM_MANUAL 0x1F
#define REG_TX_AFE_LFSR 0x67
#define B_AFE_AFELFSR_VAL (1<<7)
#define B_AFE_DIS_AFELFSR (1<<6)
#define M_AFE_RTERM_VAOUE 0xF
//
//#define REG_TX_AFE_DRV_CTRL 0x61
// #define M_AFE_DRV_SR (3<<2)
// #define O_AFE_DRV_SR 2
// #define B_AFE_DRV_RST (1<<4)
// #define B_AFE_DRV_PWD (1<<5)
// #define B_AFE_DRV_ENBIST (1<<6)
//
//#define REG_TX_AFE_XP_CTRL1 0x62
// #define B_AFE_XP_GAINBIT (1<<7)
// #define B_AFE_XP_PWDPLL (1<<6)
// #define B_AFE_XP_ENI (1<<5)
// #define B_AFE_XP_ER0 (1<<4)
// #define B_AFE_XP_RESETB (1<<3)
// #define B_AFE_XP_PWDI (1<<2)
// #define B_AFE_XP_DEI (1<<1)
// #define B_AFE_XP_BYPASS (1<<0)
//
//#define REG_TX_AFE_XP_CTRL2 0x63
// #define B_XP_ENCLKX5 (1<<3)
// #define M_XP_CLKSEL 3
// #define B_XP_CLKSEL_HALF_PCLKHV 0
// #define B_XP_CLKSEL_1_PCLKHV 1
// #define B_XP_CLKSEL_2_PCLKHV 2
// #define B_XP_CLKSEL_4_PCLKHV 3
//
//
//#define REG_TX_AFE_IP_CTRL 0x64
// #define B_AFE_IP_GAINBIT (1<<6)
// #define B_AFE_IP_PWDPLL (1<<5)
// #define B_AFE_IP_SEDB (1<<4)
// #define B_AFE_IP_ER0 (1<<3)
// #define B_AFE_IP_RESETB (1<<2)
// #define B_AFE_IP_PDIV1 (1<<1)
// #define B_AFE_IP_ENCB (1<<0)
//
//#define REG_TX_AFE_RING 0x65
// #define B_AFE_RING_FAST (1<<0)
// #define B_AFE_RING_SLOW (1<<1)
// #define M_AFE_DRV_VSW (3<<2)
// #define B_AFE_VSW_NOENH 0
// #define B_AFE_VSW_12ENH (1<<2)
// #define B_AFE_VSW_24ENH (2<<2)
// #define B_AFE_VSW_35ENH (3<<2)
// Input Data Format Register
#define REG_TX_INPUT_MODE 0x70
#define O_INCLKDLY 0
#define M_INCLKDLY 3
#define B_INDDR (1<<2)
#define B_SYNCEMB (1<<3)
#define B_2X656CLK (1<<4)
#define B_PCLKDIV2 (1<<5)
#define M_INCOLMOD (3<<6)
#define B_IN_RGB 0
#define B_IN_YUV422 (1<<6)
#define B_IN_YUV444 (2<<6)
#define REG_TX_TXFIFO_RST 0x71
#define B_ENAVMUTERST 1
#define B_TXFFRST (1<<1)
#define REG_TX_CSC_CTRL 0x72
#define B_CSC_BYPASS 0
#define B_CSC_RGB2YUV 2
#define B_CSC_YUV2RGB 3
#define M_CSC_SEL 3
#define B_TX_EN_DITHER (1<<7)
#define B_TX_EN_UDFILTER (1<<6)
#define B_TX_DNFREE_GO (1<<5)
#define REG_TX_CSC_YOFF 0x73
#define REG_TX_CSC_COFF 0x74
#define REG_TX_CSC_RGBOFF 0x75
#define REG_TX_CSC_MTX11_L 0x76
#define REG_TX_CSC_MTX11_H 0x77
#define REG_TX_CSC_MTX12_L 0x78
#define REG_TX_CSC_MTX12_H 0x79
#define REG_TX_CSC_MTX13_L 0x7A
#define REG_TX_CSC_MTX13_H 0x7B
#define REG_TX_CSC_MTX21_L 0x7C
#define REG_TX_CSC_MTX21_H 0x7D
#define REG_TX_CSC_MTX22_L 0x7E
#define REG_TX_CSC_MTX22_H 0x7F
#define REG_TX_CSC_MTX23_L 0x80
#define REG_TX_CSC_MTX23_H 0x81
#define REG_TX_CSC_MTX31_L 0x82
#define REG_TX_CSC_MTX31_H 0x83
#define REG_TX_CSC_MTX32_L 0x84
#define REG_TX_CSC_MTX32_H 0x85
#define REG_TX_CSC_MTX33_L 0x86
#define REG_TX_CSC_MTX33_H 0x87
#define REG_TX_CSC_GAIN1V_L 0x88
#define REG_TX_CSC_GAIN1V_H 0x89
#define REG_TX_CSC_GAIN2V_L 0x8A
#define REG_TX_CSC_GAIN2V_H 0x8B
#define REG_TX_CSC_GAIN3V_L 0x8C
#define REG_TX_CSC_GAIN3V_H 0x8D
#define REG_TX_HVPol 0x90
#define REG_TX_HfPixel 0x91
#define REG_TX_HSSL 0x95
#define REG_TX_HSEL 0x96
#define REG_TX_HSH 0x97
#define REG_TX_VSS1 0xA0
#define REG_TX_VSE1 0xA1
#define REG_TX_VSS2 0xA2
#define REG_TX_VSE2 0xA3
// HDMI General Control Registers
#define REG_TX_HDMI_MODE 0xC0
#define B_TX_HDMI_MODE 1
#define B_TX_DVI_MODE 0
#define REG_TX_AV_MUTE 0xC1
#define REG_TX_GCP 0xC1
#define B_CLR_AVMUTE 0
#define B_SET_AVMUTE 1
#define B_TX_SETAVMUTE (1<<0)
#define B_BLUE_SCR_MUTE (1<<1)
#define B_NODEF_PHASE (1<<2)
#define B_PHASE_RESYNC (1<<3)
#define O_COLOR_DEPTH 4
#define M_COLOR_DEPTH 7
#define B_COLOR_DEPTH_MASK (M_COLOR_DEPTH<<O_COLOR_DEPTH)
#define B_CD_NODEF 0
#define B_CD_24 (4<<4)
#define B_CD_30 (5<<4)
#define B_CD_36 (6<<4)
#define B_CD_48 (7<<4)
#define REG_TX_OESS_CYCLE 0xC3
#define REG_TX_ENCRYPTION 0xC4
#define B_DISABLE_ENCRYPTION 1
#define B_ENABLE_ENCRYPTION 0
#define REG_TX_PKT_SINGLE_CTRL 0xC5
#define B_SINGLE_PKT 1
#define B_BURST_PKT
#define B_SW_CTS (1<<1)
#define REG_TX_PKT_GENERAL_CTRL 0xC6
#define REG_TX_NULL_CTRL 0xC9
#define REG_TX_ACP_CTRL 0xCA
#define REG_TX_ISRC1_CTRL 0xCB
#define REG_TX_ISRC2_CTRL 0xCC
#define REG_TX_AVI_INFOFRM_CTRL 0xCD
#define REG_TX_AUD_INFOFRM_CTRL 0xCE
#define REG_TX_SPD_INFOFRM_CTRL 0xCF
#define REG_TX_MPG_INFOFRM_CTRL 0xD0
#define B_ENABLE_PKT 1
#define B_REPEAT_PKT (1<<1)
// Audio Channel Control
#define REG_TX_AUDIO_CTRL0 0xE0
#define M_AUD_SWL (3<<6)
#define M_AUD_16BIT (0<<6)
#define M_AUD_18BIT (1<<6)
#define M_AUD_20BIT (2<<6)
#define M_AUD_24BIT (3<<6)
#define B_SPDIFTC (1<<5)
#define B_AUD_SPDIF (1<<4)
#define B_AUD_I2S (0<<4)
#define B_AUD_EN_I2S3 (1<<3)
#define B_AUD_EN_I2S2 (1<<2)
#define B_AUD_EN_I2S1 (1<<1)
#define B_AUD_EN_I2S0 (1<<0)
#define REG_TX_AUDIO_CTRL1 0xE1
#define B_AUD_FULLPKT (1<<6)
#define B_AUDFMT_STD_I2S (0<<0)
#define B_AUDFMT_32BIT_I2S (1<<0)
#define B_AUDFMT_LEFT_JUSTIFY (0<<1)
#define B_AUDFMT_RIGHT_JUSTIFY (1<<1)
#define B_AUDFMT_DELAY_1T_TO_WS (0<<2)
#define B_AUDFMT_NO_DELAY_TO_WS (1<<2)
#define B_AUDFMT_WS0_LEFT (0<<3)
#define B_AUDFMT_WS0_RIGHT (1<<3)
#define B_AUDFMT_MSB_SHIFT_FIRST (0<<4)
#define B_AUDFMT_LSB_SHIFT_FIRST (1<<4)
#define B_AUDFMT_RISE_EDGE_SAMPLE_WS (0<<5)
#define B_AUDFMT_FALL_EDGE_SAMPLE_WS (0<<5)
#define REG_TX_AUDIO_FIFOMAP 0xE2
#define O_FIFO3SEL 6
#define O_FIFO2SEL 4
#define O_FIFO1SEL 2
#define O_FIFO0SEL 0
#define B_SELSRC3 3
#define B_SELSRC2 2
#define B_SELSRC1 1
#define B_SELSRC0 0
#define REG_TX_AUDIO_CTRL3 0xE3
#define B_AUD_MULCH (1<<7)
#define B_EN_ZERO_CTS (1<<6)
#define B_CHSTSEL (1<<4)
#define B_S3RLCHG (1<<3)
#define B_S2RLCHG (1<<2)
#define B_S1RLCHG (1<<1)
#define B_S0RLCHG (1<<0)
#define REG_TX_AUD_SRCVALID_FLAT 0xE4
#define B_AUD_SPXFLAT_SRC3 (1<<7)
#define B_AUD_SPXFLAT_SRC2 (1<<6)
#define B_AUD_SPXFLAT_SRC1 (1<<5)
#define B_AUD_SPXFLAT_SRC0 (1<<4)
#define B_AUD_ERR2FLAT (1<<3)
#define B_AUD_S3VALID (1<<2)
#define B_AUD_S2VALID (1<<1)
#define B_AUD_S1VALID (1<<0)
//////////////////////////////////////////
// Bank 1
//////////////////////////////////////////
#define REGPktAudCTS0 0x30 // 7:0
#define REGPktAudCTS1 0x31 // 15:8
#define REGPktAudCTS2 0x32 // 19:16
#define REGPktAudN0 0x33 // 7:0
#define REGPktAudN1 0x34 // 15:8
#define REGPktAudN2 0x35 // 19:16
#define REGPktAudCTSCnt0 0xA0 // 7:0
#define REGPktAudCTSCnt1 0xA1 // 15:8
#define REGPktAudCTSCnt2 0xA2 // 19:16
//////////////////////////////////////////
// COMMON PACKET for NULL,ISRC1,ISRC2,SPD
//////////////////////////////////////////
#define REG_TX_PKT_HB00 0x38
#define REG_TX_PKT_HB01 0x39
#define REG_TX_PKT_HB02 0x3A
#define REG_TX_PKT_PB00 0x3B
#define REG_TX_PKT_PB01 0x3C
#define REG_TX_PKT_PB02 0x3D
#define REG_TX_PKT_PB03 0x3E
#define REG_TX_PKT_PB04 0x3F
#define REG_TX_PKT_PB05 0x40
#define REG_TX_PKT_PB06 0x41
#define REG_TX_PKT_PB07 0x42
#define REG_TX_PKT_PB08 0x43
#define REG_TX_PKT_PB09 0x44
#define REG_TX_PKT_PB10 0x45
#define REG_TX_PKT_PB11 0x46
#define REG_TX_PKT_PB12 0x47
#define REG_TX_PKT_PB13 0x48
#define REG_TX_PKT_PB14 0x49
#define REG_TX_PKT_PB15 0x4A
#define REG_TX_PKT_PB16 0x4B
#define REG_TX_PKT_PB17 0x4C
#define REG_TX_PKT_PB18 0x4D
#define REG_TX_PKT_PB19 0x4E
#define REG_TX_PKT_PB20 0x4F
#define REG_TX_PKT_PB21 0x50
#define REG_TX_PKT_PB22 0x51
#define REG_TX_PKT_PB23 0x52
#define REG_TX_PKT_PB24 0x53
#define REG_TX_PKT_PB25 0x54
#define REG_TX_PKT_PB26 0x55
#define REG_TX_PKT_PB27 0x56
#define REG_TX_AVIINFO_DB1 0x58
#define REG_TX_AVIINFO_DB2 0x59
#define REG_TX_AVIINFO_DB3 0x5A
#define REG_TX_AVIINFO_DB4 0x5B
#define REG_TX_AVIINFO_DB5 0x5C
#define REG_TX_AVIINFO_DB6 0x5E
#define REG_TX_AVIINFO_DB7 0x5F
#define REG_TX_AVIINFO_DB8 0x60
#define REG_TX_AVIINFO_DB9 0x61
#define REG_TX_AVIINFO_DB10 0x62
#define REG_TX_AVIINFO_DB11 0x63
#define REG_TX_AVIINFO_DB12 0x64
#define REG_TX_AVIINFO_DB13 0x65
#define REG_TX_AVIINFO_SUM 0x5D
#define REG_TX_PKT_AUDINFO_CC 0x68 // [2:0]
#define REG_TX_PKT_AUDINFO_SF 0x69 // [4:2]
#define REG_TX_PKT_AUDINFO_CA 0x6B // [7:0]
#define REG_TX_PKT_AUDINFO_DM_LSV 0x6C // [7][6:3]
#define REG_TX_PKT_AUDINFO_SUM 0x6D // [7:0]
// Source Product Description Info Frame
#define REG_TX_PKT_SPDINFO_SUM 0x70
#define REG_TX_PKT_SPDINFO_PB1 0x71
#define REG_TX_PKT_SPDINFO_PB2 0x72
#define REG_TX_PKT_SPDINFO_PB3 0x73
#define REG_TX_PKT_SPDINFO_PB4 0x74
#define REG_TX_PKT_SPDINFO_PB5 0x75
#define REG_TX_PKT_SPDINFO_PB6 0x76
#define REG_TX_PKT_SPDINFO_PB7 0x77
#define REG_TX_PKT_SPDINFO_PB8 0x78
#define REG_TX_PKT_SPDINFO_PB9 0x79
#define REG_TX_PKT_SPDINFO_PB10 0x7A
#define REG_TX_PKT_SPDINFO_PB11 0x7B
#define REG_TX_PKT_SPDINFO_PB12 0x7C
#define REG_TX_PKT_SPDINFO_PB13 0x7D
#define REG_TX_PKT_SPDINFO_PB14 0x7E
#define REG_TX_PKT_SPDINFO_PB15 0x7F
#define REG_TX_PKT_SPDINFO_PB16 0x80
#define REG_TX_PKT_SPDINFO_PB17 0x81
#define REG_TX_PKT_SPDINFO_PB18 0x82
#define REG_TX_PKT_SPDINFO_PB19 0x83
#define REG_TX_PKT_SPDINFO_PB20 0x84
#define REG_TX_PKT_SPDINFO_PB21 0x85
#define REG_TX_PKT_SPDINFO_PB22 0x86
#define REG_TX_PKT_SPDINFO_PB23 0x87
#define REG_TX_PKT_SPDINFO_PB24 0x88
#define REG_TX_PKT_SPDINFO_PB25 0x89
#define REG_TX_PKT_MPGINFO_FMT 0x8A
#define B_MPG_FR 1
#define B_MPG_MF_I (1<<1)
#define B_MPG_MF_B (2<<1)
#define B_MPG_MF_P (3<<1)
#define B_MPG_MF_MASK (3<<1)
#define REG_TX_PKG_MPGINFO_DB0 0x8B
#define REG_TX_PKG_MPGINFO_DB1 0x8C
#define REG_TX_PKG_MPGINFO_DB2 0x8D
#define REG_TX_PKG_MPGINFO_DB3 0x8E
#define REG_TX_PKG_MPGINFO_SUM 0x8F
#define REG_TX_AUDCHST_MODE 0x91 // 191 REG_TX_AUD_CHSTD[2:0] 6:4
// REG_TX_AUD_CHSTC 3
// REG_TX_AUD_NLPCM 2
// REG_TX_AUD_MONO 0
#define REG_TX_AUDCHST_CAT 0x92 // 192 REG_TX_AUD_CHSTCAT 7:0
#define REG_TX_AUDCHST_SRCNUM 0x93 // 193 REG_TX_AUD_CHSTSRC 3:0
#define REG_TX_AUD0CHST_CHTNUM 0x94 // 194 REG_TX_AUD0_CHSTCHR 7:4
// REG_TX_AUD0_CHSTCHL 3:0
#define REG_TX_AUD1CHST_CHTNUM 0x95 // 195 REG_TX_AUD1_CHSTCHR 7:4
// REG_TX_AUD1_CHSTCHL 3:0
#define REG_TX_AUD2CHST_CHTNUM 0x96 // 196 REG_TX_AUD2_CHSTCHR 7:4
// REG_TX_AUD2_CHSTCHL 3:0
#define REG_TX_AUD3CHST_CHTNUM 0x97 // 197 REG_TX_AUD3_CHSTCHR 7:4
// REG_TX_AUD3_CHSTCHL 3:0
#define REG_TX_AUDCHST_CA_FS 0x98 // 198 REG_TX_AUD_CHSTCA 5:4
// REG_TX_AUD_CHSTFS 3:0
#define REG_TX_AUDCHST_OFS_WL 0x99 // 199 REG_TX_AUD_CHSTOFS 7:4
// REG_TX_AUD_CHSTWL 3:0
/////////////////////////////////////////////////////////////////////
// Macro
/////////////////////////////////////////////////////////////////////
#define Switch_HDMITX_Bank(x) HDMITX_WriteI2C_Byte(0x0f,(x)&1)
#define HDMI_OrREG_TX_Byte(reg,ormask) HDMITX_WriteI2C_Byte(reg,(HDMITX_ReadI2C_Byte(reg) | (ormask)))
#define HDMI_AndREG_TX_Byte(reg,andmask) HDMITX_WriteI2C_Byte(reg,(HDMITX_ReadI2C_Byte(reg) & (andmask)))
#define HDMI_SetREG_TX_Byte(reg,andmask,ormask) HDMITX_WriteI2C_Byte(reg,((HDMITX_ReadI2C_Byte(reg) & (andmask))|(ormask)))
/////////////////////////////////////////////////////////////////////
// data structure
/////////////////////////////////////////////////////////////////////
typedef struct _INSTANCE_STRUCT {
BYTE I2C_DEV ;
BYTE I2C_ADDR ;
/////////////////////////////////////////////////
// Interrupt Type
/////////////////////////////////////////////////
BYTE bIntType ; // = 0 ;
/////////////////////////////////////////////////
// Video Property
/////////////////////////////////////////////////
BYTE bInputVideoSignalType ; // for Sync Embedded,CCIR656,InputDDR
/////////////////////////////////////////////////
// Audio Property
/////////////////////////////////////////////////
BYTE bOutputAudioMode ; // = 0 ;
BYTE bAudioChannelSwap ; // = 0 ;
BYTE bAudioChannelEnable ;
BYTE bAudFs ;
unsigned long TMDSClock ;
BYTE bAuthenticated:1 ;
BYTE bHDMIMode: 1;
BYTE bIntPOL:1 ; // 0 = Low Active
BYTE bHPD:1 ;
} INSTANCE ;
// 2008/02/27 added by jj_tseng@chipadvanced.com
typedef enum _mode_id {
UNKNOWN_MODE=0,
CEA_640x480p60,
CEA_720x480p60,
CEA_1280x720p60,
CEA_1920x1080i60,
CEA_720x480i60,
CEA_720x240p60,
CEA_1440x480i60,
CEA_1440x240p60,
CEA_2880x480i60,
CEA_2880x240p60,
CEA_1440x480p60,
CEA_1920x1080p60,
CEA_720x576p50,
CEA_1280x720p50,
CEA_1920x1080i50,
CEA_720x576i50,
CEA_1440x576i50,
CEA_720x288p50,
CEA_1440x288p50,
CEA_2880x576i50,
CEA_2880x288p50,
CEA_1440x576p50,
CEA_1920x1080p50,
CEA_1920x1080p24,
CEA_1920x1080p25,
CEA_1920x1080p30,
VESA_640x350p85,
VESA_640x400p85,
VESA_720x400p85,
VESA_640x480p60,
VESA_640x480p72,
VESA_640x480p75,
VESA_640x480p85,
VESA_800x600p56,
VESA_800x600p60,
VESA_800x600p72,
VESA_800x600p75,
VESA_800X600p85,
VESA_840X480p60,
VESA_1024x768p60,
VESA_1024x768p70,
VESA_1024x768p75,
VESA_1024x768p85,
VESA_1152x864p75,
VESA_1280x768p60R,
VESA_1280x768p60,
VESA_1280x768p75,
VESA_1280x768p85,
VESA_1280x960p60,
VESA_1280x960p85,
VESA_1280x1024p60,
VESA_1280x1024p75,
VESA_1280X1024p85,
VESA_1360X768p60,
VESA_1400x768p60R,
VESA_1400x768p60,
VESA_1400x1050p75,
VESA_1400x1050p85,
VESA_1440x900p60R,
VESA_1440x900p60,
VESA_1440x900p75,
VESA_1440x900p85,
VESA_1600x1200p60,
VESA_1600x1200p65,
VESA_1600x1200p70,
VESA_1600x1200p75,
VESA_1600x1200p85,
VESA_1680x1050p60R,
VESA_1680x1050p60,
VESA_1680x1050p75,
VESA_1680x1050p85,
VESA_1792x1344p60,
VESA_1792x1344p75,
VESA_1856x1392p60,
VESA_1856x1392p75,
VESA_1920x1200p60R,
VESA_1920x1200p60,
VESA_1920x1200p75,
VESA_1920x1200p85,
VESA_1920x1440p60,
VESA_1920x1440p75,
} MODE_ID ;
//~jj_tseng@chipadvanced.com
//////////////////////////////////////////////////////////////////////
// External Interface
//////////////////////////////////////////////////////////////////////
void InitIT6613();
void HDMITX_InitInstance(INSTANCE *pInstance) ;
BOOL EnableVideoOutput(VIDEOPCLKLEVEL level,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI) ;
BOOL SetupVideoInputSignal(BYTE inputSignalType) ;
#ifdef SUPPORT_DEGEN
BOOL ProgramDEGenModeByID(MODE_ID id,BYTE bInputSignalType) ;
#endif // SUPPORT_DEGEN
#ifdef SUPPORT_SYNCEMBEDDED
BOOL ProgramSyncEmbeddedVideoMode(BYTE VIC,BYTE bInputType) ;
#endif
BOOL EnableAudioOutput(unsigned long VideoPixelClock,BYTE bAudioSampleFreq,BYTE ChannelNumber,BYTE bAudSWL,BYTE bSPDIF) ;
void DisableIT6613() ;
void DisableVideoOutput() ;
void DisableAudioOutput() ;
BOOL GetEDIDData(int EDIDBlockID,BYTE *pEDIDData);
BOOL CheckHDMITX(BYTE *pHPD,BYTE *pHPDChange) ;
BOOL EnableHDCP(BYTE bEnable) ;
BOOL EnableAVIInfoFrame(BYTE bEnable,BYTE *pAVIInfoFrame);
BOOL EnableAudioInfoFrame(BYTE bEnable,BYTE *pAudioInfoFrame);
// BOOL EnableVideoOutputIndirect(BYTE xCnt,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI) ;
void SetAVMute(BYTE bEnable) ;
void SetOutputColorDepthPhase(BYTE ColorDepth,BYTE bPhase) ;
void Get6613Reg(BYTE *pReg) ;
////////////////////////////////////////////////////////////////////
// Required Interfance
////////////////////////////////////////////////////////////////////
BYTE I2C_Read_Byte(BYTE Addr,BYTE RegAddr);
SYS_STATUS I2C_Write_Byte(BYTE Addr,BYTE RegAddr,BYTE Data);
SYS_STATUS I2C_Read_ByteN(BYTE Addr,BYTE RegAddr,BYTE *pData,int N) ;
SYS_STATUS I2C_Write_ByteN(BYTE Addr,BYTE RegAddr,BYTE *pData,int N) ;
BYTE HDMITX_ReadI2C_Byte(BYTE RegAddr);
SYS_STATUS HDMITX_WriteI2C_Byte(BYTE RegAddr,BYTE val);
SYS_STATUS HDMITX_ReadI2C_ByteN(BYTE RegAddr,BYTE *pData,int N);
SYS_STATUS HDMITX_WriteI2C_ByteN(BYTE RegAddr,BYTE *pData,int N);
#endif // _IT6613_H_

View File

@ -0,0 +1,550 @@
///////////////////////////////////////////////////////////////////////////////
// This is the sample program for CAT6611 driver usage.
///////////////////////////////////////////////////////////////////////////////
#include "hdmitx.h"
#include "it6613_sys.h" // richard add
#include "edid.h" // richard add
extern int TX_HDP; // richard add
int gEnableColorDepth = 1; //richard add
////////////////////////////////////////////////////////////////////////////////
// EDID
////////////////////////////////////////////////////////////////////////////////
static _XDATA unsigned char EDID_Buf[128] ;
// richard static RX_CAP _XDATA RxCapability ;
RX_CAP _XDATA RxCapability ;
// richard static BOOL bChangeMode = FALSE ;
BOOL bChangeMode = FALSE ;
_XDATA AVI_InfoFrame AviInfo;
_XDATA Audio_InfoFrame AudioInfo ;
////////////////////////////////////////////////////////////////////////////////
// Program utility.
////////////////////////////////////////////////////////////////////////////////
// move to .h BOOL ParseEDID() ;
// richard static BOOL ParseCEAEDID(BYTE *pCEAEDID) ;
void ConfigAVIInfoFrame(BYTE VIC, BYTE pixelrep) ;
void ConfigAudioInfoFrm() ;
#ifndef SUPPORT_SYNCEMB
_IDATA BYTE bInputColorMode = F_MODE_RGB444; //F_MODE_RGB444;
_IDATA BYTE bInputSignalType = 0 ;
// BYTE bInputSignalType = T_MODE_INDDR ; // for DDR mode input
#else
// BYTE bInputSignalType = T_MODE_SYNCEMB ; // for 16 bit sync embedded
_IDATA BYTE bInputColorMode = F_MODE_YUV422 ;
_IDATA BYTE bInputSignalType = T_MODE_SYNCEMB | T_MODE_CCIR656 ; // for 16 bit sync embedded
#endif // SUPPORT_SYNCEMB
_IDATA BYTE iVideoModeSelect=0 ;
_IDATA BYTE bOutputColorMode = F_MODE_RGB444; //F_MODE_RGB444 ;
_XDATA ULONG VideoPixelClock ;
_XDATA BYTE VIC ; // 480p60
_XDATA BYTE pixelrep ; // no pixelrepeating
_XDATA HDMI_Aspec aspec ;
_XDATA HDMI_Colorimetry Colorimetry ;
BOOL bHDMIMode, bAudioEnable ;
////////////////////////////////////////////////////////////////////////////////
// Function Body.
////////////////////////////////////////////////////////////////////////////////
//richard, move to .h void HDMITX_ChangeDisplayOption(HDMI_Video_Type VideoMode, HDMI_OutputColorMode OutputColorMode) ;
//richard, move to .hvoid HDMITX_SetOutput() ;
//richard richard, move to .h void HDMITX_DevLoopProc() ;
void
HDMITX_SetOutput()
{
VIDEOPCLKLEVEL level ;
unsigned long TMDSClock = VideoPixelClock*(pixelrep+1);
#ifdef SUPPORT_SYNCEMB
ProgramSyncEmbeddedVideoMode(VIC, bInputSignalType) ; // inf CCIR656 input
#endif
//TMDSClock = 745000000; //????? richard
if( TMDSClock>80000000 )
{
level = PCLK_HIGH ;
}
else if(TMDSClock>20000000)
{
level = PCLK_MEDIUM ;
}
else
{
level = PCLK_LOW ;
}
//BOOL EnableVideoOutput(VIDEOPCLKLEVEL level,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI) ;
//EnableVideoOutput(level,bInputColorMode, bInputSignalType, bOutputColorMode,bHDMIMode) ;
EnableVideoOutput(level,bInputColorMode, bOutputColorMode,bHDMIMode) ; // richard modify
if( bHDMIMode )
{
OS_PRINTF("ConfigAVIInfoFrame, VIC=%d\n", VIC);
ConfigAVIInfoFrame(VIC, pixelrep) ;
EnableHDCP(TRUE) ;
if( bAudioEnable )
{
//BOOL EnableAudioOutput(ULONG VideoPixelClock,BYTE bAudioSampleFreq,BYTE ChannelNumber,BYTE bAudSWL,BYTE bSPDIF)
//EnableAudioOutput(TMDSClock,48000, 2, FALSE);
bool bSPDIF = FALSE;
EnableAudioOutput(TMDSClock,AUDFS_48KHz, 2, 16, bSPDIF); // richard modify
ConfigAudioInfoFrm() ;
}
}
SetAVMute(FALSE) ;
bChangeMode = FALSE ;
}
void
HDMITX_ChangeDisplayOption(HDMI_Video_Type OutputVideoTiming, HDMI_OutputColorMode OutputColorMode)
{
//HDMI_Video_Type t=HDMI_480i60_16x9;
switch(OutputVideoTiming)
{
case HDMI_640x480p60:
VIC = 1 ;
VideoPixelClock = 25000000 ;
pixelrep = 0 ;
aspec = HDMI_4x3 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_480p60:
VIC = 2 ;
VideoPixelClock = 27000000 ;
pixelrep = 0 ;
aspec = HDMI_4x3 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_480p60_16x9:
VIC = 3 ;
VideoPixelClock = 27000000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_720p60:
VIC = 4 ;
VideoPixelClock = 74250000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_1080i60:
VIC = 5 ;
VideoPixelClock = 74250000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_480i60:
VIC = 6 ;
VideoPixelClock = 13500000 ;
pixelrep = 1 ;
aspec = HDMI_4x3 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_480i60_16x9:
VIC = 7 ;
VideoPixelClock = 13500000 ;
pixelrep = 1 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_1080p60:
VIC = 16 ;
VideoPixelClock = 148500000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_576p50:
VIC = 17 ;
VideoPixelClock = 27000000 ;
pixelrep = 0 ;
aspec = HDMI_4x3 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_576p50_16x9:
VIC = 18 ;
VideoPixelClock = 27000000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_720p50:
VIC = 19 ;
VideoPixelClock = 74250000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_1080i50:
VIC = 20 ;
VideoPixelClock = 74250000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_576i50:
VIC = 21 ;
VideoPixelClock = 13500000 ;
pixelrep = 1 ;
aspec = HDMI_4x3 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_576i50_16x9:
VIC = 22 ;
VideoPixelClock = 13500000 ;
pixelrep = 1 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU601 ;
break ;
case HDMI_1080p50:
VIC = 31 ;
VideoPixelClock = 148500000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_1080p24:
VIC = 32 ;
VideoPixelClock = 74250000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_1080p25:
VIC = 33 ;
VideoPixelClock = 74250000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_1080p30:
VIC = 34 ;
VideoPixelClock = 74250000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU709 ;
break ;
case HDMI_1080i120:// richard add
VIC = 46 ;
VideoPixelClock = 148500000 ;
pixelrep = 0 ;
aspec = HDMI_16x9 ;
Colorimetry = HDMI_ITU601 ;
break ;
default:
VIC = 0; // richard add
bChangeMode = FALSE ;
return ;
}
switch(OutputColorMode)
{
case HDMI_YUV444:
bOutputColorMode = F_MODE_YUV444 ;
break ;
case HDMI_YUV422:
bOutputColorMode = F_MODE_YUV422 ;
break ;
case HDMI_RGB444:
default:
bOutputColorMode = F_MODE_RGB444 ;
break ;
}
if( Colorimetry == HDMI_ITU709 )
{
bInputColorMode |= F_VIDMODE_ITU709 ;
}
else
{
bInputColorMode &= ~F_VIDMODE_ITU709 ;
}
if( Colorimetry != HDMI_640x480p60)
{
bInputColorMode |= F_VIDMODE_16_235 ;
}
else
{
bInputColorMode &= ~F_VIDMODE_16_235 ;
}
bChangeMode = TRUE ;
}
void
ConfigAVIInfoFrame(BYTE VIC, BYTE pixelrep)
{
// AVI_InfoFrame AviInfo;
AviInfo.pktbyte.AVI_HB[0] = AVI_INFOFRAME_TYPE|0x80 ;
AviInfo.pktbyte.AVI_HB[1] = AVI_INFOFRAME_VER ;
AviInfo.pktbyte.AVI_HB[2] = AVI_INFOFRAME_LEN ;
switch(bOutputColorMode)
{
case F_MODE_YUV444:
// AviInfo.info.ColorMode = 2 ;
AviInfo.pktbyte.AVI_DB[0] = (2<<5)|(1<<4) ;
break ;
case F_MODE_YUV422:
// AviInfo.info.ColorMode = 1 ;
AviInfo.pktbyte.AVI_DB[0] = (1<<5)|(1<<4) ;
break ;
case F_MODE_RGB444:
default:
// AviInfo.info.ColorMode = 0 ;
AviInfo.pktbyte.AVI_DB[0] = (0<<5)|(1<<4) ;
break ;
}
AviInfo.pktbyte.AVI_DB[1] = 8 ;
AviInfo.pktbyte.AVI_DB[1] |= (aspec != HDMI_16x9)?(1<<4):(2<<4) ; // 4:3 or 16:9
AviInfo.pktbyte.AVI_DB[1] |= (Colorimetry != HDMI_ITU709)?(1<<6):(2<<6) ; // 4:3 or 16:9
AviInfo.pktbyte.AVI_DB[2] = 0 ;
AviInfo.pktbyte.AVI_DB[3] = VIC ;
AviInfo.pktbyte.AVI_DB[4] = pixelrep & 3 ;
AviInfo.pktbyte.AVI_DB[5] = 0 ;
AviInfo.pktbyte.AVI_DB[6] = 0 ;
AviInfo.pktbyte.AVI_DB[7] = 0 ;
AviInfo.pktbyte.AVI_DB[8] = 0 ;
AviInfo.pktbyte.AVI_DB[9] = 0 ;
AviInfo.pktbyte.AVI_DB[10] = 0 ;
AviInfo.pktbyte.AVI_DB[11] = 0 ;
AviInfo.pktbyte.AVI_DB[12] = 0 ;
EnableAVIInfoFrame(TRUE, (unsigned char *)&AviInfo) ;
}
////////////////////////////////////////////////////////////////////////////////
// Function: ConfigAudioInfoFrm
// Parameter: NumChannel, number from 1 to 8
// Return: ER_SUCCESS for successfull.
// Remark: Evaluate. The speakerplacement is only for reference.
// For production, the caller of SetAudioInfoFrame should program
// Speaker placement by actual status.
// Side-Effect:
////////////////////////////////////////////////////////////////////////////////
void
ConfigAudioInfoFrm()
{
int i ;
ErrorF("ConfigAudioInfoFrm(%d)\n",2) ;
AudioInfo.pktbyte.AUD_HB[0] = AUDIO_INFOFRAME_TYPE ;
AudioInfo.pktbyte.AUD_HB[1] = 1 ;
AudioInfo.pktbyte.AUD_HB[2] = AUDIO_INFOFRAME_LEN ;
AudioInfo.pktbyte.AUD_DB[0] = 1 ;
for( i = 1 ;i < AUDIO_INFOFRAME_LEN ; i++ )
{
AudioInfo.pktbyte.AUD_DB[i] = 0 ;
}
EnableAudioInfoFrame(TRUE, (unsigned char *)&AudioInfo) ;
}
/////////////////////////////////////////////////////////////////////
// ParseEDID()
// Check EDID check sum and EDID 1.3 extended segment.
/////////////////////////////////////////////////////////////////////
BOOL
ParseEDID()
{
// collect the EDID ucdata of segment 0
BYTE CheckSum ;
BYTE BlockCount ;
BOOL err ;
BOOL bValidCEA = FALSE ;
int i ;
RxCapability.ValidCEA = FALSE ;
// richard GetEDIDData(0, EDID_Buf);
if (!GetEDIDData(0, EDID_Buf))
return FALSE;
for( i = 0, CheckSum = 0 ; i < 128 ; i++ )
{
CheckSum += EDID_Buf[i] ; CheckSum &= 0xFF ;
}
//Eep_Write(0x80, 0x80, EDID_Buf) ;
if( CheckSum != 0 ) // 128-byte EDID sum shall equal zero
{
return FALSE ;
}
// check EDID Header
if( EDID_Buf[0] != 0x00 ||
EDID_Buf[1] != 0xFF ||
EDID_Buf[2] != 0xFF ||
EDID_Buf[3] != 0xFF ||
EDID_Buf[4] != 0xFF ||
EDID_Buf[5] != 0xFF ||
EDID_Buf[6] != 0xFF ||
EDID_Buf[7] != 0x00)
{
return FALSE ;
}
BlockCount = EDID_Buf[0x7E] ; // Extention Flash: Number of 128-byte EDID extesion blocks to follow
if( BlockCount == 0 )
{
return TRUE ; // do nothing.
}
else if ( BlockCount > 4 )
{
BlockCount = 4 ;
}
// read all segment for test
for( i = 1 ; i <= BlockCount ; i++ )
{
err = GetEDIDData(i, EDID_Buf) ;
if( err )
{
if( !bValidCEA && EDID_Buf[0] == 0x2 && EDID_Buf[1] == 0x3 ) //EDID_Buf[0] == 0x2 ==> Additional timing data type 2
{
// richard change
//err = ParseCEAEDID(EDID_Buf) ;
err = ParseCEAEDID(EDID_Buf, &RxCapability);
if( err )
{
if(RxCapability.IEEEOUI==0x0c03)
{
RxCapability.ValidHDMI = TRUE ;
bValidCEA = TRUE ;
}
else
{
RxCapability.ValidHDMI = FALSE ;
}
}
}
}
}
return err?FALSE:TRUE ; // richard modify
}
/* richard: use the one defined edid.c
static BOOL
ParseCEAEDID(BYTE *pCEAEDID)
{
BYTE offset,End ;
BYTE count ;
BYTE tag ;
int i ;
// richard if( pCEAEDID[0] != 0x02 || pCEAEDID[1] != 0x03 ) return ER_SUCCESS ; // not a CEA BLOCK.
if( pCEAEDID[0] != 0x02 || pCEAEDID[1] != 0x03 ) // not a CEA BLOCK.
return FALSE;
End = pCEAEDID[2] ; // CEA description.
RxCapability.VideoMode = pCEAEDID[3] ;
RxCapability.VDOModeCount = 0 ;
RxCapability.idxNativeVDOMode = 0xff ;
for( offset = 4 ; offset < End ; )
{
tag = pCEAEDID[offset] >> 5 ;
count = pCEAEDID[offset] & 0x1f ;
switch( tag )
{
case 0x01: // Audio Data Block ;
RxCapability.AUDDesCount = count/3 ;
offset++ ;
for( i = 0 ; i < RxCapability.AUDDesCount ; i++ )
{
RxCapability.AUDDes[i].uc[0] = pCEAEDID[offset++] ;
RxCapability.AUDDes[i].uc[1] = pCEAEDID[offset++] ;
RxCapability.AUDDes[i].uc[2] = pCEAEDID[offset++] ;
}
break ;
case 0x02: // Video Data Block ;
//RxCapability.VDOModeCount = 0 ;
offset ++ ;
for( i = 0,RxCapability.idxNativeVDOMode = 0xff ; i < count ; i++, offset++ )
{
BYTE VIC ;
VIC = pCEAEDID[offset] & (~0x80) ;
// if( FindModeTableEntryByVIC(VIC) != -1 )
{
RxCapability.VDOMode[RxCapability.VDOModeCount] = VIC ;
if( pCEAEDID[offset] & 0x80 )
{
RxCapability.idxNativeVDOMode = (BYTE)RxCapability.VDOModeCount ;
iVideoModeSelect = RxCapability.VDOModeCount ;
}
RxCapability.VDOModeCount++ ;
}
}
break ;
case 0x03: // Vendor Specific Data Block ;
offset ++ ;
RxCapability.IEEEOUI = (ULONG)pCEAEDID[offset+2] ;
RxCapability.IEEEOUI <<= 8 ;
RxCapability.IEEEOUI += (ULONG)pCEAEDID[offset+1] ;
RxCapability.IEEEOUI <<= 8 ;
RxCapability.IEEEOUI += (ULONG)pCEAEDID[offset] ;
offset += count ; // ignore the remaind.
break ;
case 0x04: // Speaker Data Block ;
offset ++ ;
RxCapability.SpeakerAllocBlk.uc[0] = pCEAEDID[offset] ;
RxCapability.SpeakerAllocBlk.uc[1] = pCEAEDID[offset+1] ;
RxCapability.SpeakerAllocBlk.uc[2] = pCEAEDID[offset+2] ;
offset += 3 ;
break ;
case 0x05: // VESA Data Block ;
offset += count+1 ;
break ;
case 0x07: // Extended Data Block ;
offset += count+1 ; //ignore
break ;
default:
offset += count+1 ; // ignore
}
}
RxCapability.ValidCEA = TRUE ;
return TRUE ;
}
*/

View File

@ -0,0 +1,63 @@
#ifndef _CAT6611_SYS_H_
#define _CAT6611_SYS_H_
////////////////////////////////////////////////////////////////////////////////
// Internal Data Type
////////////////////////////////////////////////////////////////////////////////
typedef enum tagHDMI_Video_Type {
HDMI_Unkown = 0 ,
HDMI_640x480p60 = 1 ,
HDMI_480p60,
HDMI_480p60_16x9,
HDMI_720p60,
HDMI_1080i60,
HDMI_480i60,
HDMI_480i60_16x9,
HDMI_1080p60 = 16,
HDMI_576p50,
HDMI_576p50_16x9,
HDMI_720p50 = 19,
HDMI_1080i50,
HDMI_576i50,
HDMI_576i50_16x9,
HDMI_1080p50 = 31,
HDMI_1080p24,
HDMI_1080p25,
HDMI_1080p30,
HDMI_1080i120 = 46, // richard add
} HDMI_Video_Type ;
typedef enum tagHDMI_Aspec {
HDMI_4x3 ,
HDMI_16x9
} HDMI_Aspec;
typedef enum tagHDMI_OutputColorMode {
HDMI_RGB444,
HDMI_YUV444,
HDMI_YUV422
} HDMI_OutputColorMode ;
typedef enum tagHDMI_Colorimetry {
HDMI_ITU601,
HDMI_ITU709
} HDMI_Colorimetry ;
///////////////////////////////////////////////////////////////////////
// Output Mode Type
///////////////////////////////////////////////////////////////////////
#define RES_ASPEC_4x3 0
#define RES_ASPEC_16x9 1
#define F_MODE_REPT_NO 0
#define F_MODE_REPT_TWICE 1
#define F_MODE_REPT_QUATRO 3
#define F_MODE_CSC_ITU601 0
#define F_MODE_CSC_ITU709 1
void HDMITX_ChangeDisplayOption(HDMI_Video_Type VideoMode, HDMI_OutputColorMode OutputColorMode);
void HDMITX_SetOutput();
#endif // _CAT6611_SYS_H_

View File

@ -0,0 +1,329 @@
#ifndef _TYPEDEF_H_
#define _TYPEDEF_H_
//////////////////////////////////////////////////
// data type
//////////////////////////////////////////////////
#ifdef _MCU_
typedef bit BOOL ;
#define _CODE //richard code
#define _IDATA //richard idata
#define _XDATA //richard xdata
#else
typedef int BOOL ;
#define _CODE
#define _IDATA
#define _XDATA
#endif // _MCU_
typedef char CHAR,*PCHAR ;
typedef unsigned char uchar,*puchar ;
typedef unsigned char UCHAR,*PUCHAR ;
typedef unsigned char byte,*pbyte ;
typedef unsigned char BYTE,*PBYTE ;
typedef short SHORT,*PSHORT ;
typedef unsigned short ushort,*pushort ;
typedef unsigned short USHORT,*PUSHORT ;
typedef unsigned short word,*pword ;
typedef unsigned short WORD,*PWORD ;
typedef long LONG,*PLONG ;
typedef unsigned long ulong,*pulong ;
typedef unsigned long ULONG,*PULONG ;
typedef unsigned long dword,*pdword ;
typedef unsigned long DWORD,*PDWORD ;
#define FALSE 0
#define TRUE 1
#define SUCCESS 0
#define FAIL -1
#define ON 1
#define OFF 0
typedef enum _SYS_STATUS {
ER_SUCCESS = 0,
ER_FAIL,
ER_RESERVED
} SYS_STATUS ;
#define abs(x) (((x)>=0)?(x):(-(x)))
typedef enum _Video_State_Type {
VSTATE_PwrOff = 0,
VSTATE_SyncWait ,
VSTATE_SWReset,
VSTATE_SyncChecking,
VSTATE_HDCPSet,
VSTATE_HDCP_Reset,
VSTATE_ModeDetecting,
VSTATE_VideoOn,
VSTATE_Reserved
} Video_State_Type ;
typedef enum _Audio_State_Type {
ASTATE_AudioOff = 0,
ASTATE_RequestAudio ,
ASTATE_ResetAudio,
ASTATE_WaitForReady,
ASTATE_AudioOn ,
ASTATE_Reserved
} Audio_State_Type ;
typedef enum _TXVideo_State_Type {
TXVSTATE_Unplug = 0,
TXVSTATE_HPD,
TXVSTATE_WaitForMode,
TXVSTATE_WaitForVStable,
TXVSTATE_VideoInit,
TXVSTATE_VideoSetup,
TXVSTATE_VideoOn,
TXVSTATE_Reserved
} TXVideo_State_Type ;
typedef enum _TXAudio_State_Type {
TXASTATE_AudioOff = 0,
TXASTATE_AudioPrepare,
TXASTATE_AudioOn,
TXASTATE_AudioFIFOFail,
TXASTATE_Reserved
} TXAudio_State_Type ;
typedef enum {
PCLK_LOW = 0 ,
PCLK_MEDIUM,
PCLK_HIGH
} VIDEOPCLKLEVEL ;
///////////////////////////////////////////////////////////////////////
// Video Data Type
///////////////////////////////////////////////////////////////////////
#define F_MODE_RGB24 0
#define F_MODE_RGB444 0
#define F_MODE_YUV422 1
#define F_MODE_YUV444 2
#define F_MODE_CLRMOD_MASK 3
#define F_MODE_INTERLACE 1
#define F_MODE_ITU709 (1<<4)
#define F_MODE_ITU601 0
#define F_MODE_0_255 0
#define F_MODE_16_235 (1<<5)
#define F_MODE_EN_UDFILT (1<<6) // output mode only,and loaded from EEPROM
#define F_MODE_EN_DITHER (1<<7) // output mode only,and loaded from EEPROM
#define F_VIDMODE_ITU709 F_MODE_ITU709 // richard add
#define F_VIDMODE_16_235 F_MODE_16_235 // richard add
typedef union _VideoFormatCode
{
struct _VFC
{
BYTE colorfmt:2 ;
BYTE interlace:1 ;
BYTE Colorimetry:1 ;
BYTE Quantization:1 ;
BYTE UpDownFilter:1 ;
BYTE Dither:1 ;
} VFCCode ;
unsigned char VFCByte ;
} VideoFormatCode ;
#define T_MODE_CCIR656 (1<<0)
#define T_MODE_SYNCEMB (1<<1)
#define T_MODE_INDDR (1<<2)
#define T_MODE_PCLKDIV2 (1<<3)
#define T_MODE_DEGEN (1<<4)
#define T_MODE_SYNCGEN (1<<5)
//////////////////////////////////////////////////////////////////
// Audio relate definition and macro.
//////////////////////////////////////////////////////////////////
// for sample clock
#define AUDFS_22p05KHz 4
#define AUDFS_44p1KHz 0
#define AUDFS_88p2KHz 8
#define AUDFS_176p4KHz 12
#define AUDFS_24KHz 6
#define AUDFS_48KHz 2
#define AUDFS_96KHz 10
#define AUDFS_192KHz 14
#define AUDFS_32KHz 3
#define AUDFS_OTHER 1
// Audio Enable
#define ENABLE_SPDIF (1<<4)
#define ENABLE_I2S_SRC3 (1<<3)
#define ENABLE_I2S_SRC2 (1<<2)
#define ENABLE_I2S_SRC1 (1<<1)
#define ENABLE_I2S_SRC0 (1<<0)
#define AUD_SWL_NOINDICATE 0x0
#define AUD_SWL_16 0x2
#define AUD_SWL_17 0xC
#define AUD_SWL_18 0x4
#define AUD_SWL_20 0xA // for maximum 20 bit
#define AUD_SWL_21 0xD
#define AUD_SWL_22 0x5
#define AUD_SWL_23 0x9
#define AUD_SWL_24 0xB
/////////////////////////////////////////////////////////////////////
// Packet and Info Frame definition and datastructure.
/////////////////////////////////////////////////////////////////////
#define VENDORSPEC_INFOFRAME_TYPE 0x01
#define AVI_INFOFRAME_TYPE 0x02
#define SPD_INFOFRAME_TYPE 0x03
#define AUDIO_INFOFRAME_TYPE 0x04
#define MPEG_INFOFRAME_TYPE 0x05
#define VENDORSPEC_INFOFRAME_VER 0x01
#define AVI_INFOFRAME_VER 0x02
#define SPD_INFOFRAME_VER 0x01
#define AUDIO_INFOFRAME_VER 0x01
#define MPEG_INFOFRAME_VER 0x01
#define VENDORSPEC_INFOFRAME_LEN 8
#define AVI_INFOFRAME_LEN 13
#define SPD_INFOFRAME_LEN 25
#define AUDIO_INFOFRAME_LEN 10
#define MPEG_INFOFRAME_LEN 10
#define ACP_PKT_LEN 9
#define ISRC1_PKT_LEN 16
#define ISRC2_PKT_LEN 16
typedef union _AVI_InfoFrame
{
struct {
BYTE Type ;
BYTE Ver ;
BYTE Len ;
BYTE Scan:2 ;
BYTE BarInfo:2 ;
BYTE ActiveFmtInfoPresent:1 ;
BYTE ColorMode:2 ;
BYTE FU1:1 ;
BYTE ActiveFormatAspectRatio:4 ;
BYTE PictureAspectRatio:2 ;
BYTE Colorimetry:2 ;
BYTE Scaling:2 ;
BYTE FU2:6 ;
BYTE VIC:7 ;
BYTE FU3:1 ;
BYTE PixelRepetition:4 ;
BYTE FU4:4 ;
SHORT Ln_End_Top ;
SHORT Ln_Start_Bottom ;
SHORT Pix_End_Left ;
SHORT Pix_Start_Right ;
} info ;
struct {
BYTE AVI_HB[3] ;
BYTE AVI_DB[AVI_INFOFRAME_LEN] ;
} pktbyte ;
} AVI_InfoFrame ;
typedef union _Audio_InfoFrame {
struct {
BYTE Type ;
BYTE Ver ;
BYTE Len ;
BYTE AudioChannelCount:3 ;
BYTE RSVD1:1 ;
BYTE AudioCodingType:4 ;
BYTE SampleSize:2 ;
BYTE SampleFreq:3 ;
BYTE Rsvd2:3 ;
BYTE FmtCoding ;
BYTE SpeakerPlacement ;
BYTE Rsvd3:3 ;
BYTE LevelShiftValue:4 ;
BYTE DM_INH:1 ;
} info ;
struct {
BYTE AUD_HB[3] ;
BYTE AUD_DB[AUDIO_INFOFRAME_LEN] ;
} pktbyte ;
} Audio_InfoFrame ;
typedef union _MPEG_InfoFrame {
struct {
BYTE Type ;
BYTE Ver ;
BYTE Len ;
ULONG MpegBitRate ;
BYTE MpegFrame:2 ;
BYTE Rvsd1:2 ;
BYTE FieldRepeat:1 ;
BYTE Rvsd2:3 ;
} info ;
struct {
BYTE MPG_HB[3] ;
BYTE MPG_DB[MPEG_INFOFRAME_LEN] ;
} pktbyte ;
} MPEG_InfoFrame ;
// Source Product Description
typedef union _SPD_InfoFrame {
struct {
BYTE Type ;
BYTE Ver ;
BYTE Len ;
char VN[8] ; // vendor name character in 7bit ascii characters
char PD[16] ; // product description character in 7bit ascii characters
BYTE SourceDeviceInfomation ;
} info ;
struct {
BYTE SPD_HB[3] ;
BYTE SPD_DB[SPD_INFOFRAME_LEN] ;
} pktbyte ;
} SPD_InfoFrame ;
///////////////////////////////////////////////////////////////////////////
// Using for interface.
///////////////////////////////////////////////////////////////////////////
struct VideoTiming {
ULONG VideoPixelClock ;
BYTE VIC ;
BYTE pixelrep ;
BYTE outputVideoMode ;
} ;
#endif // _TYPEDEF_H_

View File

@ -0,0 +1 @@
:00000001FF

View File

@ -0,0 +1 @@
set_global_assignment -name SEARCH_PATH $::quartus(qip_path)

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<simPackage>
<file path="hdl_sim/sys_onchip_memory2_0.dat" type="DAT" initParamName="INIT_FILE" memoryPath="onchip_memory2_0" />
<file path="epcq_controller_0.hex" type="HEX" memoryPath="epcq_controller_0" />
<file path="sys_onchip_memory2_0.hex" type="HEX" initParamName="INIT_FILE" memoryPath="onchip_memory2_0" />
</simPackage>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include "lcd.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#define LCD_CMD 0x00
#define LCD_DATA 0x40
#define WRDELAY 20
#define CLEARDELAY 800
void lcd_init() {
alt_u8 lcd_ctrl = 0x00;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl);
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x38); // function set
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x39); // function set, select extended table (IS=1)
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x14); // osc freq
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x71); // contrast set
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x5E); // power/icon/cont
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x6D); // follower control
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x0C); // display on
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x01); // clear display
usleep(CLEARDELAY);
SPI_write(I2CA_BASE, 0x06); // entry mode set
usleep(WRDELAY);
SPI_write(I2CA_BASE, 0x02); // return home
usleep(CLEARDELAY);
lcd_ctrl |= LCD_CS_N;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl);
}
void lcd_write(char *row1, char *row2) {
alt_u8 i, rowlen;
alt_u8 lcd_ctrl = 0x00;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl);
SPI_write(I2CA_BASE, 0x01); // clear display
usleep(CLEARDELAY);
// Set RS to enter data write mode
lcd_ctrl |= LCD_RS;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl);
//ensure no empty row
rowlen = strnlen(row1, LCD_ROW_LEN);
if (rowlen == 0) {
strncpy(row1, " ", LCD_ROW_LEN+1);
rowlen++;
}
for (i=0; i<rowlen; i++) {
SPI_write(I2CA_BASE, row1[i]);
usleep(WRDELAY);
}
// second row
lcd_ctrl &= ~LCD_RS;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl);
SPI_write(I2CA_BASE, (1<<7)|0x40);
usleep(WRDELAY);
lcd_ctrl |= LCD_RS;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl);
//ensure no empty row
rowlen = strnlen(row2, LCD_ROW_LEN);
if (rowlen == 0) {
strncpy(row2, " ", LCD_ROW_LEN+1);
rowlen++;
}
for (i=0; i<rowlen; i++) {
SPI_write(I2CA_BASE, row2[i]);
usleep(WRDELAY);
}
lcd_ctrl |= LCD_CS_N;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl);
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef LCD_H_
#define LCD_H_
#include "system.h"
#include <stdio.h>
#include "sysconfig.h"
#define LCD_ROW_LEN 16
//#define I2C_DEBUG
#define I2CA_BASE I2C_OPENCORES_0_BASE
#define LCD_CS_N (1<<0)
#define LCD_RS (1<<1)
void lcd_init();
void lcd_write(char *row1, char *row2);
#endif /* LCD_H_ */

View File

@ -0,0 +1,34 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef SYSCONFIG_H_
#define SYSCONFIG_H_
#ifndef DEBUG
#define OS_PRINTF(...)
#define ErrorF(...)
#define printf(...)
#else
#define OS_PRINTF printf
#define ErrorF printf
// use reduced printf
//#define printf alt_printf
#endif
#endif /* SYSCONFIG_H_ */

View File

@ -0,0 +1,81 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <stdio.h>
#include <unistd.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "i2c_opencores.h"
#include "ths7353.h"
inline alt_u32 ths_readreg(alt_u8 channel) {
//Phase 1
I2C_start(I2CA_BASE, THS_BASE, 0);
I2C_write(I2CA_BASE, channel, 1);
//Phase 2
I2C_start(I2CA_BASE, THS_BASE, 1);
return I2C_read(I2CA_BASE,1);
}
inline void ths_writereg(alt_u8 channel, alt_u8 data) {
I2C_start(I2CA_BASE, THS_BASE, 0);
I2C_write(I2CA_BASE, channel, 0);
I2C_write(I2CA_BASE, data, 1);
}
int ths_init() {
//Avoid random FIFO state (see datasheet p.37)
I2C_write(I2CA_BASE, 0x00, 0);
usleep(10);
//Initialize all channels
ths_writereg(THS_CH1, (THS_LPF_DEFAULT<<THS_LPF_OFFS));
ths_writereg(THS_CH2, (THS_LPF_DEFAULT<<THS_LPF_OFFS));
ths_writereg(THS_CH3, (THS_LPF_DEFAULT<<THS_LPF_OFFS));
return (ths_readreg(THS_CH1) == (THS_LPF_DEFAULT<<THS_LPF_OFFS));
}
void ths_set_lpf(alt_u8 val) {
alt_u8 status = ths_readreg(THS_CH1) & ~THS_LPF_MASK;
status |= (val<<THS_LPF_OFFS);
ths_writereg(THS_CH1, status);
ths_writereg(THS_CH2, status);
ths_writereg(THS_CH3, status);
printf("THS LPF value set to 0x%x\n", val);
}
void ths_source_sel(ths_input_t input, alt_u8 lpf) {
alt_u8 status = ths_readreg(THS_CH1) & ~(THS_SRC_MASK|THS_MODE_MASK);
//alt_u8 status = 0x00;
if (input == THS_STANDBY)
status |= (THS_MODE_AVMUTE<<THS_MODE_OFFS);
else
status |= (THS_MODE_AC_BIAS | (input<<THS_SRC_OFFS));
//status |= (lpf<<THS_LPF_OFFS);
ths_writereg(THS_CH1, status);
ths_writereg(THS_CH2, status);
ths_writereg(THS_CH3, status);
printf("THS source set to %u\n", input);
}

View File

@ -0,0 +1,63 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef THS7353_H_
#define THS7353_H_
#include "sysconfig.h"
#define THS_BASE (0x58>>1)
#define THS_CH1 0x01
#define THS_CH2 0x02
#define THS_CH3 0x03
typedef enum {
THS_INPUT_A = 0,
THS_INPUT_B = 1,
THS_STANDBY = 2
} ths_input_t;
#define THS_LPF_DEFAULT 0x3
#define THS_LPF_MASK 0x18
#define THS_LPF_OFFS 3
#define THS_SRC_MASK 0x20
#define THS_SRC_OFFS 5
#define THS_MODE_MASK 0x7
#define THS_MODE_OFFS 0
#define THS_MODE_DISABLE 0
#define THS_MODE_AVMUTE 1
#define THS_MODE_AC_BIAS 4
#define THS_MODE_STC 6 //mid bias
#define THS_LPF_BYPASS 0x03
//#define I2C_DEBUG
#define I2CA_BASE I2C_OPENCORES_0_BASE
int ths_init();
void ths_set_lpf(alt_u8 val);
void ths_source_sel(ths_input_t input, alt_u8 lpf);
#endif /* THS7353_H_ */

View File

@ -0,0 +1,401 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <stdio.h>
#include <unistd.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "i2c_opencores.h"
#include "tvp7002.h"
//#define SYNCBYPASS // Bypass VGA syncs (for debug - needed for interlace?)
//#define EXTADCCLK // Use external ADC clock (external osc)
//#define ADCPOWERDOWN // Power-down ADCs
//#define PLLPOSTDIV // Double-rate PLL with div-by-2 (decrease jitter?)
/* Y'Pb'Pr' to R'G'B' CSC coefficients.
*
* Coefficients from "Colour Space Conversions" (http://www.poynton.com/PDFs/coloureq.pdf).
*/
const ypbpr_to_rgb_csc_t csc_coeffs[] = {
{ "Rec. 601", 0x2000, 0x0000, 0x2CE5, 0x2000, 0xF4FD, 0xE926, 0x2000, 0x38BC, 0x0000 }, // eq. 101
{ "Rec. 709", 0x2000, 0x0000, 0x323E, 0x2000, 0xFA04, 0xF113, 0x2000, 0x3B61, 0x0000 }, // eq. 105
};
extern mode_data_t video_modes[];
static inline void tvp_set_hpllcoast(alt_u8 pre, alt_u8 post) {
tvp_writereg(TVP_HPLLPRECOAST, pre);
tvp_writereg(TVP_HPLLPOSTCOAST, post);
}
static inline void tvp_set_ssthold(alt_u8 vsdetect_thold) {
tvp_writereg(TVP_SSTHOLD, vsdetect_thold);
}
static void tvp_set_clamp(video_format fmt) {
switch (fmt) {
case FORMAT_RGBS:
case FORMAT_RGBHV:
case FORMAT_RGsB:
//select bottom clamp (RGB)
tvp_writereg(TVP_SOGTHOLD, 0x58);
break;
case FORMAT_YPbPr:
//select mid clamp for Pb & Pr
tvp_writereg(TVP_SOGTHOLD, 0x5D);
break;
default:
break;
}
}
static void tvp_set_clamp_position(video_type type) {
switch (type) {
case VIDEO_LDTV:
tvp_writereg(TVP_CLAMPSTART, 0x2);
tvp_writereg(TVP_CLAMPWIDTH, 0x6);
break;
case VIDEO_SDTV:
case VIDEO_EDTV:
case VIDEO_PC:
tvp_writereg(TVP_CLAMPSTART, 0x6);
tvp_writereg(TVP_CLAMPWIDTH, 0x10);
break;
case VIDEO_HDTV:
tvp_writereg(TVP_CLAMPSTART, 0x32);
tvp_writereg(TVP_CLAMPWIDTH, 0x20);
break;
default:
break;
}
}
static void tvp_set_alc(video_type type) {
//disable ALC
//tvp_writereg(TVP_ALCEN, 0x00);
//tvp_writereg(TVP_ALCEN, 0x80);
//set analog (coarse) gain to max recommended value (-> 91% of the ADC range with 0.7Vpp input)
tvp_writereg(TVP_BG_CGAIN, 0x88);
tvp_writereg(TVP_R_CGAIN, 0x08);
//set rest of the gain digitally (fine) to utilize 100% of the range at the output (0.91*(1+(26/256)) = 1)
tvp_writereg(TVP_R_FGAIN, 26);
tvp_writereg(TVP_G_FGAIN, 26);
tvp_writereg(TVP_B_FGAIN, 26);
//select ALC placement
switch (type) {
case VIDEO_LDTV:
tvp_writereg(TVP_ALCPLACE, 0x9);
break;
case VIDEO_SDTV:
case VIDEO_EDTV:
case VIDEO_PC:
tvp_writereg(TVP_ALCPLACE, 0x18);
break;
case VIDEO_HDTV:
tvp_writereg(TVP_ALCPLACE, 0x5A);
break;
default:
break;
}
}
inline alt_u32 tvp_readreg(alt_u32 regaddr) {
I2C_start(I2CA_BASE, TVP_BASE, 0);
I2C_write(I2CA_BASE, regaddr, 1); //don't use repeated start as it seems unreliable at 400kHz
I2C_start(I2CA_BASE, TVP_BASE, 1);
return I2C_read(I2CA_BASE,1);
}
inline void tvp_writereg(alt_u32 regaddr, alt_u8 data) {
I2C_start(I2CA_BASE, TVP_BASE, 0);
I2C_write(I2CA_BASE, regaddr, 0);
I2C_write(I2CA_BASE, data, 1);
}
inline void tvp_reset() {
usleep(10000);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00);
usleep(10000);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x01);
usleep(10000);
}
inline void tvp_disable_output() {
usleep(10000);
tvp_writereg(TVP_MISCCTRL1, 0x13);
usleep(10000);
tvp_writereg(TVP_MISCCTRL2, 0x03);
usleep(10000);
}
inline void tvp_enable_output() {
usleep(10000);
tvp_writereg(TVP_MISCCTRL1, 0x11);
usleep(10000);
tvp_writereg(TVP_MISCCTRL2, 0x02);
usleep(10000);
}
void tvp_init() {
// disable output
tvp_disable_output();
//Set global defaults
// Hsync input->output delay (horizontal shift)
// Default is 13, which maintains alignment of RGB and hsync at output
//tvp_writereg(TVP_HSOUTSTART, 0);
// Hsync edge->Vsync edge delay
tvp_writereg(TVP_VSOUTALIGN, 0);
// Set default CSC coeffs.
tvp_sel_csc(&csc_coeffs[0]);
// Set default phase
tvp_set_hpll_phase(0x10);
// Set min LPF
tvp_set_lpf(0);
tvp_set_sync_lpf(0);
// Increase line length tolerance
tvp_writereg(TVP_LINELENTOL, 0x06);
// Common sync separator threshold
// Some arcade games need more that the default 0x40
tvp_set_ssthold(0x44);
}
// Configure H-PLL (sampling rate, VCO gain and charge pump current)
void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 plldivby2) {
alt_u32 pclk_est;
alt_u8 vco_range;
alt_u8 cp_current;
alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0xF8;
// Enable PLL post-div-by-2 with double samplerate
if (plldivby2) {
tvp_writereg(TVP_HPLLPHASE, status|1);
h_samplerate = 2*h_samplerate;
} else {
tvp_writereg(TVP_HPLLPHASE, status);
}
tvp_writereg(TVP_HPLLDIV_MSB, (h_samplerate >> 4));
tvp_writereg(TVP_HPLLDIV_LSB, ((h_samplerate & 0xf) << 4));
printf("Horizontal samplerate set to %u\n", h_samplerate);
pclk_est = ((alt_u32)h_samplerate * v_lines * hz) / 1000; //in kHz
printf("Estimated PCLK: %u.%.3u MHz\n", pclk_est/1000, pclk_est%1000);
if (pclk_est < 36000) {
vco_range = 0;
} else if (pclk_est < 70000) {
vco_range = 1;
} else if (pclk_est < 135000) {
vco_range = 2;
} else {
vco_range = 3;
}
cp_current = (40*Kvco[vco_range]+h_samplerate/2) / h_samplerate; //"+h_samplerate/2" for fast rounding
printf("VCO range: %s\nCPC: %u\n", Kvco_str[vco_range], cp_current);
tvp_writereg(TVP_HPLLCTRL, ((vco_range << 6) | (cp_current << 3)));
}
void tvp_sel_clk(alt_u8 refclk) {
alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0xFA;
//TODO: set SOG and CLP LPF based on mode
if (refclk == REFCLK_INTCLK) {
tvp_writereg(TVP_INPMUX2, status|0x2);
} else {
#ifdef EXTADCCLK
tvp_writereg(TVP_INPMUX2, status|0x8);
#else
tvp_writereg(TVP_INPMUX2, status|0xA);
#endif
}
}
void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc) {
tvp_writereg(TVP_CSC1HI, (csc->G_Y >> 8));
tvp_writereg(TVP_CSC1LO, (csc->G_Y & 0xff));
tvp_writereg(TVP_CSC2HI, (csc->G_Pb >> 8));
tvp_writereg(TVP_CSC2LO, (csc->G_Pb & 0xff));
tvp_writereg(TVP_CSC3HI, (csc->G_Pr >> 8));
tvp_writereg(TVP_CSC3LO, (csc->G_Pr & 0xff));
tvp_writereg(TVP_CSC4HI, (csc->R_Y >> 8));
tvp_writereg(TVP_CSC4LO, (csc->R_Y & 0xff));
tvp_writereg(TVP_CSC5HI, (csc->R_Pb >> 8));
tvp_writereg(TVP_CSC5LO, (csc->R_Pb & 0xff));
tvp_writereg(TVP_CSC6HI, (csc->R_Pr >> 8));
tvp_writereg(TVP_CSC6LO, (csc->R_Pr & 0xff));
tvp_writereg(TVP_CSC7HI, (csc->B_Y >> 8));
tvp_writereg(TVP_CSC7LO, (csc->B_Y & 0xff));
tvp_writereg(TVP_CSC8HI, (csc->B_Pb >> 8));
tvp_writereg(TVP_CSC8LO, (csc->B_Pb & 0xff));
tvp_writereg(TVP_CSC9HI, (csc->B_Pr >> 8));
tvp_writereg(TVP_CSC9LO, (csc->B_Pr & 0xff));
}
void tvp_set_lpf(alt_u8 val) {
alt_u8 status = tvp_readreg(TVP_VIDEOBWLIM) & 0xF0;
tvp_writereg(TVP_VIDEOBWLIM, status|val);
printf("TVP LPF value set to 0x%x\n", val);
}
void tvp_set_sync_lpf(alt_u8 val) {
alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0x3F;
tvp_writereg(TVP_INPMUX2, status|((3-val)<<6));
printf("Sync LPF value set to 0x%x\n", (3-val));
}
void tvp_set_hpll_phase(alt_u8 val) {
alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0x07;
tvp_writereg(TVP_HPLLPHASE, (val<<3)|status);
printf("Phase value set to 0x%x\n", val);
}
void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk) {
// Configure clock settings
tvp_sel_clk(refclk);
// Clamp position and ALC
tvp_set_clamp_position(type);
tvp_set_alc(type);
// Macrovision enable/disable, coast disable for RGBHV.
// Coast needs to be enabled when HSYNC is missing during VSYNC. Valid only for RGBHV?
// Macrovision should be enabled when serration pulses etc. present, so disable only for RGBHV.
switch (type) {
case VIDEO_PC:
//tvp_writereg(TVP_MISCCTRL4, 0x04);
tvp_writereg(TVP_MISCCTRL4, 0x0C);
tvp_writereg(TVP_MVSWIDTH, 0x03);
break;
case VIDEO_HDTV:
tvp_writereg(TVP_MISCCTRL4, 0x08);
tvp_writereg(TVP_MVSWIDTH, 0x0E);
break;
case VIDEO_LDTV:
case VIDEO_SDTV:
case VIDEO_EDTV:
tvp_writereg(TVP_MISCCTRL4, 0x08);
tvp_writereg(TVP_MVSWIDTH, 0x88); // TODO: check mode
break;
default:
break;
}
tvp_setup_hpll(video_modes[modeid].h_total, vlines, hz, !!(video_modes[modeid].flags & MODE_PLLDIVBY2));
//Long coast may lead to PLL frequency drift and sync loss (e.g. SNES)
/*if (video_modes[modeid].v_active < 720)
tvp_set_hpllcoast(3, 3);
else*/
tvp_set_hpllcoast(1, 0);
// Hsync output width
tvp_writereg(TVP_HSOUTWIDTH, video_modes[modeid].h_synclen);
}
void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk) {
alt_u8 sync_status;
alt_u8 sog_ch;
if ((fmt == FORMAT_RGsB) || (fmt == FORMAT_YPbPr))
sog_ch = (input == TVP_INPUT3) ? 2 : 0;
else if ((input == TVP_INPUT1) && (fmt == FORMAT_RGBS))
sog_ch = 1;
else
sog_ch = 2;
// RGB+SOG input select
tvp_writereg(TVP_INPMUX1, (sog_ch<<6) | (input<<4) | (input<<2) | input);
// Configure clock settings
tvp_sel_clk(refclk);
// Clamp setup
tvp_set_clamp(fmt);
// HV/SOG sync select
if ((input == TVP_INPUT3) && (fmt != FORMAT_RGsB)) {
if (fmt == FORMAT_RGBHV)
tvp_writereg(TVP_SYNCCTRL1, 0x52);
else // RGBS
tvp_writereg(TVP_SYNCCTRL1, 0x53);
sync_status = tvp_readreg(TVP_SYNCSTAT);
if (sync_status & (1<<7))
printf("%s detected, %s polarity\n", (sync_status & (1<<3)) ? "Csync" : "Hsync", (sync_status & (1<<5)) ? "pos" : "neg");
if (sync_status & (1<<4))
printf("Vsync detected, %s polarity\n", (sync_status & (1<<2)) ? "pos" : "neg");
} else {
tvp_writereg(TVP_SYNCCTRL1, 0x5B);
sync_status = tvp_readreg(TVP_SYNCSTAT);
if (sync_status & (1<<1))
printf("SOG detected\n");
else
printf("SOG not detected\n");
}
// Enable CSC for YPbPr
if (fmt == FORMAT_YPbPr)
tvp_writereg(TVP_MISCCTRL3, 0x10);
else
tvp_writereg(TVP_MISCCTRL3, 0x00);
#ifdef SYNCBYPASS
tvp_writereg(TVP_SYNCBYPASS, 0x03);
#else
tvp_writereg(TVP_SYNCBYPASS, 0x00);
#endif
//TODO:
//clamps
//TVP_ADCSETUP
printf("\n");
}
alt_u8 tvp_check_sync(tvp_input_t input) {
alt_u8 sync_status;
sync_status = tvp_readreg(TVP_SYNCSTAT);
if (input == TVP_INPUT3)
return !!((sync_status & 0x98) > 0x80);
//return !!((sync_status & 0x90) == 0x90);
else
return !!(sync_status & (1<<1));
}

View File

@ -0,0 +1,90 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef TVP7002_H_
#define TVP7002_H_
#include "tvp7002_regs.h"
#include "video_modes.h"
#include "sysconfig.h"
//#define I2C_DEBUG
#define I2CA_BASE I2C_OPENCORES_0_BASE
typedef enum {
TVP_INPUT1 = 0,
TVP_INPUT2 = 1,
TVP_INPUT3 = 2
} tvp_input_t;
static const alt_u8 Kvco[] = {75, 85, 150, 200};
static const char *Kvco_str[] = { "Ultra low", "Low", "Medium", "High" };
typedef enum {
REFCLK_EXT27 = 0,
REFCLK_INTCLK = 1
} tvp_refclk_t;
typedef struct {
const char *name;
alt_u16 R_Y;
alt_u16 R_Pb;
alt_u16 R_Pr;
alt_u16 G_Y;
alt_u16 G_Pb;
alt_u16 G_Pr;
alt_u16 B_Y;
alt_u16 B_Pb;
alt_u16 B_Pr;
} ypbpr_to_rgb_csc_t;
static const alt_u32 clkrate[] = {27000000, 6500000}; //in MHz
inline alt_u32 tvp_readreg(alt_u32 regaddr);
inline void tvp_writereg(alt_u32 regaddr, alt_u8 data);
inline void tvp_reset();
inline void tvp_disable_output();
inline void tvp_enable_output();
void tvp_init();
void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 plldivby2);
void tvp_sel_clk(alt_u8 refclk);
void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc);
void tvp_set_lpf(alt_u8 val);
void tvp_set_sync_lpf(alt_u8 val);
void tvp_set_hpll_phase(alt_u8 val);
void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk);
void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk);
alt_u8 tvp_check_sync(tvp_input_t input);
#endif /* TVP7002_H_ */

View File

@ -0,0 +1,117 @@
//
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef TVP7002_REGS_H_
#define TVP7002_REGS_H_
#define TVP_BASE (0xB8>>1)
#define TVP_CHIPREV 0x00
#define TVP_HPLLDIV_MSB 0x01
#define TVP_HPLLDIV_LSB 0x02
#define TVP_HPLLCTRL 0x03
#define TVP_HPLLPHASE 0x04
#define TVP_CLAMPSTART 0x05
#define TVP_CLAMPWIDTH 0x06
#define TVP_HSOUTWIDTH 0x07
#define TVP_B_FGAIN 0x08
#define TVP_G_FGAIN 0x09
#define TVP_R_FGAIN 0x0A
#define TVP_B_FOFFSET_MSB 0x0B
#define TVP_G_FOFFSET_MSB 0x0C
#define TVP_R_FOFFSET_MSB 0x0D
#define TVP_SYNCCTRL1 0x0E
#define TVP_HPLLCTRL2 0x0F
#define TVP_SOGTHOLD 0x10
#define TVP_SSTHOLD 0x11
#define TVP_HPLLPRECOAST 0x12
#define TVP_HPLLPOSTCOAST 0x13
#define TVP_SYNCSTAT 0x14
#define TVP_OUTFORMAT 0x15
#define TVP_MISCCTRL1 0x16
#define TVP_MISCCTRL2 0x17
#define TVP_MISCCTRL3 0x18
#define TVP_INPMUX1 0x19
#define TVP_INPMUX2 0x1A
#define TVP_BG_CGAIN 0x1B
#define TVP_R_CGAIN 0x1C
#define TVP_FOFFSET_LSB 0x1D
#define TVP_B_COFFSET 0x1E
#define TVP_G_COFFSET 0x1F
#define TVP_R_COFFSET 0x20
#define TVP_HSOUTSTART 0x21
#define TVP_MISCCTRL4 0x22
#define TVP_B_ALCOUT_LSB 0x23
#define TVP_G_ALCOUT_LSB 0x24
#define TVP_R_ALCOUT_LSB 0x25
#define TVP_ALCEN 0x26
#define TVP_ALCOUT_MSB 0x27
#define TVP_ALCFILT 0x28
#define TVP_FCLAMPCTRL 0x2A
#define TVP_POWERCTRL 0x2B
#define TVP_ADCSETUP 0x2C
#define TVP_CCLAMPCTRL 0x2D
#define TVP_SOGCLAMP 0x2E
#define TVP_RGBCCLAMPCTRL 0x2F
#define TVP_SOGCCLAMPCTRL 0x30
#define TVP_ALCPLACE 0x31
#define TVP_MVSWIDTH 0x34
#define TVP_VSOUTALIGN 0x35
#define TVP_SYNCBYPASS 0x36
#define TVP_LINECNT1 0x37
#define TVP_LINECNT2 0x38
#define TVP_CLKCNT1 0x39
#define TVP_CLKCNT2 0x3A
#define TVP_HSINWIDTH 0x3B
#define TVP_VSINWIDTH 0x3C
#define TVP_LINELENTOL 0x3D
#define TVP_VIDEOBWLIM 0x3F
#define TVP_AVIDSTART1 0x40
#define TVP_AVIDSTART2 0x41
#define TVP_AVIDSTOP1 0x42
#define TVP_AVIDSTOP2 0x43
#define TVP_VB0OFF 0x44
#define TVP_VB1OFF 0x45
#define TVP_VB0DUR 0x46
#define TVP_VB1DUR 0x47
#define TVP_CSC1LO 0x4A
#define TVP_CSC1HI 0x4B
#define TVP_CSC2LO 0x4C
#define TVP_CSC2HI 0x4D
#define TVP_CSC3LO 0x4E
#define TVP_CSC3HI 0x4F
#define TVP_CSC4LO 0x50
#define TVP_CSC4HI 0x51
#define TVP_CSC5LO 0x52
#define TVP_CSC5HI 0x53
#define TVP_CSC6LO 0x54
#define TVP_CSC6HI 0x55
#define TVP_CSC7LO 0x56
#define TVP_CSC7HI 0x57
#define TVP_CSC8LO 0x58
#define TVP_CSC8HI 0x59
#define TVP_CSC9LO 0x5A
#define TVP_CSC9HI 0x5B
#endif /* TVP7002_REGS_H_ */

Some files were not shown because too many files have changed in this diff Show More