mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-01-26 03:51:07 +00:00
Spy Hunter: add CSD board + update FX68K
This commit is contained in:
674
common/CPU/68000/FX68k/LICENSE
Normal file
674
common/CPU/68000/FX68k/LICENSE
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://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 <https://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
|
||||
<https://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
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
17
common/CPU/68000/FX68k/README.md
Normal file
17
common/CPU/68000/FX68k/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# fx68k
|
||||
FX68K 68000 cycle accurate SystemVerilog core
|
||||
|
||||
Copyright (c) 2018 by Jorge Cwik
|
||||
fx68k@fxatari.com
|
||||
|
||||
FX68K is a 68000 cycle exact compatible core. At least in theory, it should be impossible to distinguish functionally from a real 68K processor.
|
||||
|
||||
On Cyclone families it uses just over 5,100 LEs and about 5KB internal ram, reaching a max effective clock frequency close to 40MHz. Some optimizations are still possible to implement and increase the performance.
|
||||
|
||||
The core is fully synchronous. Considerable effort was made to avoid any asynchronous logic.
|
||||
|
||||
Written in SystemVerilog.
|
||||
|
||||
The timing of the external bus signals is exactly as the original processor. The only feature that is not implemented yet is bus retry using the external HALT input signal.
|
||||
|
||||
It was designed to replace an actual chip on a real board. This wasn't yet tested however and not all necessary output enable control signals are fully implemented.
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// microrom and nanorom instantiation
|
||||
//
|
||||
// There is bit of wasting of resources here. An extra registering pipeline happens that is not needed.
|
||||
// This is just for the purpose of helping inferring block RAM using pure generic code. Inferring RAM is important for performance.
|
||||
// Might be more efficient to use vendor specific features such as clock enable.
|
||||
//
|
||||
|
||||
module uRom( input clk, input [UADDR_WIDTH-1:0] microAddr, output logic [UROM_WIDTH-1:0] microOutput);
|
||||
reg [UROM_WIDTH-1:0] uRam[ UROM_DEPTH];
|
||||
initial begin
|
||||
$readmemb("microrom.mem", uRam);
|
||||
end
|
||||
|
||||
always_ff @( posedge clk)
|
||||
microOutput <= uRam[ microAddr];
|
||||
endmodule
|
||||
|
||||
|
||||
module nanoRom( input clk, input [NADDR_WIDTH-1:0] nanoAddr, output logic [NANO_WIDTH-1:0] nanoOutput);
|
||||
reg [NANO_WIDTH-1:0] nRam[ NANO_DEPTH];
|
||||
initial begin
|
||||
$readmemb("nanorom.mem", nRam);
|
||||
end
|
||||
|
||||
always_ff @( posedge clk)
|
||||
nanoOutput <= nRam[ nanoAddr];
|
||||
endmodule
|
||||
@@ -1,35 +0,0 @@
|
||||
// add bcd correction factor
|
||||
// It would be more efficient to merge add/sub with main ALU !!!
|
||||
module aluCorf( input [7:0] binResult, input bAdd, input cin, input hCarry,
|
||||
output [7:0] bcdResult, output dC, output logic ov);
|
||||
|
||||
reg [8:0] htemp;
|
||||
reg [4:0] hNib;
|
||||
|
||||
wire lowC = hCarry | (bAdd ? gt9( binResult[ 3:0]) : 1'b0);
|
||||
wire highC = cin | (bAdd ? (gt9( htemp[7:4]) | htemp[8]) : 1'b0);
|
||||
|
||||
always_comb begin
|
||||
if( bAdd) begin
|
||||
htemp = { 1'b0, binResult} + (lowC ? 4'h6 : 4'h0);
|
||||
hNib = htemp[8:4] + (highC ? 4'h6 : 4'h0);
|
||||
ov = hNib[3] & ~binResult[7];
|
||||
end
|
||||
else begin
|
||||
htemp = { 1'b0, binResult} - (lowC ? 4'h6 : 4'h0);
|
||||
hNib = htemp[8:4] - (highC ? 4'h6 : 4'h0);
|
||||
ov = ~hNib[3] & binResult[7];
|
||||
end
|
||||
end
|
||||
|
||||
assign bcdResult = { hNib[ 3:0], htemp[3:0]};
|
||||
assign dC = hNib[4] | cin;
|
||||
|
||||
// Nibble > 9
|
||||
function gt9 (input [3:0] nib);
|
||||
begin
|
||||
gt9 = nib[3] & (nib[2] | nib[1]);
|
||||
end
|
||||
endfunction
|
||||
|
||||
endmodule
|
||||
@@ -1,90 +0,0 @@
|
||||
// Get current OP from row & col
|
||||
module aluGetOp( input [15:0] row, input [2:0] col, input isCorf,
|
||||
output logic [4:0] aluOp);
|
||||
|
||||
always_comb begin
|
||||
aluOp = 'X;
|
||||
unique case( col)
|
||||
1: aluOp = OP_AND;
|
||||
5: aluOp = OP_EXT;
|
||||
|
||||
default:
|
||||
unique case( 1'b1)
|
||||
row[1]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUB;
|
||||
3: aluOp = OP_SUBC;
|
||||
4,6: aluOp = OP_SLAA;
|
||||
endcase
|
||||
|
||||
row[2]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_ADD;
|
||||
3: aluOp = OP_ADDC;
|
||||
4: aluOp = OP_ASR;
|
||||
endcase
|
||||
|
||||
row[3]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_ADDX;
|
||||
3: aluOp = isCorf ? OP_ABCD : OP_ADD;
|
||||
4: aluOp = OP_ASL;
|
||||
endcase
|
||||
|
||||
row[4]:
|
||||
aluOp = ( col == 4) ? OP_LSL : OP_AND;
|
||||
|
||||
row[5],
|
||||
row[6]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUB;
|
||||
3: aluOp = OP_SUBC;
|
||||
4: aluOp = OP_LSR;
|
||||
endcase
|
||||
|
||||
row[7]: // MUL
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUB;
|
||||
3: aluOp = OP_ADD;
|
||||
4: aluOp = OP_ROXR;
|
||||
endcase
|
||||
|
||||
row[8]:
|
||||
// OP_AND For EXT.L
|
||||
// But would be more efficient to change ucode and use column 1 instead of col3 at ublock extr1!
|
||||
unique case( col)
|
||||
2: aluOp = OP_EXT;
|
||||
3: aluOp = OP_AND;
|
||||
4: aluOp = OP_ROXR;
|
||||
endcase
|
||||
|
||||
row[9]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUBX;
|
||||
3: aluOp = OP_SBCD;
|
||||
4: aluOp = OP_ROL;
|
||||
endcase
|
||||
|
||||
row[10]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUBX;
|
||||
3: aluOp = OP_SUBC;
|
||||
4: aluOp = OP_ROR;
|
||||
endcase
|
||||
|
||||
row[11]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUB0;
|
||||
3: aluOp = OP_SUB0;
|
||||
4: aluOp = OP_ROXL;
|
||||
endcase
|
||||
|
||||
row[12]: aluOp = OP_ADDX;
|
||||
row[13]: aluOp = OP_EOR;
|
||||
row[14]: aluOp = (col == 4) ? OP_EOR : OP_OR;
|
||||
row[15]: aluOp = (col == 3) ? OP_ADD : OP_OR; // OP_ADD used by DBcc
|
||||
|
||||
endcase
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
@@ -1,32 +0,0 @@
|
||||
module aluShifter( input [31:0] data,
|
||||
input isByte, input isLong, swapWords,
|
||||
input dir, input cin,
|
||||
output logic [31:0] result);
|
||||
// output reg cout
|
||||
|
||||
logic [31:0] tdata;
|
||||
|
||||
// size mux, put cin in position if dir == right
|
||||
always_comb begin
|
||||
tdata = data;
|
||||
if( isByte & dir)
|
||||
tdata[8] = cin;
|
||||
else if( !isLong & dir)
|
||||
tdata[16] = cin;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
// Reverse alu/alue position for MUL & DIV
|
||||
// Result reversed again
|
||||
if( swapWords & dir)
|
||||
result = { tdata[0], tdata[31:17], cin, tdata[15:1]};
|
||||
else if( swapWords)
|
||||
result = { tdata[30:16], cin, tdata[14:0], tdata[31]};
|
||||
|
||||
else if( dir)
|
||||
result = { cin, tdata[31:1]};
|
||||
else
|
||||
result = { tdata[30:0], cin};
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,87 +0,0 @@
|
||||
//
|
||||
// DMA/BUS Arbitration
|
||||
//
|
||||
|
||||
module busArbiter( input s_clks Clks,
|
||||
input BRi, BgackI, Halti, bgBlock,
|
||||
output busAvail,
|
||||
output logic BGn);
|
||||
|
||||
enum int unsigned { DRESET = 0, DIDLE, D1, D_BR, D_BA, D_BRA, D3, D2} dmaPhase, next;
|
||||
|
||||
always_comb begin
|
||||
case(dmaPhase)
|
||||
DRESET: next = DIDLE;
|
||||
DIDLE: begin
|
||||
if( bgBlock)
|
||||
next = DIDLE;
|
||||
else if( ~BgackI)
|
||||
next = D_BA;
|
||||
else if( ~BRi)
|
||||
next = D1;
|
||||
else
|
||||
next = DIDLE;
|
||||
end
|
||||
|
||||
D_BA: begin // Loop while only BGACK asserted, BG negated here
|
||||
if( ~BRi & !bgBlock)
|
||||
next = D3;
|
||||
else if( ~BgackI & !bgBlock)
|
||||
next = D_BA;
|
||||
else
|
||||
next = DIDLE;
|
||||
end
|
||||
|
||||
D1: next = D_BR; // Loop while only BR asserted
|
||||
D_BR: next = ~BRi & BgackI ? D_BR : D_BA; // No direct path to IDLE !
|
||||
|
||||
D3: next = D_BRA;
|
||||
D_BRA: begin // Loop while both BR and BGACK asserted
|
||||
case( {BgackI, BRi} )
|
||||
2'b11: next = DIDLE; // Both deasserted
|
||||
2'b10: next = D_BR; // BR asserted only
|
||||
2'b01: next = D2; // BGACK asserted only
|
||||
2'b00: next = D_BRA; // Stay here while both asserted
|
||||
endcase
|
||||
end
|
||||
|
||||
// Might loop here if both deasserted, should normally don't arrive here anyway?
|
||||
// D2: next = (BgackI & BRi) | bgBlock ? D2: D_BA;
|
||||
|
||||
D2: next = D_BA;
|
||||
|
||||
default: next = DIDLE; // Should not reach here normally
|
||||
endcase
|
||||
end
|
||||
|
||||
logic granting;
|
||||
always_comb begin
|
||||
unique case( next)
|
||||
D1, D3, D_BR, D_BRA: granting = 1'b1;
|
||||
default: granting = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
reg rGranted;
|
||||
assign busAvail = Halti & BRi & BgackI & ~rGranted;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( Clks.extReset) begin
|
||||
dmaPhase <= DRESET;
|
||||
rGranted <= 1'b0;
|
||||
end
|
||||
else if( Clks.enPhi2) begin
|
||||
dmaPhase <= next;
|
||||
// Internal signal changed on PHI2
|
||||
rGranted <= granting;
|
||||
end
|
||||
|
||||
// External Output changed on PHI1
|
||||
if( Clks.extReset)
|
||||
BGn <= 1'b1;
|
||||
else if( Clks.enPhi1)
|
||||
BGn <= ~rGranted;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,197 +0,0 @@
|
||||
module busControl( input s_clks Clks, input enT1, input enT4,
|
||||
input permStart, permStop, iStop,
|
||||
input aob0,
|
||||
input isWrite, isByte, isRmc,
|
||||
input busAvail,
|
||||
output bgBlock,
|
||||
output busAddrErr,
|
||||
output waitBusCycle,
|
||||
output busStarting, // Asserted during S0
|
||||
output logic addrOe, // Asserted from S1 to the end, whole bus cycle except S0
|
||||
output bciWrite, // Used for SSW on bus/addr error
|
||||
|
||||
input rDtack, BeDebounced, Vpai,
|
||||
output ASn, output LDSn, output UDSn, eRWn);
|
||||
|
||||
reg rAS, rLDS, rUDS, rRWn;
|
||||
assign ASn = rAS;
|
||||
assign LDSn = rLDS;
|
||||
assign UDSn = rUDS;
|
||||
assign eRWn = rRWn;
|
||||
|
||||
reg dataOe;
|
||||
|
||||
reg bcPend;
|
||||
reg isWriteReg, bciByte, isRmcReg, wendReg;
|
||||
assign bciWrite = isWriteReg;
|
||||
reg addrOeDelay;
|
||||
reg isByteT4;
|
||||
|
||||
wire canStart, busEnd;
|
||||
wire bcComplete, bcReset;
|
||||
|
||||
wire isRcmReset = bcComplete & bcReset & isRmcReg;
|
||||
|
||||
assign busAddrErr = aob0 & ~bciByte;
|
||||
|
||||
// Bus retry not really supported.
|
||||
// It's BERR and HALT and not address error, and not read-modify cycle.
|
||||
wire busRetry = ~busAddrErr & 1'b0;
|
||||
|
||||
enum int unsigned { SRESET = 0, SIDLE, S0, S2, S4, S6, SRMC_RES} busPhase, next;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( Clks.extReset)
|
||||
busPhase <= SRESET;
|
||||
else if( Clks.enPhi1)
|
||||
busPhase <= next;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
case( busPhase)
|
||||
SRESET: next = SIDLE;
|
||||
SRMC_RES: next = SIDLE; // Single cycle special state when read phase of RMC reset
|
||||
S0: next = S2;
|
||||
S2: next = S4;
|
||||
S4: next = busEnd ? S6 : S4;
|
||||
S6: next = isRcmReset ? SRMC_RES : (canStart ? S0 : SIDLE);
|
||||
SIDLE: next = canStart ? S0 : SIDLE;
|
||||
default: next = SIDLE;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Idle phase of RMC bus cycle. Might be better to just add a new state
|
||||
wire rmcIdle = (busPhase == SIDLE) & ~ASn & isRmcReg;
|
||||
|
||||
assign canStart = (busAvail | rmcIdle) & (bcPend | permStart) & !busRetry & !bcReset;
|
||||
|
||||
wire busEnding = (next == SIDLE) | (next == S0);
|
||||
|
||||
assign busStarting = (busPhase == S0);
|
||||
|
||||
// term signal (DTACK, BERR, VPA, adress error)
|
||||
assign busEnd = ~rDtack | iStop;
|
||||
|
||||
// bcComplete asserted on raising edge of S6 (together with SNC).
|
||||
assign bcComplete = (busPhase == S6);
|
||||
|
||||
// Clear bus info latch on completion (regular or aborted) and no bus retry (and not PHI1).
|
||||
// bciClear asserted half clock later on PHI2, and bci latches cleared async concurrently
|
||||
wire bciClear = bcComplete & ~busRetry;
|
||||
|
||||
// Reset on reset or (berr & berrDelay & (not halt or rmc) & not 6800 & in bus cycle) (and not PHI1)
|
||||
assign bcReset = Clks.extReset | (addrOeDelay & BeDebounced & Vpai);
|
||||
|
||||
// Enable uclock only on S6 (S8 on Bus Error) or not bciPermStop
|
||||
assign waitBusCycle = wendReg & !bcComplete;
|
||||
|
||||
// Block Bus Grant when starting new bus cycle. But No need if AS already asserted (read phase of RMC)
|
||||
// Except that when that RMC phase aborted on bus error, it's asserted one cycle later!
|
||||
assign bgBlock = ((busPhase == S0) & ASn) | (busPhase == SRMC_RES);
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( Clks.extReset) begin
|
||||
addrOe <= 1'b0;
|
||||
end
|
||||
else if( Clks.enPhi2 & ( busPhase == S0)) // From S1, whole bus cycle except S0
|
||||
addrOe <= 1'b1;
|
||||
else if( Clks.enPhi1 & (busPhase == SRMC_RES))
|
||||
addrOe <= 1'b0;
|
||||
else if( Clks.enPhi1 & ~isRmcReg & busEnding)
|
||||
addrOe <= 1'b0;
|
||||
|
||||
if( Clks.enPhi1)
|
||||
addrOeDelay <= addrOe;
|
||||
|
||||
if( Clks.extReset) begin
|
||||
rAS <= 1'b1;
|
||||
rUDS <= 1'b1;
|
||||
rLDS <= 1'b1;
|
||||
rRWn <= 1'b1;
|
||||
dataOe <= '0;
|
||||
end
|
||||
else begin
|
||||
|
||||
if( Clks.enPhi2 & isWriteReg & (busPhase == S2))
|
||||
dataOe <= 1'b1;
|
||||
else if( Clks.enPhi1 & (busEnding | (busPhase == SIDLE)) )
|
||||
dataOe <= 1'b0;
|
||||
|
||||
if( Clks.enPhi1 & busEnding)
|
||||
rRWn <= 1'b1;
|
||||
else if( Clks.enPhi1 & isWriteReg) begin
|
||||
// Unlike LDS/UDS Asserted even in address error
|
||||
if( (busPhase == S0) & isWriteReg)
|
||||
rRWn <= 1'b0;
|
||||
end
|
||||
|
||||
// AS. Actually follows addrOe half cycle later!
|
||||
if( Clks.enPhi1 & (busPhase == S0))
|
||||
rAS <= 1'b0;
|
||||
else if( Clks.enPhi2 & (busPhase == SRMC_RES)) // Bus error on read phase of RMC. Deasserted one cycle later
|
||||
rAS <= 1'b1;
|
||||
else if( Clks.enPhi2 & bcComplete & ~SRMC_RES)
|
||||
if( ~isRmcReg) // Keep AS asserted on the IDLE phase of RMC
|
||||
rAS <= 1'b1;
|
||||
|
||||
if( Clks.enPhi1 & (busPhase == S0)) begin
|
||||
if( ~isWriteReg & !busAddrErr) begin
|
||||
rUDS <= ~(~bciByte | ~aob0);
|
||||
rLDS <= ~(~bciByte | aob0);
|
||||
end
|
||||
end
|
||||
else if( Clks.enPhi1 & isWriteReg & (busPhase == S2) & !busAddrErr) begin
|
||||
rUDS <= ~(~bciByte | ~aob0);
|
||||
rLDS <= ~(~bciByte | aob0);
|
||||
end
|
||||
else if( Clks.enPhi2 & bcComplete) begin
|
||||
rUDS <= 1'b1;
|
||||
rLDS <= 1'b1;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
// Bus cycle info latch. Needed because uinstr might change if the bus is busy and we must wait.
|
||||
// Note that urom advances even on wait states. It waits *after* updating urom and nanorom latches.
|
||||
// Even without wait states, ublocks of type ir (init reading) will not wait for bus completion.
|
||||
// Originally latched on (permStart AND T1).
|
||||
|
||||
// Bus cycle info latch: isRead, isByte, read-modify-cycle, and permStart (bus cycle pending). Some previously latched on T4?
|
||||
// permStop also latched, but unconditionally on T1
|
||||
|
||||
// Might make more sense to register this outside this module
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( enT4) begin
|
||||
isByteT4 <= isByte;
|
||||
end
|
||||
end
|
||||
|
||||
// Bus Cycle Info Latch
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( Clks.pwrUp) begin
|
||||
bcPend <= 1'b0;
|
||||
wendReg <= 1'b0;
|
||||
isWriteReg <= 1'b0;
|
||||
bciByte <= 1'b0;
|
||||
isRmcReg <= 1'b0;
|
||||
end
|
||||
|
||||
else if( Clks.enPhi2 & (bciClear | bcReset)) begin
|
||||
bcPend <= 1'b0;
|
||||
wendReg <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
if( enT1 & permStart) begin
|
||||
isWriteReg <= isWrite;
|
||||
bciByte <= isByteT4;
|
||||
isRmcReg <= isRmc & ~isWrite; // We need special case the end of the read phase only.
|
||||
bcPend <= 1'b1;
|
||||
end
|
||||
if( enT1)
|
||||
wendReg <= permStop;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,76 +0,0 @@
|
||||
// Row/col CCR update table
|
||||
module ccrTable(
|
||||
input [2:0] col, input [15:0] row, input finish,
|
||||
output logic [MASK_NBITS-1:0] ccrMask);
|
||||
|
||||
localparam
|
||||
KNZ00 = 5'b01111, // ok coz operators clear them
|
||||
KKZKK = 5'b00100,
|
||||
KNZKK = 5'b01100,
|
||||
KNZ10 = 5'b01111, // Used by OP_EXT on divison overflow
|
||||
KNZ0C = 5'b01111, // Used by DIV. V should be 0, but it is ok:
|
||||
// DIVU: ends with quotient - 0, so V & C always clear.
|
||||
// DIVS: ends with 1i (AND), again, V & C always clear.
|
||||
|
||||
KNZVC = 5'b01111,
|
||||
CUPDALL = 5'b11111,
|
||||
CUNUSED = 5'bxxxxx;
|
||||
|
||||
|
||||
logic [MASK_NBITS-1:0] ccrMask1;
|
||||
|
||||
always_comb begin
|
||||
unique case( col)
|
||||
1: ccrMask = ccrMask1;
|
||||
|
||||
2,3:
|
||||
unique case( 1'b1)
|
||||
row[1]: ccrMask = KNZ0C; // DIV, used as 3n in col3
|
||||
row[2],
|
||||
row[3], // ABCD
|
||||
row[5],
|
||||
row[9], // SBCD/NBCD
|
||||
row[10], // SUBX/NEGX
|
||||
row[12]: ccrMask = CUPDALL; // ADDX
|
||||
row[6], // CMP
|
||||
row[7], // MUL
|
||||
row[11]: ccrMask = KNZVC; // NOT
|
||||
row[4],
|
||||
row[8], // Not used in col 3
|
||||
row[13],
|
||||
row[14]: ccrMask = KNZ00;
|
||||
row[15]: ccrMask = 5'b0; // TAS/Scc, not used in col 3
|
||||
// default: ccrMask = CUNUSED;
|
||||
endcase
|
||||
|
||||
4:
|
||||
unique case( row)
|
||||
// 1: DIV, only n (4n & 6n)
|
||||
// 14: BCLR 4n
|
||||
// 6,12,13,15 // not used
|
||||
`ALU_ROW_02,
|
||||
`ALU_ROW_03, // ASL (originally ANZVA)
|
||||
`ALU_ROW_04,
|
||||
`ALU_ROW_05: ccrMask = CUPDALL; // Shifts (originally ANZ0A)
|
||||
|
||||
`ALU_ROW_07: ccrMask = KNZ00; // MUL (originally KNZ0A)
|
||||
`ALU_ROW_09,
|
||||
`ALU_ROW_10: ccrMask = KNZ00; // RO[lr] (originally KNZ0A)
|
||||
`ALU_ROW_11: ccrMask = CUPDALL; // ROXL (originally ANZ0A)
|
||||
default: ccrMask = CUNUSED;
|
||||
endcase
|
||||
|
||||
5: ccrMask = row[1] ? KNZ10 : 5'b0;
|
||||
default: ccrMask = CUNUSED;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Column 1 (AND)
|
||||
always_comb begin
|
||||
if( finish)
|
||||
ccrMask1 = row[7] ? KNZ00 : KNZKK;
|
||||
else
|
||||
ccrMask1 = row[13] | row[14] ? KKZKK : KNZ00;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,97 +0,0 @@
|
||||
//
|
||||
// Data bus I/O
|
||||
// At a separate module because it is a bit complicated and the timing is special.
|
||||
// Here we do the low/high byte mux and the special case of MOVEP.
|
||||
//
|
||||
// Original implementation is rather complex because both the internal and external buses are bidirectional.
|
||||
// Input is latched async at the EDB register.
|
||||
// We capture directly from the external data bus to the internal registers (IRC & DBIN) on PHI2, starting the external S7 phase, at a T4 internal period.
|
||||
|
||||
module dataIo( input s_clks Clks,
|
||||
input enT1, enT2, enT3, enT4,
|
||||
input s_nanod Nanod, input s_irdecod Irdecod,
|
||||
input [15:0] iEdb,
|
||||
input aob0,
|
||||
|
||||
input dobIdle,
|
||||
input [15:0] dobInput,
|
||||
|
||||
output logic [15:0] Irc,
|
||||
output logic [15:0] dbin,
|
||||
output logic [15:0] oEdb
|
||||
);
|
||||
|
||||
reg [15:0] dob;
|
||||
|
||||
// DBIN/IRC
|
||||
|
||||
// Timing is different than any other register. We can latch only on the next T4 (bus phase S7).
|
||||
// We need to register all control signals correctly because the next ublock will already be started.
|
||||
// Can't latch control on T4 because if there are wait states there might be multiple T4 before we latch.
|
||||
|
||||
reg xToDbin, xToIrc;
|
||||
reg dbinNoLow, dbinNoHigh;
|
||||
reg byteMux, isByte_T4;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
|
||||
// Byte mux control. Can't latch at T1. AOB might be not ready yet.
|
||||
// Must latch IRD decode at T1 (or T4). Then combine and latch only at T3.
|
||||
|
||||
// Can't latch at T3, a new IRD might be loaded already at T1.
|
||||
// Ok to latch at T4 if combination latched then at T3
|
||||
if( enT4)
|
||||
isByte_T4 <= Irdecod.isByte; // Includes MOVEP from mem, we could OR it here
|
||||
|
||||
if( enT3) begin
|
||||
dbinNoHigh <= Nanod.noHighByte;
|
||||
dbinNoLow <= Nanod.noLowByte;
|
||||
byteMux <= Nanod.busByte & isByte_T4 & ~aob0;
|
||||
end
|
||||
|
||||
if( enT1) begin
|
||||
// If on wait states, we continue latching until next T1
|
||||
xToDbin <= 1'b0;
|
||||
xToIrc <= 1'b0;
|
||||
end
|
||||
else if( enT3) begin
|
||||
xToDbin <= Nanod.todbin;
|
||||
xToIrc <= Nanod.toIrc;
|
||||
end
|
||||
|
||||
// Capture on T4 of the next ucycle
|
||||
// If there are wait states, we keep capturing every PHI2 until the next T1
|
||||
|
||||
if( xToIrc & Clks.enPhi2)
|
||||
Irc <= iEdb;
|
||||
if( xToDbin & Clks.enPhi2) begin
|
||||
// Original connects both halves of EDB.
|
||||
if( ~dbinNoLow)
|
||||
dbin[ 7:0] <= byteMux ? iEdb[ 15:8] : iEdb[7:0];
|
||||
if( ~dbinNoHigh)
|
||||
dbin[ 15:8] <= ~byteMux & dbinNoLow ? iEdb[ 7:0] : iEdb[ 15:8];
|
||||
end
|
||||
end
|
||||
|
||||
// DOB
|
||||
logic byteCycle;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
// Originaly on T1. Transfer to internal EDB also on T1 (stays enabled upto the next T1). But only on T4 (S3) output enables.
|
||||
// It is safe to do on T3, then, but control signals if derived from IRD must be registered.
|
||||
// Originally control signals are not registered.
|
||||
|
||||
// Wait states don't affect DOB operation that is done at the start of the bus cycle.
|
||||
|
||||
if( enT4)
|
||||
byteCycle <= Nanod.busByte & Irdecod.isByte; // busIsByte but not MOVEP
|
||||
|
||||
// Originally byte low/high interconnect is done at EDB, not at DOB.
|
||||
if( enT3 & ~dobIdle) begin
|
||||
dob[7:0] <= Nanod.noLowByte ? dobInput[15:8] : dobInput[ 7:0];
|
||||
dob[15:8] <= (byteCycle | Nanod.noHighByte) ? dobInput[ 7:0] : dobInput[15:8];
|
||||
end
|
||||
end
|
||||
assign oEdb = dob;
|
||||
|
||||
endmodule
|
||||
@@ -1,553 +0,0 @@
|
||||
/*
|
||||
Execution unit
|
||||
|
||||
Executes register transfers set by the microcode. Originally through a set of bidirectional buses.
|
||||
Most sources are available at T3, but DBIN only at T4! CCR also might be updated at T4, but it is not connected to these buses.
|
||||
We mux at T1 and T2, then transfer to the destination at T3. The exception is AOB that need to be updated earlier.
|
||||
|
||||
*/
|
||||
|
||||
module excUnit( input s_clks Clks,
|
||||
input enT1, enT2, enT3, enT4,
|
||||
input s_nanod Nanod, input s_irdecod Irdecod,
|
||||
input [15:0] Ird, // ALU row (and others) decoder needs it
|
||||
input pswS,
|
||||
input [15:0] ftu,
|
||||
input [15:0] iEdb,
|
||||
|
||||
output logic [7:0] ccr,
|
||||
output [15:0] alue,
|
||||
|
||||
output prenEmpty, au05z,
|
||||
output logic dcr4, ze,
|
||||
output logic aob0,
|
||||
output [15:0] AblOut,
|
||||
output logic [15:0] Irc,
|
||||
output logic [15:0] oEdb,
|
||||
output logic [23:1] eab);
|
||||
|
||||
localparam REG_USP = 15;
|
||||
localparam REG_SSP = 16;
|
||||
localparam REG_DT = 17;
|
||||
|
||||
// Register file
|
||||
reg [15:0] regs68L[ 18];
|
||||
reg [15:0] regs68H[ 18];
|
||||
|
||||
// synthesis translate off
|
||||
/*
|
||||
It is bad practice to initialize simulation registers that the hardware doesn't.
|
||||
There is risk that simulation would be different than the real hardware. But in this case is the other way around.
|
||||
Some ROM uses something like sub.l An,An at powerup which clears the register
|
||||
Simulator power ups the registers with 'X, as they are really undetermined at the real hardware.
|
||||
But the simulator doesn't realize (it can't) that the same value is substracting from itself,
|
||||
and that the result should be zero even when it's 'X - 'X.
|
||||
*/
|
||||
|
||||
initial begin
|
||||
for( int i = 0; i < 18; i++) begin
|
||||
regs68L[i] <= '0;
|
||||
regs68H[i] <= '0;
|
||||
end
|
||||
end
|
||||
|
||||
// For simulation display only
|
||||
wire [31:0] SSP = { regs68H[REG_SSP], regs68L[REG_SSP]};
|
||||
|
||||
// synthesis translate on
|
||||
|
||||
|
||||
wire [15:0] aluOut;
|
||||
wire [15:0] dbin;
|
||||
logic [15:0] dcrOutput;
|
||||
|
||||
reg [15:0] PcL, PcH;
|
||||
|
||||
reg [31:0] auReg, aob;
|
||||
|
||||
reg [15:0] Ath, Atl;
|
||||
|
||||
// Bus execution
|
||||
reg [15:0] Dbl, Dbh;
|
||||
reg [15:0] Abh, Abl;
|
||||
reg [15:0] Abd, Dbd;
|
||||
|
||||
assign AblOut = Abl;
|
||||
assign au05z = (~| auReg[5:0]);
|
||||
|
||||
logic [15:0] dblMux, dbhMux;
|
||||
logic [15:0] abhMux, ablMux;
|
||||
logic [15:0] abdMux, dbdMux;
|
||||
|
||||
logic abdIsByte;
|
||||
|
||||
logic Pcl2Dbl, Pch2Dbh;
|
||||
logic Pcl2Abl, Pch2Abh;
|
||||
|
||||
|
||||
// RX RY muxes
|
||||
// RX and RY actual registers
|
||||
logic [4:0] actualRx, actualRy;
|
||||
logic [3:0] movemRx;
|
||||
logic byteNotSpAlign; // Byte instruction and no sp word align
|
||||
|
||||
// IRD decoded signals must be latched. See comments on decoder
|
||||
// But nanostore decoding can't be latched before T4.
|
||||
//
|
||||
// If we need this earlier we can register IRD decode on T3 and use nano async
|
||||
|
||||
logic [4:0] rxMux, ryMux;
|
||||
logic [3:0] rxReg, ryReg;
|
||||
logic rxIsSp, ryIsSp;
|
||||
logic rxIsAreg, ryIsAreg;
|
||||
|
||||
always_comb begin
|
||||
|
||||
// Unique IF !!
|
||||
if( Nanod.ssp) begin
|
||||
rxMux = REG_SSP;
|
||||
rxIsSp = 1'b1;
|
||||
rxReg = 1'bX;
|
||||
end
|
||||
else if( Irdecod.rxIsUsp) begin
|
||||
rxMux = REG_USP;
|
||||
rxIsSp = 1'b1;
|
||||
rxReg = 1'bX;
|
||||
end
|
||||
else if( Irdecod.rxIsDt & !Irdecod.implicitSp) begin
|
||||
rxMux = REG_DT;
|
||||
rxIsSp = 1'b0;
|
||||
rxReg = 1'bX;
|
||||
end
|
||||
else begin
|
||||
if( Irdecod.implicitSp)
|
||||
rxReg = 15;
|
||||
else if( Irdecod.rxIsMovem)
|
||||
rxReg = movemRx;
|
||||
else
|
||||
rxReg = { Irdecod.rxIsAreg, Irdecod.rx};
|
||||
|
||||
if( (& rxReg)) begin
|
||||
rxMux = pswS ? REG_SSP : 15;
|
||||
rxIsSp = 1'b1;
|
||||
end
|
||||
else begin
|
||||
rxMux = { 1'b0, rxReg};
|
||||
rxIsSp = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// RZ has higher priority!
|
||||
if( Irdecod.ryIsDt & !Nanod.rz) begin
|
||||
ryMux = REG_DT;
|
||||
ryIsSp = 1'b0;
|
||||
ryReg = 'X;
|
||||
end
|
||||
else begin
|
||||
ryReg = Nanod.rz ? Irc[15:12] : {Irdecod.ryIsAreg, Irdecod.ry};
|
||||
ryIsSp = (& ryReg);
|
||||
if( ryIsSp & pswS) // No implicit SP on RY
|
||||
ryMux = REG_SSP;
|
||||
else
|
||||
ryMux = { 1'b0, ryReg};
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( enT4) begin
|
||||
byteNotSpAlign <= Irdecod.isByte & ~(Nanod.rxlDbl ? rxIsSp : ryIsSp);
|
||||
|
||||
actualRx <= rxMux;
|
||||
actualRy <= ryMux;
|
||||
|
||||
rxIsAreg <= rxIsSp | rxMux[3];
|
||||
ryIsAreg <= ryIsSp | ryMux[3];
|
||||
end
|
||||
|
||||
if( enT4)
|
||||
abdIsByte <= Nanod.abdIsByte & Irdecod.isByte;
|
||||
end
|
||||
|
||||
// Set RX/RY low word to which bus segment is connected.
|
||||
|
||||
wire ryl2Abl = Nanod.ryl2ab & (ryIsAreg | Nanod.ablAbd);
|
||||
wire ryl2Abd = Nanod.ryl2ab & (~ryIsAreg | Nanod.ablAbd);
|
||||
wire ryl2Dbl = Nanod.ryl2db & (ryIsAreg | Nanod.dblDbd);
|
||||
wire ryl2Dbd = Nanod.ryl2db & (~ryIsAreg | Nanod.dblDbd);
|
||||
|
||||
wire rxl2Abl = Nanod.rxl2ab & (rxIsAreg | Nanod.ablAbd);
|
||||
wire rxl2Abd = Nanod.rxl2ab & (~rxIsAreg | Nanod.ablAbd);
|
||||
wire rxl2Dbl = Nanod.rxl2db & (rxIsAreg | Nanod.dblDbd);
|
||||
wire rxl2Dbd = Nanod.rxl2db & (~rxIsAreg | Nanod.dblDbd);
|
||||
|
||||
// Buses. Main mux
|
||||
|
||||
logic abhIdle, ablIdle, abdIdle;
|
||||
logic dbhIdle, dblIdle, dbdIdle;
|
||||
|
||||
always_comb begin
|
||||
{abhIdle, ablIdle, abdIdle} = '0;
|
||||
{dbhIdle, dblIdle, dbdIdle} = '0;
|
||||
|
||||
unique case( 1'b1)
|
||||
ryl2Dbd: dbdMux = regs68L[ actualRy];
|
||||
rxl2Dbd: dbdMux = regs68L[ actualRx];
|
||||
Nanod.alue2Dbd: dbdMux = alue;
|
||||
Nanod.dbin2Dbd: dbdMux = dbin;
|
||||
Nanod.alu2Dbd: dbdMux = aluOut;
|
||||
Nanod.dcr2Dbd: dbdMux = dcrOutput;
|
||||
default: begin dbdMux = 'X; dbdIdle = 1'b1; end
|
||||
endcase
|
||||
|
||||
unique case( 1'b1)
|
||||
rxl2Dbl: dblMux = regs68L[ actualRx];
|
||||
ryl2Dbl: dblMux = regs68L[ actualRy];
|
||||
Nanod.ftu2Dbl: dblMux = ftu;
|
||||
Nanod.au2Db: dblMux = auReg[15:0];
|
||||
Nanod.atl2Dbl: dblMux = Atl;
|
||||
Pcl2Dbl: dblMux = PcL;
|
||||
default: begin dblMux = 'X; dblIdle = 1'b1; end
|
||||
endcase
|
||||
|
||||
unique case( 1'b1)
|
||||
Nanod.rxh2dbh: dbhMux = regs68H[ actualRx];
|
||||
Nanod.ryh2dbh: dbhMux = regs68H[ actualRy];
|
||||
Nanod.au2Db: dbhMux = auReg[31:16];
|
||||
Nanod.ath2Dbh: dbhMux = Ath;
|
||||
Pch2Dbh: dbhMux = PcH;
|
||||
default: begin dbhMux = 'X; dbhIdle = 1'b1; end
|
||||
endcase
|
||||
|
||||
unique case( 1'b1)
|
||||
ryl2Abd: abdMux = regs68L[ actualRy];
|
||||
rxl2Abd: abdMux = regs68L[ actualRx];
|
||||
Nanod.dbin2Abd: abdMux = dbin;
|
||||
Nanod.alu2Abd: abdMux = aluOut;
|
||||
default: begin abdMux = 'X; abdIdle = 1'b1; end
|
||||
endcase
|
||||
|
||||
unique case( 1'b1)
|
||||
Pcl2Abl: ablMux = PcL;
|
||||
rxl2Abl: ablMux = regs68L[ actualRx];
|
||||
ryl2Abl: ablMux = regs68L[ actualRy];
|
||||
Nanod.ftu2Abl: ablMux = ftu;
|
||||
Nanod.au2Ab: ablMux = auReg[15:0];
|
||||
Nanod.aob2Ab: ablMux = aob[15:0];
|
||||
Nanod.atl2Abl: ablMux = Atl;
|
||||
default: begin ablMux = 'X; ablIdle = 1'b1; end
|
||||
endcase
|
||||
|
||||
unique case( 1'b1)
|
||||
Pch2Abh: abhMux = PcH;
|
||||
Nanod.rxh2abh: abhMux = regs68H[ actualRx];
|
||||
Nanod.ryh2abh: abhMux = regs68H[ actualRy];
|
||||
Nanod.au2Ab: abhMux = auReg[31:16];
|
||||
Nanod.aob2Ab: abhMux = aob[31:16];
|
||||
Nanod.ath2Abh: abhMux = Ath;
|
||||
default: begin abhMux = 'X; abhIdle = 1'b1; end
|
||||
endcase
|
||||
|
||||
end
|
||||
|
||||
// Source starts driving the bus on T1. Bus holds data until end of T3. Destination latches at T3.
|
||||
|
||||
// These registers store the first level mux, without bus interconnections.
|
||||
// Even when this uses almost to 100 registers, it saves a lot of comb muxing and it is much faster.
|
||||
reg [15:0] preAbh, preAbl, preAbd;
|
||||
reg [15:0] preDbh, preDbl, preDbd;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
|
||||
// Register first level mux at T1
|
||||
if( enT1) begin
|
||||
{preAbh, preAbl, preAbd} <= { abhMux, ablMux, abdMux};
|
||||
{preDbh, preDbl, preDbd} <= { dbhMux, dblMux, dbdMux};
|
||||
end
|
||||
|
||||
// Process bus interconnection at T2. Many combinations only used on DIV
|
||||
// We use a simple method. If a specific bus segment is not driven we know that it should get data from a neighbour segment.
|
||||
// In some cases this is not true and the segment is really idle without any destination. But then it doesn't matter.
|
||||
|
||||
if( enT2) begin
|
||||
if( Nanod.extAbh)
|
||||
Abh <= { 16{ ablIdle ? preAbd[ 15] : preAbl[ 15] }};
|
||||
else if( abhIdle)
|
||||
Abh <= ablIdle ? preAbd : preAbl;
|
||||
else
|
||||
Abh <= preAbh;
|
||||
|
||||
if( ~ablIdle)
|
||||
Abl <= preAbl;
|
||||
else
|
||||
Abl <= Nanod.ablAbh ? preAbh : preAbd;
|
||||
|
||||
Abd <= ~abdIdle ? preAbd : ablIdle ? preAbh : preAbl;
|
||||
|
||||
if( Nanod.extDbh)
|
||||
Dbh <= { 16{ dblIdle ? preDbd[ 15] : preDbl[ 15] }};
|
||||
else if( dbhIdle)
|
||||
Dbh <= dblIdle ? preDbd : preDbl;
|
||||
else
|
||||
Dbh <= preDbh;
|
||||
|
||||
if( ~dblIdle)
|
||||
Dbl <= preDbl;
|
||||
else
|
||||
Dbl <= Nanod.dblDbh ? preDbh : preDbd;
|
||||
|
||||
Dbd <= ~dbdIdle ? preDbd: dblIdle ? preDbh : preDbl;
|
||||
|
||||
/*
|
||||
Dbl <= dblMux; Dbh <= dbhMux;
|
||||
Abd <= abdMux; Dbd <= dbdMux;
|
||||
Abh <= abhMux; Abl <= ablMux; */
|
||||
end
|
||||
end
|
||||
|
||||
// AOB
|
||||
//
|
||||
// Originally change on T1. We do on T2, only then the output is enabled anyway.
|
||||
//
|
||||
// AOB[0] is used for address error. But even when raises on T1, seems not actually used until T2 or possibly T3.
|
||||
// It is used on T1 when deasserted at the BSER exception ucode. Probably deassertion timing is not critical.
|
||||
// But in that case (at BSER), AOB is loaded from AU, so we can safely transfer on T1.
|
||||
|
||||
// We need to take directly from first level muxes that are updated and T1
|
||||
|
||||
wire au2Aob = Nanod.au2Aob | (Nanod.au2Db & Nanod.db2Aob);
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
// UNIQUE IF !
|
||||
|
||||
if( enT1 & au2Aob) // From AU we do can on T1
|
||||
aob <= auReg;
|
||||
else if( enT2) begin
|
||||
if( Nanod.db2Aob)
|
||||
aob <= { preDbh, ~dblIdle ? preDbl : preDbd};
|
||||
else if( Nanod.ab2Aob)
|
||||
aob <= { preAbh, ~ablIdle ? preAbl : preAbd};
|
||||
end
|
||||
end
|
||||
|
||||
assign eab = aob[23:1];
|
||||
assign aob0 = aob[0];
|
||||
|
||||
// AU
|
||||
logic [31:0] auInpMux;
|
||||
|
||||
// `ifdef ALW_COMB_BUG
|
||||
// Old Modelsim bug. Doesn't update ouput always. Need excplicit sensitivity list !?
|
||||
// always @( Nanod.auCntrl) begin
|
||||
|
||||
always_comb begin
|
||||
unique case( Nanod.auCntrl)
|
||||
3'b000: auInpMux = 0;
|
||||
3'b001: auInpMux = byteNotSpAlign | Nanod.noSpAlign ? 1 : 2; // +1/+2
|
||||
3'b010: auInpMux = -4;
|
||||
3'b011: auInpMux = { Abh, Abl};
|
||||
3'b100: auInpMux = 2;
|
||||
3'b101: auInpMux = 4;
|
||||
3'b110: auInpMux = -2;
|
||||
3'b111: auInpMux = byteNotSpAlign | Nanod.noSpAlign ? -1 : -2; // -1/-2
|
||||
default: auInpMux = 'X;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Simulation problem
|
||||
// Sometimes (like in MULM1) DBH is not set. AU is used in these cases just as a 6 bits counter testing if bits 5-0 are zero.
|
||||
// But when adding something like 32'hXXXX0000, the simulator (incorrectly) will set *all the 32 bits* of the result as X.
|
||||
|
||||
// synthesis translate_off
|
||||
`define SIMULBUGX32 1
|
||||
wire [16:0] aulow = Dbl + auInpMux[15:0];
|
||||
wire [31:0] auResult = {Dbh + auInpMux[31:16] + aulow[16], aulow[15:0]};
|
||||
// synthesis translate_on
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( Clks.pwrUp)
|
||||
auReg <= '0;
|
||||
else if( enT3 & Nanod.auClkEn)
|
||||
`ifdef SIMULBUGX32
|
||||
auReg <= auResult;
|
||||
`else
|
||||
auReg <= { Dbh, Dbl } + auInpMux;
|
||||
`endif
|
||||
end
|
||||
|
||||
|
||||
// Main A/D registers
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( enT3) begin
|
||||
if( Nanod.dbl2rxl | Nanod.abl2rxl) begin
|
||||
if( ~rxIsAreg) begin
|
||||
if( Nanod.dbl2rxl) regs68L[ actualRx] <= Dbd;
|
||||
else if( abdIsByte) regs68L[ actualRx][7:0] <= Abd[7:0];
|
||||
else regs68L[ actualRx] <= Abd;
|
||||
end
|
||||
else
|
||||
regs68L[ actualRx] <= Nanod.dbl2rxl ? Dbl : Abl;
|
||||
end
|
||||
|
||||
if( Nanod.dbl2ryl | Nanod.abl2ryl) begin
|
||||
if( ~ryIsAreg) begin
|
||||
if( Nanod.dbl2ryl) regs68L[ actualRy] <= Dbd;
|
||||
else if( abdIsByte) regs68L[ actualRy][7:0] <= Abd[7:0];
|
||||
else regs68L[ actualRy] <= Abd;
|
||||
end
|
||||
else
|
||||
regs68L[ actualRy] <= Nanod.dbl2ryl ? Dbl : Abl;
|
||||
end
|
||||
|
||||
// High registers are easier. Both A & D on the same buses, and not byte ops.
|
||||
if( Nanod.dbh2rxh | Nanod.abh2rxh)
|
||||
regs68H[ actualRx] <= Nanod.dbh2rxh ? Dbh : Abh;
|
||||
if( Nanod.dbh2ryh | Nanod.abh2ryh)
|
||||
regs68H[ actualRy] <= Nanod.dbh2ryh ? Dbh : Abh;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
// PC & AT
|
||||
reg dbl2Pcl, dbh2Pch, abh2Pch, abl2Pcl;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( Clks.extReset) begin
|
||||
{ dbl2Pcl, dbh2Pch, abh2Pch, abl2Pcl } <= '0;
|
||||
|
||||
Pcl2Dbl <= 1'b0;
|
||||
Pch2Dbh <= 1'b0;
|
||||
Pcl2Abl <= 1'b0;
|
||||
Pch2Abh <= 1'b0;
|
||||
end
|
||||
else if( enT4) begin // Must latch on T4 !
|
||||
dbl2Pcl <= Nanod.dbl2reg & Nanod.pcldbl;
|
||||
dbh2Pch <= Nanod.dbh2reg & Nanod.pchdbh;
|
||||
abh2Pch <= Nanod.abh2reg & Nanod.pchabh;
|
||||
abl2Pcl <= Nanod.abl2reg & Nanod.pclabl;
|
||||
|
||||
Pcl2Dbl <= Nanod.reg2dbl & Nanod.pcldbl;
|
||||
Pch2Dbh <= Nanod.reg2dbh & Nanod.pchdbh;
|
||||
Pcl2Abl <= Nanod.reg2abl & Nanod.pclabl;
|
||||
Pch2Abh <= Nanod.reg2abh & Nanod.pchabh;
|
||||
end
|
||||
|
||||
// Unique IF !!!
|
||||
if( enT1 & Nanod.au2Pc)
|
||||
PcL <= auReg[15:0];
|
||||
else if( enT3) begin
|
||||
if( dbl2Pcl)
|
||||
PcL <= Dbl;
|
||||
else if( abl2Pcl)
|
||||
PcL <= Abl;
|
||||
end
|
||||
|
||||
// Unique IF !!!
|
||||
if( enT1 & Nanod.au2Pc)
|
||||
PcH <= auReg[31:16];
|
||||
else if( enT3) begin
|
||||
if( dbh2Pch)
|
||||
PcH <= Dbh;
|
||||
else if( abh2Pch)
|
||||
PcH <= Abh;
|
||||
end
|
||||
|
||||
// Unique IF !!!
|
||||
if( enT3) begin
|
||||
if( Nanod.dbl2Atl)
|
||||
Atl <= Dbl;
|
||||
else if( Nanod.abl2Atl)
|
||||
Atl <= Abl;
|
||||
end
|
||||
|
||||
// Unique IF !!!
|
||||
if( enT3) begin
|
||||
if( Nanod.abh2Ath)
|
||||
Ath <= Abh;
|
||||
else if( Nanod.dbh2Ath)
|
||||
Ath <= Dbh;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
// Movem reg mask priority encoder
|
||||
|
||||
wire rmIdle;
|
||||
logic [3:0] prHbit;
|
||||
logic [15:0] prenLatch;
|
||||
|
||||
// Invert reg order for predecrement mode
|
||||
assign prenEmpty = (~| prenLatch);
|
||||
pren rmPren( .mask( prenLatch), .hbit (prHbit));
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
// Cheating: PREN always loaded from DBIN
|
||||
// Must be on T1 to branch earlier if reg mask is empty!
|
||||
if( enT1 & Nanod.abl2Pren)
|
||||
prenLatch <= dbin;
|
||||
else if( enT3 & Nanod.updPren) begin
|
||||
prenLatch [prHbit] <= 1'b0;
|
||||
movemRx <= Irdecod.movemPreDecr ? ~prHbit : prHbit;
|
||||
end
|
||||
end
|
||||
|
||||
// DCR
|
||||
wire [15:0] dcrCode;
|
||||
|
||||
wire [3:0] dcrInput = abdIsByte ? { 1'b0, Abd[ 2:0]} : Abd[ 3:0];
|
||||
onehotEncoder4 dcrDecoder( .bin( dcrInput), .bitMap( dcrCode));
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( Clks.pwrUp)
|
||||
dcr4 <= '0;
|
||||
else if( enT3 & Nanod.abd2Dcr) begin
|
||||
dcrOutput <= dcrCode;
|
||||
dcr4 <= Abd[4];
|
||||
end
|
||||
end
|
||||
|
||||
// ALUB
|
||||
reg [15:0] alub;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( enT3) begin
|
||||
// UNIQUE IF !!
|
||||
if( Nanod.dbd2Alub)
|
||||
alub <= Dbd;
|
||||
else if( Nanod.abd2Alub)
|
||||
alub <= Abd; // abdIsByte affects this !!??
|
||||
end
|
||||
end
|
||||
|
||||
wire alueClkEn = enT3 & Nanod.dbd2Alue;
|
||||
|
||||
// DOB/DBIN/IRC
|
||||
|
||||
logic [15:0] dobInput;
|
||||
wire dobIdle = (~| Nanod.dobCtrl);
|
||||
|
||||
always_comb begin
|
||||
unique case (Nanod.dobCtrl)
|
||||
NANO_DOB_ADB: dobInput = Abd;
|
||||
NANO_DOB_DBD: dobInput = Dbd;
|
||||
NANO_DOB_ALU: dobInput = aluOut;
|
||||
default: dobInput = 'X;
|
||||
endcase
|
||||
end
|
||||
|
||||
dataIo dataIo( .Clks, .enT1, .enT2, .enT3, .enT4, .Nanod, .Irdecod,
|
||||
.iEdb, .dobIdle, .dobInput, .aob0,
|
||||
.Irc, .dbin, .oEdb);
|
||||
|
||||
fx68kAlu alu(
|
||||
.clk( Clks.clk), .pwrUp( Clks.pwrUp), .enT1, .enT3, .enT4,
|
||||
.ird( Ird),
|
||||
.aluColumn( Nanod.aluColumn), .aluAddrCtrl( Nanod.aluActrl),
|
||||
.init( Nanod.aluInit), .finish( Nanod.aluFinish), .aluIsByte( Irdecod.isByte),
|
||||
.ftu2Ccr( Nanod.ftu2Ccr),
|
||||
.alub, .ftu, .alueClkEn, .alue,
|
||||
.aluDataCtrl( Nanod.aluDctrl), .iDataBus( Dbd), .iAddrBus(Abd),
|
||||
.ze, .aluOut, .ccr);
|
||||
|
||||
endmodule
|
||||
File diff suppressed because it is too large
Load Diff
@@ -72,3 +72,16 @@ set_multicycle_path -setup -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/micr
|
||||
set_multicycle_path -hold -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/nanoAddr_reg*/D] 1
|
||||
set_multicycle_path -hold -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/microAddr_reg*/D] 1
|
||||
|
||||
|
||||
The update of the CCR flags is also time critical. Some compilers might benefit with the following constraints, but this wasn't fully verified yet:
|
||||
|
||||
|
||||
# Altera/Intel
|
||||
# set_multicycle_path -start -setup -from [fx68k:fx68k|nanoLatch[*]]
|
||||
# -to [get_keepers fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|pswCcr[*]] 2
|
||||
# set_multicycle_path -start -setup -from [fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|oper[*]]
|
||||
# -to [get_keepers fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|pswCcr[*]] 2
|
||||
# set_multicycle_path -start -hold -from [fx68k:fx68k|nanoLatch[*]]
|
||||
# -to [get_keepers fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|pswCcr[*]] 1
|
||||
# set_multicycle_path -start -hold -from [fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|oper[*]]
|
||||
# -to [get_keepers fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|pswCcr[*]] 1
|
||||
|
||||
39
common/CPU/68000/FX68k/fx68k.vhd
Normal file
39
common/CPU/68000/FX68k/fx68k.vhd
Normal file
@@ -0,0 +1,39 @@
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
|
||||
package fx68k is
|
||||
COMPONENT fx68k
|
||||
PORT
|
||||
(
|
||||
clk : in std_logic;
|
||||
extReset : in std_logic; -- External sync reset on emulated system
|
||||
pwrUp : in std_logic; -- Asserted together with reset on emulated system coldstart
|
||||
enPhi1 : in std_logic;
|
||||
enPhi2 : in std_logic; -- Clock enables. Next cycle is PHI1 or PHI2
|
||||
|
||||
eRWn : out std_logic;
|
||||
ASn : out std_logic;
|
||||
LDSn : out std_logic;
|
||||
UDSn : out std_logic;
|
||||
E : out std_logic;
|
||||
VMAn : out std_logic;
|
||||
FC0 : out std_logic;
|
||||
FC1 : out std_logic;
|
||||
FC2 : out std_logic;
|
||||
BGn : out std_logic;
|
||||
oRESETn : out std_logic;
|
||||
oHALTEDn : out std_logic;
|
||||
DTACKn : in std_logic;
|
||||
VPAn : in std_logic;
|
||||
BERRn : in std_logic;
|
||||
BRn : in std_logic;
|
||||
BGACKn : in std_logic;
|
||||
IPL0n : in std_logic;
|
||||
IPL1n : in std_logic;
|
||||
IPL2n : in std_logic;
|
||||
iEdb : in std_logic_vector(15 downto 0);
|
||||
oEdb : out std_logic_vector(15 downto 0);
|
||||
eab : out std_logic_vector(23 downto 1)
|
||||
);
|
||||
END COMPONENT;
|
||||
end package;
|
||||
@@ -96,31 +96,15 @@ module fx68kAlu ( input clk, pwrUp, enT1, enT3, enT4,
|
||||
wire [15:0] cRow;
|
||||
wire cIsArX;
|
||||
wire cNoCcrEn;
|
||||
rowDecoder rowDecoder(
|
||||
.ird ( ird),
|
||||
.row ( cRow),
|
||||
.noCcrEn ( cNoCcrEn),
|
||||
.isArX ( cIsArX)
|
||||
);
|
||||
rowDecoder rowDecoder( .ird( ird), .row( cRow), .noCcrEn( cNoCcrEn), .isArX( cIsArX));
|
||||
|
||||
// Get Operation & CCR Mask from row/col
|
||||
// Registering them on T4 increase performance. But slowest part seems to be corf !
|
||||
wire [4:0] cMask;
|
||||
wire [4:0] aluOp;
|
||||
|
||||
aluGetOp aluGetOp(
|
||||
.row ( row),
|
||||
.col ( aluColumn),
|
||||
.isCorf ( isCorf),
|
||||
.aluOp ( aluOp)
|
||||
);
|
||||
|
||||
ccrTable ccrTable(
|
||||
.col ( aluColumn),
|
||||
.row ( row),
|
||||
.finish ( finish),
|
||||
.ccrMask ( cMask)
|
||||
);
|
||||
aluGetOp aluGetOp( .row, .col( aluColumn), .isCorf, .aluOp);
|
||||
ccrTable ccrTable( .col( aluColumn), .row( row), .finish, .ccrMask( cMask));
|
||||
|
||||
// Inefficient, uCode could help !
|
||||
wire shftIsMul = row[7];
|
||||
@@ -177,26 +161,16 @@ module fx68kAlu ( input clk, pwrUp, enT1, enT3, enT4,
|
||||
// Can't be registered because uses bus operands that aren't available early !
|
||||
wire shftMsb = isLong ? alue[15] : (isByte ? aOperand[7] : aOperand[15]);
|
||||
|
||||
aluShifter shifter(
|
||||
.data ( { alue, aOperand}),
|
||||
.swapWords ( shftIsMul | shftIsDiv),
|
||||
.cin ( shftCin),
|
||||
.dir ( shftRight),
|
||||
.isByte ( isByte),
|
||||
.isLong ( isLong),
|
||||
.result ( shftResult)
|
||||
);
|
||||
aluShifter shifter( .data( { alue, aOperand}),
|
||||
.swapWords( shftIsMul | shftIsDiv),
|
||||
.cin( shftCin), .dir( shftRight), .isByte( isByte), .isLong( isLong),
|
||||
.result( shftResult));
|
||||
|
||||
wire [7:0] bcdResult;
|
||||
wire bcdC, bcdV;
|
||||
aluCorf aluCorf(
|
||||
.binResult ( aluLatch[7:0]),
|
||||
.hCarry ( coreH),
|
||||
.bAdd ( (oper != OP_SBCD) ),
|
||||
.cin ( pswCcr[ XF]),
|
||||
.bcdResult ( bcdResult),
|
||||
.dC ( bcdC),
|
||||
.ov ( bcdV));
|
||||
aluCorf aluCorf( .binResult( aluLatch[7:0]), .hCarry( coreH),
|
||||
.bAdd( (oper != OP_SBCD) ), .cin( pswCcr[ XF]),
|
||||
.bcdResult( bcdResult), .dC( bcdC), .ov( bcdV));
|
||||
|
||||
// BCD adjust is among the slowest processing on ALU !
|
||||
// Precompute and register BCD result on T1
|
||||
@@ -332,7 +306,7 @@ module fx68kAlu ( input clk, pwrUp, enT1, enT3, enT4,
|
||||
|
||||
ccrTemp[XF] = pswCcr[XF]; ccrTemp[CF] = 0; ccrTemp[VF] = 0;
|
||||
|
||||
// Not on all operators !!!
|
||||
// Not on all operators
|
||||
ccrTemp[ ZF] = isByte ? ~(| result[7:0]) : ~(| result);
|
||||
ccrTemp[ NF] = isByte ? result[7] : result[15];
|
||||
|
||||
@@ -341,7 +315,8 @@ module fx68kAlu ( input clk, pwrUp, enT1, enT3, enT4,
|
||||
OP_EXT:
|
||||
// Division overflow.
|
||||
if( aluColumn == 5) begin
|
||||
ccrTemp[VF] = 1'b1; ccrTemp[NF] = 1'b1;
|
||||
ccrTemp[VF] = 1'b1;
|
||||
ccrTemp[NF] = 1'b1; ccrTemp[ ZF] = 1'b0;
|
||||
end
|
||||
|
||||
OP_SUB0, // used by NOT
|
||||
@@ -438,7 +413,8 @@ module fx68kAlu ( input clk, pwrUp, enT1, enT3, enT4,
|
||||
logic [4:0] ccrMasked;
|
||||
always_comb begin
|
||||
ccrMasked = (ccrTemp & ccrMask) | (pswCcr & ~ccrMask);
|
||||
if( finish | isCorf | isArX)
|
||||
// if( finish | isCorf | isArX) // No need to check specicially for isCorf as they always have the "finish" flag anyway
|
||||
if( finish | isArX)
|
||||
ccrMasked[ ZF] = ccrTemp[ ZF] & pswCcr[ ZF];
|
||||
end
|
||||
|
||||
@@ -476,4 +452,388 @@ module fx68kAlu ( input clk, pwrUp, enT1, enT3, enT4,
|
||||
|
||||
endmodule
|
||||
|
||||
// add bcd correction factor
|
||||
// It would be more efficient to merge add/sub with main ALU !!!
|
||||
module aluCorf( input [7:0] binResult, input bAdd, input cin, input hCarry,
|
||||
output [7:0] bcdResult, output dC, output logic ov);
|
||||
|
||||
reg [8:0] htemp;
|
||||
reg [4:0] hNib;
|
||||
|
||||
wire lowC = hCarry | (bAdd ? gt9( binResult[ 3:0]) : 1'b0);
|
||||
wire highC = cin | (bAdd ? (gt9( htemp[7:4]) | htemp[8]) : 1'b0);
|
||||
|
||||
always_comb begin
|
||||
if( bAdd) begin
|
||||
htemp = { 1'b0, binResult} + (lowC ? 4'h6 : 4'h0);
|
||||
hNib = htemp[8:4] + (highC ? 4'h6 : 4'h0);
|
||||
ov = hNib[3] & ~binResult[7];
|
||||
end
|
||||
else begin
|
||||
htemp = { 1'b0, binResult} - (lowC ? 4'h6 : 4'h0);
|
||||
hNib = htemp[8:4] - (highC ? 4'h6 : 4'h0);
|
||||
ov = ~hNib[3] & binResult[7];
|
||||
end
|
||||
end
|
||||
|
||||
assign bcdResult = { hNib[ 3:0], htemp[3:0]};
|
||||
assign dC = hNib[4] | cin;
|
||||
|
||||
// Nibble > 9
|
||||
function gt9 (input [3:0] nib);
|
||||
begin
|
||||
gt9 = nib[3] & (nib[2] | nib[1]);
|
||||
end
|
||||
endfunction
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module aluShifter( input [31:0] data,
|
||||
input isByte, input isLong, swapWords,
|
||||
input dir, input cin,
|
||||
output logic [31:0] result);
|
||||
// output reg cout
|
||||
|
||||
logic [31:0] tdata;
|
||||
|
||||
// size mux, put cin in position if dir == right
|
||||
always_comb begin
|
||||
tdata = data;
|
||||
if( isByte & dir)
|
||||
tdata[8] = cin;
|
||||
else if( !isLong & dir)
|
||||
tdata[16] = cin;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
// Reverse alu/alue position for MUL & DIV
|
||||
// Result reversed again
|
||||
if( swapWords & dir)
|
||||
result = { tdata[0], tdata[31:17], cin, tdata[15:1]};
|
||||
else if( swapWords)
|
||||
result = { tdata[30:16], cin, tdata[14:0], tdata[31]};
|
||||
|
||||
else if( dir)
|
||||
result = { cin, tdata[31:1]};
|
||||
else
|
||||
result = { tdata[30:0], cin};
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
// Get current OP from row & col
|
||||
module aluGetOp( input [15:0] row, input [2:0] col, input isCorf,
|
||||
output logic [4:0] aluOp);
|
||||
|
||||
always_comb begin
|
||||
aluOp = 'X;
|
||||
unique case( col)
|
||||
1: aluOp = OP_AND;
|
||||
5: aluOp = OP_EXT;
|
||||
|
||||
default:
|
||||
unique case( 1'b1)
|
||||
row[1]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUB;
|
||||
3: aluOp = OP_SUBC;
|
||||
4,6: aluOp = OP_SLAA;
|
||||
endcase
|
||||
|
||||
row[2]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_ADD;
|
||||
3: aluOp = OP_ADDC;
|
||||
4: aluOp = OP_ASR;
|
||||
endcase
|
||||
|
||||
row[3]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_ADDX;
|
||||
3: aluOp = isCorf ? OP_ABCD : OP_ADD;
|
||||
4: aluOp = OP_ASL;
|
||||
endcase
|
||||
|
||||
row[4]:
|
||||
aluOp = ( col == 4) ? OP_LSL : OP_AND;
|
||||
|
||||
row[5],
|
||||
row[6]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUB;
|
||||
3: aluOp = OP_SUBC;
|
||||
4: aluOp = OP_LSR;
|
||||
endcase
|
||||
|
||||
row[7]: // MUL
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUB;
|
||||
3: aluOp = OP_ADD;
|
||||
4: aluOp = OP_ROXR;
|
||||
endcase
|
||||
|
||||
row[8]:
|
||||
// OP_AND For EXT.L
|
||||
// But would be more efficient to change ucode and use column 1 instead of col3 at ublock extr1!
|
||||
unique case( col)
|
||||
2: aluOp = OP_EXT;
|
||||
3: aluOp = OP_AND;
|
||||
4: aluOp = OP_ROXR;
|
||||
endcase
|
||||
|
||||
row[9]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUBX;
|
||||
3: aluOp = OP_SBCD;
|
||||
4: aluOp = OP_ROL;
|
||||
endcase
|
||||
|
||||
row[10]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUBX;
|
||||
3: aluOp = OP_SUBC;
|
||||
4: aluOp = OP_ROR;
|
||||
endcase
|
||||
|
||||
row[11]:
|
||||
unique case( col)
|
||||
2: aluOp = OP_SUB0;
|
||||
3: aluOp = OP_SUB0;
|
||||
4: aluOp = OP_ROXL;
|
||||
endcase
|
||||
|
||||
row[12]: aluOp = OP_ADDX;
|
||||
row[13]: aluOp = OP_EOR;
|
||||
row[14]: aluOp = (col == 4) ? OP_EOR : OP_OR;
|
||||
row[15]: aluOp = (col == 3) ? OP_ADD : OP_OR; // OP_ADD used by DBcc
|
||||
|
||||
endcase
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
||||
// Decodes IRD into ALU row (1-15)
|
||||
// Slow, but no need to optimize for speed since IRD is latched at least two CPU cycles before it is used
|
||||
// We also register the result after combining with column from nanocode
|
||||
//
|
||||
// Many opcodes are not decoded because they either don't do any ALU op,
|
||||
// or use only columns 1 and 5 that are the same for all rows.
|
||||
|
||||
module rowDecoder( input [15:0] ird,
|
||||
output logic [15:0] row, output noCcrEn, output logic isArX);
|
||||
|
||||
|
||||
// Addr or data register direct
|
||||
wire eaRdir = (ird[ 5:4] == 2'b00);
|
||||
// Addr register direct
|
||||
wire eaAdir = (ird[ 5:3] == 3'b001);
|
||||
wire size11 = ird[7] & ird[6];
|
||||
|
||||
always_comb begin
|
||||
case( ird[15:12])
|
||||
'h4,
|
||||
'h9,
|
||||
'hd:
|
||||
isArX = row[10] | row[12];
|
||||
default:
|
||||
isArX = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
unique case( ird[15:12])
|
||||
|
||||
'h4: begin
|
||||
if( ird[8])
|
||||
row = `ALU_ROW_06; // chk (or lea)
|
||||
else case( ird[11:9])
|
||||
'b000: row = `ALU_ROW_10; // negx
|
||||
'b001: row = `ALU_ROW_04; // clr
|
||||
'b010: row = `ALU_ROW_05; // neg
|
||||
'b011: row = `ALU_ROW_11; // not
|
||||
'b100: row = (ird[7]) ? `ALU_ROW_08 : `ALU_ROW_09; // nbcd/swap/ext(or pea)
|
||||
'b101: row = `ALU_ROW_15; // tst & tas
|
||||
default: row = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
'h0: begin
|
||||
if( ird[8]) // dynamic bit
|
||||
row = ird[7] ? `ALU_ROW_14 : `ALU_ROW_13;
|
||||
else case( ird[ 11:9])
|
||||
'b000: row = `ALU_ROW_14; // ori
|
||||
'b001: row = `ALU_ROW_04; // andi
|
||||
'b010: row = `ALU_ROW_05; // subi
|
||||
'b011: row = `ALU_ROW_02; // addi
|
||||
'b100: row = ird[7] ? `ALU_ROW_14 : `ALU_ROW_13; // static bit
|
||||
'b101: row = `ALU_ROW_13; // eori
|
||||
'b110: row = `ALU_ROW_06; // cmpi
|
||||
default: row = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
// MOVE
|
||||
// move.b originally also rows 5 & 15. Only because IRD bit 14 is not decoded.
|
||||
// It's the same for move the operations performed by MOVE.B
|
||||
|
||||
'h1,'h2,'h3: row = `ALU_ROW_02;
|
||||
|
||||
'h5:
|
||||
if( size11)
|
||||
row = `ALU_ROW_15; // As originally and easier to decode
|
||||
else
|
||||
row = ird[8] ? `ALU_ROW_05 : `ALU_ROW_02; // addq/subq
|
||||
'h6: row = 0; //bcc/bra/bsr
|
||||
'h7: row = `ALU_ROW_02; // moveq
|
||||
'h8:
|
||||
if( size11) // div
|
||||
row = `ALU_ROW_01;
|
||||
else if( ird[8] & eaRdir) // sbcd
|
||||
row = `ALU_ROW_09;
|
||||
else
|
||||
row = `ALU_ROW_14; // or
|
||||
'h9:
|
||||
if( ird[8] & ~size11 & eaRdir)
|
||||
row = `ALU_ROW_10; // subx
|
||||
else
|
||||
row = `ALU_ROW_05; // sub/suba
|
||||
'hb:
|
||||
if( ird[8] & ~size11 & ~eaAdir)
|
||||
row = `ALU_ROW_13; // eor
|
||||
else
|
||||
row = `ALU_ROW_06; // cmp/cmpa/cmpm
|
||||
'hc:
|
||||
if( size11)
|
||||
row = `ALU_ROW_07; // mul
|
||||
else if( ird[8] & eaRdir) // abcd
|
||||
row = `ALU_ROW_03;
|
||||
else
|
||||
row = `ALU_ROW_04; // and
|
||||
'hd:
|
||||
if( ird[8] & ~size11 & eaRdir)
|
||||
row = `ALU_ROW_12; // addx
|
||||
else
|
||||
row = `ALU_ROW_02; // add/adda
|
||||
'he:
|
||||
begin
|
||||
reg [1:0] stype;
|
||||
|
||||
if( size11) // memory shift/rotate
|
||||
stype = ird[ 10:9];
|
||||
else // register shift/rotate
|
||||
stype = ird[ 4:3];
|
||||
|
||||
case( {stype, ird[8]})
|
||||
0: row = `ALU_ROW_02; // ASR
|
||||
1: row = `ALU_ROW_03; // ASL
|
||||
2: row = `ALU_ROW_05; // LSR
|
||||
3: row = `ALU_ROW_04; // LSL
|
||||
4: row = `ALU_ROW_08; // ROXR
|
||||
5: row = `ALU_ROW_11; // ROXL
|
||||
6: row = `ALU_ROW_10; // ROR
|
||||
7: row = `ALU_ROW_09; // ROL
|
||||
endcase
|
||||
end
|
||||
|
||||
default: row = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Decode opcodes that don't affect flags
|
||||
// ADDA/SUBA ADDQ/SUBQ MOVEA
|
||||
|
||||
assign noCcrEn =
|
||||
// ADDA/SUBA
|
||||
( ird[15] & ~ird[13] & ird[12] & size11) |
|
||||
// ADDQ/SUBQ to An
|
||||
( (ird[15:12] == 4'h5) & eaAdir) |
|
||||
// MOVEA
|
||||
( (~ird[15] & ~ird[14] & ird[13]) & ird[8:6] == 3'b001);
|
||||
|
||||
endmodule
|
||||
|
||||
// Row/col CCR update table
|
||||
module ccrTable(
|
||||
input [2:0] col, input [15:0] row, input finish,
|
||||
output logic [MASK_NBITS-1:0] ccrMask);
|
||||
|
||||
localparam
|
||||
KNZ00 = 5'b01111, // ok coz operators clear them
|
||||
KKZKK = 5'b00100,
|
||||
KNZKK = 5'b01100,
|
||||
KNZ10 = 5'b01111, // Used by OP_EXT on divison overflow
|
||||
KNZ0C = 5'b01111, // Used by DIV. V should be 0, but it is ok:
|
||||
// DIVU: ends with quotient - 0, so V & C always clear.
|
||||
// DIVS: ends with 1i (AND), again, V & C always clear.
|
||||
|
||||
KNZVC = 5'b01111,
|
||||
XNKVC = 5'b11011, // Used by BCD instructions. Don't modify Z at all at the binary operation. Only at the BCD correction cycle
|
||||
|
||||
CUPDALL = 5'b11111,
|
||||
CUNUSED = 5'bxxxxx;
|
||||
|
||||
|
||||
logic [MASK_NBITS-1:0] ccrMask1;
|
||||
|
||||
always_comb begin
|
||||
unique case( col)
|
||||
1: ccrMask = ccrMask1;
|
||||
|
||||
2,3:
|
||||
unique case( 1'b1)
|
||||
row[1]: ccrMask = KNZ0C; // DIV, used as 3n in col3
|
||||
|
||||
row[3], // ABCD
|
||||
row[9]: // SBCD/NBCD
|
||||
ccrMask = (col == 2) ? XNKVC : CUPDALL;
|
||||
|
||||
row[2],
|
||||
row[5],
|
||||
row[10], // SUBX/NEGX
|
||||
row[12]: ccrMask = CUPDALL; // ADDX
|
||||
|
||||
row[6], // CMP
|
||||
row[7], // MUL
|
||||
row[11]: ccrMask = KNZVC; // NOT
|
||||
row[4],
|
||||
row[8], // Not used in col 3
|
||||
row[13],
|
||||
row[14]: ccrMask = KNZ00;
|
||||
row[15]: ccrMask = 5'b0; // TAS/Scc, not used in col 3
|
||||
// default: ccrMask = CUNUSED;
|
||||
endcase
|
||||
|
||||
4:
|
||||
unique case( row)
|
||||
// 1: DIV, only n (4n & 6n)
|
||||
// 14: BCLR 4n
|
||||
// 6,12,13,15 // not used
|
||||
`ALU_ROW_02,
|
||||
`ALU_ROW_03, // ASL (originally ANZVA)
|
||||
`ALU_ROW_04,
|
||||
`ALU_ROW_05: ccrMask = CUPDALL; // Shifts (originally ANZ0A)
|
||||
|
||||
`ALU_ROW_07: ccrMask = KNZ00; // MUL (originally KNZ0A)
|
||||
`ALU_ROW_09,
|
||||
`ALU_ROW_10: ccrMask = KNZ00; // RO[lr] (originally KNZ0A)
|
||||
`ALU_ROW_08, // ROXR (originally ANZ0A)
|
||||
`ALU_ROW_11: ccrMask = CUPDALL; // ROXL (originally ANZ0A)
|
||||
default: ccrMask = CUNUSED;
|
||||
endcase
|
||||
|
||||
5: ccrMask = row[1] ? KNZ10 : 5'b0;
|
||||
default: ccrMask = CUNUSED;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Column 1 (AND)
|
||||
always_comb begin
|
||||
if( finish)
|
||||
ccrMask1 = row[7] ? KNZ00 : KNZKK;
|
||||
else
|
||||
ccrMask1 = row[13] | row[14] ? KKZKK : KNZ00;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
|
||||
//
|
||||
// For compilation test only
|
||||
//
|
||||
|
||||
module fx68k_tb( input clk32,
|
||||
input extReset,
|
||||
// input pwrUp,
|
||||
|
||||
input DTACKn, input VPAn,
|
||||
input BERRn,
|
||||
input BRn, BGACKn,
|
||||
input IPL0n, input IPL1n, input IPL2n,
|
||||
input [15:0] iEdb,
|
||||
|
||||
output [15:0] oEdb,
|
||||
output eRWn, output ASn, output LDSn, output UDSn,
|
||||
output logic E, output VMAn,
|
||||
output FC0, output FC1, output FC2,
|
||||
output BGn,
|
||||
output oRESETn, output oHALTEDn,
|
||||
output [23:1] eab
|
||||
);
|
||||
|
||||
// Clock must be at least twice the desired frequency. A 32 MHz clock means a maximum 16 MHz effective frequency.
|
||||
// In this example we divide the clock by 4. Resulting on an effective processor running at 8 MHz.
|
||||
|
||||
reg [1:0] clkDivisor = '0;
|
||||
always @( posedge clk32) begin
|
||||
clkDivisor <= clkDivisor + 1'b1;
|
||||
end
|
||||
|
||||
/*
|
||||
These two signals must be a single cycle pulse. They don't need to be registered.
|
||||
Same signal can't be asserted twice in a row. Other than that there are no restrictions.
|
||||
There can be any number of cycles, or none, even variable non constant cycles, between each pulse.
|
||||
*/
|
||||
|
||||
wire enPhi1 = (clkDivisor == 2'b11);
|
||||
wire enPhi2 = (clkDivisor == 2'b01);
|
||||
|
||||
|
||||
fx68k fx68k( .clk( clk32),
|
||||
.extReset, .pwrUp( extReset), .enPhi1, .enPhi2,
|
||||
|
||||
.DTACKn, .VPAn, .BERRn, .BRn, .BGACKn,
|
||||
.IPL0n, .IPL1n, .IPL2n,
|
||||
.iEdb,
|
||||
|
||||
.oEdb,
|
||||
.eRWn, .ASn, .LDSn, .UDSn,
|
||||
.E, .VMAn,
|
||||
.FC0, .FC1, .FC2,
|
||||
.BGn,
|
||||
.oRESETn, .oHALTEDn, .eab);
|
||||
|
||||
endmodule
|
||||
@@ -1,208 +0,0 @@
|
||||
//
|
||||
// IRD execution decoder. Complements nano code decoder
|
||||
//
|
||||
// IRD updated on T1, while ncode still executing. To avoid using the next IRD,
|
||||
// decoded signals must be registered on T3, or T4 before using them.
|
||||
//
|
||||
module irdDecode( input [15:0] ird,
|
||||
output s_irdecod Irdecod);
|
||||
|
||||
wire [3:0] line = ird[15:12];
|
||||
logic [15:0] lineOnehot;
|
||||
|
||||
// This can be registered and pipelined from the IR decoder !
|
||||
onehotEncoder4 irdLines( line, lineOnehot);
|
||||
|
||||
wire isRegShift = (lineOnehot['he]) & (ird[7:6] != 2'b11);
|
||||
wire isDynShift = isRegShift & ird[5];
|
||||
|
||||
assign Irdecod.isPcRel = (& ird[ 5:3]) & ~isDynShift & !ird[2] & ird[1];
|
||||
assign Irdecod.isTas = lineOnehot[4] & (ird[11:6] == 6'b101011);
|
||||
|
||||
assign Irdecod.rx = ird[11:9];
|
||||
assign Irdecod.ry = ird[ 2:0];
|
||||
|
||||
wire isPreDecr = (ird[ 5:3] == 3'b100);
|
||||
wire eaAreg = (ird[5:3] == 3'b001);
|
||||
|
||||
// rx is A or D
|
||||
// movem
|
||||
always_comb begin
|
||||
unique case( 1'b1)
|
||||
lineOnehot[1],
|
||||
lineOnehot[2],
|
||||
lineOnehot[3]:
|
||||
// MOVE: RX always Areg except if dest mode is Dn 000
|
||||
Irdecod.rxIsAreg = (| ird[8:6]);
|
||||
|
||||
lineOnehot[4]: Irdecod.rxIsAreg = (& ird[8:6]); // not CHK (LEA)
|
||||
|
||||
lineOnehot['h8]: Irdecod.rxIsAreg = eaAreg & ird[8] & ~ird[7]; // SBCD
|
||||
lineOnehot['hc]: Irdecod.rxIsAreg = eaAreg & ird[8] & ~ird[7]; // ABCD/EXG An,An
|
||||
|
||||
lineOnehot['h9],
|
||||
lineOnehot['hb],
|
||||
lineOnehot['hd]: Irdecod.rxIsAreg =
|
||||
(ird[7] & ird[6]) | // SUBA/CMPA/ADDA
|
||||
(eaAreg & ird[8] & (ird[7:6] != 2'b11)); // SUBX/CMPM/ADDX
|
||||
default:
|
||||
Irdecod.rxIsAreg = Irdecod.implicitSp;
|
||||
endcase
|
||||
end
|
||||
|
||||
// RX is movem
|
||||
always_comb begin
|
||||
Irdecod.rxIsMovem = lineOnehot[4] & ~ird[8] & ~Irdecod.implicitSp;
|
||||
end
|
||||
assign Irdecod.movemPreDecr = Irdecod.rxIsMovem & isPreDecr;
|
||||
|
||||
// RX is DT.
|
||||
// but SSP explicit or pc explicit has higher priority!
|
||||
// addq/subq (scc & dbcc also, but don't use rx)
|
||||
// Immediate including static bit
|
||||
assign Irdecod.rxIsDt = lineOnehot[5] | (lineOnehot[0] & ~ird[8]);
|
||||
|
||||
// RX is USP
|
||||
assign Irdecod.rxIsUsp = lineOnehot[4] & (ird[ 11:4] == 8'he6);
|
||||
|
||||
// RY is DT
|
||||
// rz or PC explicit has higher priority
|
||||
|
||||
wire eaImmOrAbs = (ird[5:3] == 3'b111) & ~ird[1];
|
||||
assign Irdecod.ryIsDt = eaImmOrAbs & ~isRegShift;
|
||||
|
||||
// RY is Address register
|
||||
always_comb begin
|
||||
logic eaIsAreg;
|
||||
|
||||
// On most cases RY is Areg expect if mode is 000 (DATA REG) or 111 (IMM, ABS,PC REL)
|
||||
eaIsAreg = (ird[5:3] != 3'b000) & (ird[5:3] != 3'b111);
|
||||
|
||||
unique case( 1'b1)
|
||||
// MOVE: RY always Areg expect if mode is 000 (DATA REG) or 111 (IMM, ABS,PC REL)
|
||||
// Most lines, including misc line 4, also.
|
||||
default: Irdecod.ryIsAreg = eaIsAreg;
|
||||
|
||||
lineOnehot[5]: // DBcc is an exception
|
||||
Irdecod.ryIsAreg = eaIsAreg & (ird[7:3] != 5'b11001);
|
||||
|
||||
lineOnehot[6],
|
||||
lineOnehot[7]: Irdecod.ryIsAreg = 1'b0;
|
||||
|
||||
lineOnehot['he]:
|
||||
Irdecod.ryIsAreg = ~isRegShift;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Byte sized instruction
|
||||
|
||||
// Original implementation sets this for some instructions that aren't really byte size
|
||||
// but doesn't matter because they don't have a byte transfer enabled at nanocode, such as MOVEQ
|
||||
|
||||
wire xIsScc = (ird[7:6] == 2'b11) & (ird[5:3] != 3'b001);
|
||||
wire xStaticMem = (ird[11:8] == 4'b1000) & (ird[5:4] == 2'b00); // Static bit to mem
|
||||
always_comb begin
|
||||
unique case( 1'b1)
|
||||
lineOnehot[0]:
|
||||
Irdecod.isByte =
|
||||
( ird[8] & (ird[5:4] != 2'b00) ) | // Dynamic bit to mem
|
||||
( (ird[11:8] == 4'b1000) & (ird[5:4] != 2'b00) ) | // Static bit to mem
|
||||
( (ird[8:7] == 2'b10) & (ird[5:3] == 3'b001) ) | // Movep from mem only! For byte mux
|
||||
( (ird[8:6] == 3'b000) & !xStaticMem ); // Immediate byte
|
||||
|
||||
lineOnehot[1]: Irdecod.isByte = 1'b1; // MOVE.B
|
||||
|
||||
|
||||
lineOnehot[4]: Irdecod.isByte = (ird[7:6] == 2'b00) | Irdecod.isTas;
|
||||
lineOnehot[5]: Irdecod.isByte = (ird[7:6] == 2'b00) | xIsScc;
|
||||
|
||||
lineOnehot[8],
|
||||
lineOnehot[9],
|
||||
lineOnehot['hb],
|
||||
lineOnehot['hc],
|
||||
lineOnehot['hd],
|
||||
lineOnehot['he]: Irdecod.isByte = (ird[7:6] == 2'b00);
|
||||
|
||||
default: Irdecod.isByte = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Need it for special byte size. Bus is byte, but whole register word is modified.
|
||||
assign Irdecod.isMovep = lineOnehot[0] & ird[8] & eaAreg;
|
||||
|
||||
|
||||
// rxIsSP implicit use of RX for actual SP transfer
|
||||
//
|
||||
// This logic is simple and will include some instructions that don't actually reference SP.
|
||||
// But doesn't matter as long as they don't perform any RX transfer.
|
||||
|
||||
always_comb begin
|
||||
unique case( 1'b1)
|
||||
lineOnehot[6]: Irdecod.implicitSp = (ird[11:8] == 4'b0001); // BSR
|
||||
lineOnehot[4]:
|
||||
// Misc like RTS, JSR, etc
|
||||
Irdecod.implicitSp = (ird[11:8] == 4'b1110) | (ird[11:6] == 6'b1000_01);
|
||||
default: Irdecod.implicitSp = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Modify CCR (and not SR)
|
||||
// Probably overkill !! Only needs to distinguish SR vs CCR
|
||||
// RTR, MOVE to CCR, xxxI to CCR
|
||||
assign Irdecod.toCcr = ( lineOnehot[4] & ((ird[11:0] == 12'he77) | (ird[11:6] == 6'b010011)) ) |
|
||||
( lineOnehot[0] & (ird[8:6] == 3'b000));
|
||||
|
||||
// FTU constants
|
||||
// This should not be latched on T3/T4. Latch on T2 or not at all. FTU needs it on next T3.
|
||||
// Note: Reset instruction gets constant from ALU not from FTU!
|
||||
logic [15:0] ftuConst;
|
||||
wire [3:0] zero28 = (ird[11:9] == 0) ? 4'h8 : { 1'b0, ird[11:9]}; // xltate 0,1-7 into 8,1-7
|
||||
|
||||
always_comb begin
|
||||
unique case( 1'b1)
|
||||
lineOnehot[6], // Bcc short
|
||||
lineOnehot[7]: ftuConst = { { 8{ ird[ 7]}}, ird[ 7:0] }; // MOVEQ
|
||||
|
||||
lineOnehot['h5], // addq/subq/static shift double check this
|
||||
lineOnehot['he]: ftuConst = { 12'b0, zero28};
|
||||
|
||||
// MULU/MULS DIVU/DIVS
|
||||
lineOnehot['h8],
|
||||
lineOnehot['hc]: ftuConst = 16'h0f;
|
||||
|
||||
lineOnehot[4]: ftuConst = 16'h80; // TAS
|
||||
|
||||
default: ftuConst = '0;
|
||||
endcase
|
||||
end
|
||||
assign Irdecod.ftuConst = ftuConst;
|
||||
|
||||
//
|
||||
// TRAP Vector # for group 2 exceptions
|
||||
//
|
||||
|
||||
always_comb begin
|
||||
if( lineOnehot[4]) begin
|
||||
case ( ird[6:5])
|
||||
2'b00,2'b01: Irdecod.macroTvn = 6; // CHK
|
||||
2'b11: Irdecod.macroTvn = 7; // TRAPV
|
||||
2'b10: Irdecod.macroTvn = {2'b10, ird[3:0]}; // TRAP
|
||||
endcase
|
||||
end
|
||||
else
|
||||
Irdecod.macroTvn = 5; // Division by zero
|
||||
end
|
||||
|
||||
|
||||
wire eaAdir = (ird[ 5:3] == 3'b001);
|
||||
wire size11 = ird[7] & ird[6];
|
||||
|
||||
// Opcodes variants that don't affect flags
|
||||
// ADDA/SUBA ADDQ/SUBQ MOVEA
|
||||
|
||||
assign Irdecod.inhibitCcr =
|
||||
( (lineOnehot[9] | lineOnehot['hd]) & size11) | // ADDA/SUBA
|
||||
( lineOnehot[5] & eaAdir) | // ADDQ/SUBQ to An (originally checks for line[4] as well !?)
|
||||
( (lineOnehot[2] | lineOnehot[3]) & ird[8:6] == 3'b001); // MOVEA
|
||||
|
||||
endmodule
|
||||
@@ -1,157 +0,0 @@
|
||||
// Translate uaddr to nanoaddr
|
||||
module microToNanoAddr(
|
||||
input [UADDR_WIDTH-1:0] uAddr,
|
||||
output [NADDR_WIDTH-1:0] orgAddr);
|
||||
|
||||
wire [UADDR_WIDTH-1:2] baseAddr = uAddr[UADDR_WIDTH-1:2];
|
||||
logic [NADDR_WIDTH-1:2] orgBase;
|
||||
assign orgAddr = { orgBase, uAddr[1:0]};
|
||||
|
||||
always @( baseAddr)
|
||||
begin
|
||||
// nano ROM (136 addresses)
|
||||
case( baseAddr)
|
||||
|
||||
'h00: orgBase = 7'h0 ;
|
||||
'h01: orgBase = 7'h1 ;
|
||||
'h02: orgBase = 7'h2 ;
|
||||
'h03: orgBase = 7'h2 ;
|
||||
'h08: orgBase = 7'h3 ;
|
||||
'h09: orgBase = 7'h4 ;
|
||||
'h0A: orgBase = 7'h5 ;
|
||||
'h0B: orgBase = 7'h5 ;
|
||||
'h10: orgBase = 7'h6 ;
|
||||
'h11: orgBase = 7'h7 ;
|
||||
'h12: orgBase = 7'h8 ;
|
||||
'h13: orgBase = 7'h8 ;
|
||||
'h18: orgBase = 7'h9 ;
|
||||
'h19: orgBase = 7'hA ;
|
||||
'h1A: orgBase = 7'hB ;
|
||||
'h1B: orgBase = 7'hB ;
|
||||
'h20: orgBase = 7'hC ;
|
||||
'h21: orgBase = 7'hD ;
|
||||
'h22: orgBase = 7'hE ;
|
||||
'h23: orgBase = 7'hD ;
|
||||
'h28: orgBase = 7'hF ;
|
||||
'h29: orgBase = 7'h10 ;
|
||||
'h2A: orgBase = 7'h11 ;
|
||||
'h2B: orgBase = 7'h10 ;
|
||||
'h30: orgBase = 7'h12 ;
|
||||
'h31: orgBase = 7'h13 ;
|
||||
'h32: orgBase = 7'h14 ;
|
||||
'h33: orgBase = 7'h14 ;
|
||||
'h38: orgBase = 7'h15 ;
|
||||
'h39: orgBase = 7'h16 ;
|
||||
'h3A: orgBase = 7'h17 ;
|
||||
'h3B: orgBase = 7'h17 ;
|
||||
'h40: orgBase = 7'h18 ;
|
||||
'h41: orgBase = 7'h18 ;
|
||||
'h42: orgBase = 7'h18 ;
|
||||
'h43: orgBase = 7'h18 ;
|
||||
'h44: orgBase = 7'h19 ;
|
||||
'h45: orgBase = 7'h19 ;
|
||||
'h46: orgBase = 7'h19 ;
|
||||
'h47: orgBase = 7'h19 ;
|
||||
'h48: orgBase = 7'h1A ;
|
||||
'h49: orgBase = 7'h1A ;
|
||||
'h4A: orgBase = 7'h1A ;
|
||||
'h4B: orgBase = 7'h1A ;
|
||||
'h4C: orgBase = 7'h1B ;
|
||||
'h4D: orgBase = 7'h1B ;
|
||||
'h4E: orgBase = 7'h1B ;
|
||||
'h4F: orgBase = 7'h1B ;
|
||||
'h54: orgBase = 7'h1C ;
|
||||
'h55: orgBase = 7'h1D ;
|
||||
'h56: orgBase = 7'h1E ;
|
||||
'h57: orgBase = 7'h1F ;
|
||||
'h5C: orgBase = 7'h20 ;
|
||||
'h5D: orgBase = 7'h21 ;
|
||||
'h5E: orgBase = 7'h22 ;
|
||||
'h5F: orgBase = 7'h23 ;
|
||||
'h70: orgBase = 7'h24 ;
|
||||
'h71: orgBase = 7'h24 ;
|
||||
'h72: orgBase = 7'h24 ;
|
||||
'h73: orgBase = 7'h24 ;
|
||||
'h74: orgBase = 7'h24 ;
|
||||
'h75: orgBase = 7'h24 ;
|
||||
'h76: orgBase = 7'h24 ;
|
||||
'h77: orgBase = 7'h24 ;
|
||||
'h78: orgBase = 7'h25 ;
|
||||
'h79: orgBase = 7'h25 ;
|
||||
'h7A: orgBase = 7'h25 ;
|
||||
'h7B: orgBase = 7'h25 ;
|
||||
'h7C: orgBase = 7'h25 ;
|
||||
'h7D: orgBase = 7'h25 ;
|
||||
'h7E: orgBase = 7'h25 ;
|
||||
'h7F: orgBase = 7'h25 ;
|
||||
'h84: orgBase = 7'h26 ;
|
||||
'h85: orgBase = 7'h27 ;
|
||||
'h86: orgBase = 7'h28 ;
|
||||
'h87: orgBase = 7'h29 ;
|
||||
'h8C: orgBase = 7'h2A ;
|
||||
'h8D: orgBase = 7'h2B ;
|
||||
'h8E: orgBase = 7'h2C ;
|
||||
'h8F: orgBase = 7'h2D ;
|
||||
'h94: orgBase = 7'h2E ;
|
||||
'h95: orgBase = 7'h2F ;
|
||||
'h96: orgBase = 7'h30 ;
|
||||
'h97: orgBase = 7'h31 ;
|
||||
'h9C: orgBase = 7'h32 ;
|
||||
'h9D: orgBase = 7'h33 ;
|
||||
'h9E: orgBase = 7'h34 ;
|
||||
'h9F: orgBase = 7'h35 ;
|
||||
'hA4: orgBase = 7'h36 ;
|
||||
'hA5: orgBase = 7'h36 ;
|
||||
'hA6: orgBase = 7'h37 ;
|
||||
'hA7: orgBase = 7'h37 ;
|
||||
'hAC: orgBase = 7'h38 ;
|
||||
'hAD: orgBase = 7'h38 ;
|
||||
'hAE: orgBase = 7'h39 ;
|
||||
'hAF: orgBase = 7'h39 ;
|
||||
'hB4: orgBase = 7'h3A ;
|
||||
'hB5: orgBase = 7'h3A ;
|
||||
'hB6: orgBase = 7'h3B ;
|
||||
'hB7: orgBase = 7'h3B ;
|
||||
'hBC: orgBase = 7'h3C ;
|
||||
'hBD: orgBase = 7'h3C ;
|
||||
'hBE: orgBase = 7'h3D ;
|
||||
'hBF: orgBase = 7'h3D ;
|
||||
'hC0: orgBase = 7'h3E ;
|
||||
'hC1: orgBase = 7'h3F ;
|
||||
'hC2: orgBase = 7'h40 ;
|
||||
'hC3: orgBase = 7'h41 ;
|
||||
'hC8: orgBase = 7'h42 ;
|
||||
'hC9: orgBase = 7'h43 ;
|
||||
'hCA: orgBase = 7'h44 ;
|
||||
'hCB: orgBase = 7'h45 ;
|
||||
'hD0: orgBase = 7'h46 ;
|
||||
'hD1: orgBase = 7'h47 ;
|
||||
'hD2: orgBase = 7'h48 ;
|
||||
'hD3: orgBase = 7'h49 ;
|
||||
'hD8: orgBase = 7'h4A ;
|
||||
'hD9: orgBase = 7'h4B ;
|
||||
'hDA: orgBase = 7'h4C ;
|
||||
'hDB: orgBase = 7'h4D ;
|
||||
'hE0: orgBase = 7'h4E ;
|
||||
'hE1: orgBase = 7'h4E ;
|
||||
'hE2: orgBase = 7'h4F ;
|
||||
'hE3: orgBase = 7'h4F ;
|
||||
'hE8: orgBase = 7'h50 ;
|
||||
'hE9: orgBase = 7'h50 ;
|
||||
'hEA: orgBase = 7'h51 ;
|
||||
'hEB: orgBase = 7'h51 ;
|
||||
'hF0: orgBase = 7'h52 ;
|
||||
'hF1: orgBase = 7'h52 ;
|
||||
'hF2: orgBase = 7'h52 ;
|
||||
'hF3: orgBase = 7'h52 ;
|
||||
'hF8: orgBase = 7'h53 ;
|
||||
'hF9: orgBase = 7'h53 ;
|
||||
'hFA: orgBase = 7'h53 ;
|
||||
'hFB: orgBase = 7'h53 ;
|
||||
|
||||
default:
|
||||
orgBase = 'X;
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,274 +0,0 @@
|
||||
// Nanorom (plus) decoder for die nanocode
|
||||
module nDecoder3( input s_clks Clks, input s_irdecod Irdecod, output s_nanod Nanod,
|
||||
input enT2, enT4,
|
||||
input [UROM_WIDTH-1:0] microLatch,
|
||||
input [NANO_WIDTH-1:0] nanoLatch);
|
||||
|
||||
localparam NANO_IR2IRD = 67;
|
||||
localparam NANO_TOIRC = 66;
|
||||
localparam NANO_ALU_COL = 63; // ALU operator column order is 63-64-65 !
|
||||
localparam NANO_ALU_FI = 61; // ALU finish-init 62-61
|
||||
localparam NANO_TODBIN = 60;
|
||||
localparam NANO_ALUE = 57; // 57-59 shared with DCR control
|
||||
localparam NANO_DCR = 57; // 57-59 shared with ALUE control
|
||||
localparam NANO_DOBCTRL_1 = 56; // Input to control and permwrite
|
||||
localparam NANO_LOWBYTE = 55; // Used by MOVEP
|
||||
localparam NANO_HIGHBYTE = 54;
|
||||
localparam NANO_DOBCTRL_0 = 53; // Input to control and permwrite
|
||||
localparam NANO_ALU_DCTRL = 51; // 52-51 databus input mux control
|
||||
localparam NANO_ALU_ACTRL = 50; // addrbus input mux control
|
||||
localparam NANO_DBD2ALUB = 49;
|
||||
localparam NANO_ABD2ALUB = 48;
|
||||
localparam NANO_DBIN2DBD = 47;
|
||||
localparam NANO_DBIN2ABD = 46;
|
||||
localparam NANO_ALU2ABD = 45;
|
||||
localparam NANO_ALU2DBD = 44;
|
||||
localparam NANO_RZ = 43;
|
||||
localparam NANO_BUSBYTE = 42; // If *both* this set and instruction is byte sized, then bus cycle is byte sized.
|
||||
localparam NANO_PCLABL = 41;
|
||||
localparam NANO_RXL_DBL = 40; // Switches RXL/RYL on DBL/ABL buses
|
||||
localparam NANO_PCLDBL = 39;
|
||||
localparam NANO_ABDHRECHARGE = 38;
|
||||
localparam NANO_REG2ABL = 37; // register to ABL
|
||||
localparam NANO_ABL2REG = 36; // ABL to register
|
||||
localparam NANO_ABLABD = 35;
|
||||
localparam NANO_DBLDBD = 34;
|
||||
localparam NANO_DBL2REG = 33; // DBL to register
|
||||
localparam NANO_REG2DBL = 32; // register to DBL
|
||||
localparam NANO_ATLCTRL = 29; // 31-29
|
||||
localparam NANO_FTUCONTROL = 25;
|
||||
localparam NANO_SSP = 24;
|
||||
localparam NANO_RXH_DBH = 22; // Switches RXH/RYH on DBH/ABH buses
|
||||
localparam NANO_AUOUT = 20; // 21-20
|
||||
localparam NANO_AUCLKEN = 19;
|
||||
localparam NANO_AUCTRL = 16; // 18-16
|
||||
localparam NANO_DBLDBH = 15;
|
||||
localparam NANO_ABLABH = 14;
|
||||
localparam NANO_EXT_ABH = 13;
|
||||
localparam NANO_EXT_DBH = 12;
|
||||
localparam NANO_ATHCTRL = 9; // 11-9
|
||||
localparam NANO_REG2ABH = 8; // register to ABH
|
||||
localparam NANO_ABH2REG = 7; // ABH to register
|
||||
localparam NANO_REG2DBH = 6; // register to DBH
|
||||
localparam NANO_DBH2REG = 5; // DBH to register
|
||||
localparam NANO_AOBCTRL = 3; // 4-3
|
||||
localparam NANO_PCH = 0; // 1-0 PchDbh PchAbh
|
||||
localparam NANO_NO_SP_ALGN = 0; // Same bits as above when both set
|
||||
|
||||
localparam NANO_FTU_UPDTPEND = 1; // Also loads FTU constant according to IRD !
|
||||
localparam NANO_FTU_INIT_ST = 15; // Set S, clear T (but not TPEND)
|
||||
localparam NANO_FTU_CLRTPEND = 14;
|
||||
localparam NANO_FTU_TVN = 13;
|
||||
localparam NANO_FTU_ABL2PREN = 12; // ABL => FTU & ABL => PREN. Both transfers enabled, but only one will be used depending on uroutine.
|
||||
localparam NANO_FTU_SSW = 11;
|
||||
localparam NANO_FTU_RSTPREN = 10;
|
||||
localparam NANO_FTU_IRD = 9;
|
||||
localparam NANO_FTU_2ABL = 8;
|
||||
localparam NANO_FTU_RDSR = 7;
|
||||
localparam NANO_FTU_INL = 6;
|
||||
localparam NANO_FTU_PSWI = 5; // Read Int Mask into FTU
|
||||
localparam NANO_FTU_DBL = 4;
|
||||
localparam NANO_FTU_2SR = 2;
|
||||
localparam NANO_FTU_CONST = 1;
|
||||
|
||||
reg [3:0] ftuCtrl;
|
||||
|
||||
logic [2:0] athCtrl, atlCtrl;
|
||||
assign athCtrl = nanoLatch[ NANO_ATHCTRL+2: NANO_ATHCTRL];
|
||||
assign atlCtrl = nanoLatch[ NANO_ATLCTRL+2: NANO_ATLCTRL];
|
||||
wire [1:0] aobCtrl = nanoLatch[ NANO_AOBCTRL+1:NANO_AOBCTRL];
|
||||
wire [1:0] dobCtrl = {nanoLatch[ NANO_DOBCTRL_1], nanoLatch[NANO_DOBCTRL_0]};
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( enT4) begin
|
||||
// Reverse order!
|
||||
ftuCtrl <= { nanoLatch[ NANO_FTUCONTROL+0], nanoLatch[ NANO_FTUCONTROL+1], nanoLatch[ NANO_FTUCONTROL+2], nanoLatch[ NANO_FTUCONTROL+3]} ;
|
||||
|
||||
Nanod.auClkEn <= !nanoLatch[ NANO_AUCLKEN];
|
||||
Nanod.auCntrl <= nanoLatch[ NANO_AUCTRL+2 : NANO_AUCTRL+0];
|
||||
Nanod.noSpAlign <= (nanoLatch[ NANO_NO_SP_ALGN + 1:NANO_NO_SP_ALGN] == 2'b11);
|
||||
Nanod.extDbh <= nanoLatch[ NANO_EXT_DBH];
|
||||
Nanod.extAbh <= nanoLatch[ NANO_EXT_ABH];
|
||||
Nanod.todbin <= nanoLatch[ NANO_TODBIN];
|
||||
Nanod.toIrc <= nanoLatch[ NANO_TOIRC];
|
||||
|
||||
// ablAbd is disabled on byte transfers (adbhCharge plus irdIsByte). Not sure the combination makes much sense.
|
||||
// It happens in a few cases but I don't see anything enabled on abL (or abH) section anyway.
|
||||
|
||||
Nanod.ablAbd <= nanoLatch[ NANO_ABLABD];
|
||||
Nanod.ablAbh <= nanoLatch[ NANO_ABLABH];
|
||||
Nanod.dblDbd <= nanoLatch[ NANO_DBLDBD];
|
||||
Nanod.dblDbh <= nanoLatch[ NANO_DBLDBH];
|
||||
|
||||
Nanod.dbl2Atl <= (atlCtrl == 3'b010);
|
||||
Nanod.atl2Dbl <= (atlCtrl == 3'b011);
|
||||
Nanod.abl2Atl <= (atlCtrl == 3'b100);
|
||||
Nanod.atl2Abl <= (atlCtrl == 3'b101);
|
||||
|
||||
Nanod.aob2Ab <= (athCtrl == 3'b101); // Used on BSER1 only
|
||||
|
||||
Nanod.abh2Ath <= (athCtrl == 3'b001) | (athCtrl == 3'b101);
|
||||
Nanod.dbh2Ath <= (athCtrl == 3'b100);
|
||||
Nanod.ath2Dbh <= (athCtrl == 3'b110);
|
||||
Nanod.ath2Abh <= (athCtrl == 3'b011);
|
||||
|
||||
Nanod.alu2Dbd <= nanoLatch[ NANO_ALU2DBD];
|
||||
Nanod.alu2Abd <= nanoLatch[ NANO_ALU2ABD];
|
||||
|
||||
Nanod.abd2Dcr <= (nanoLatch[ NANO_DCR+1:NANO_DCR] == 2'b11);
|
||||
Nanod.dcr2Dbd <= (nanoLatch[ NANO_DCR+2:NANO_DCR+1] == 2'b11);
|
||||
Nanod.dbd2Alue <= (nanoLatch[ NANO_ALUE+2:NANO_ALUE+1] == 2'b10);
|
||||
Nanod.alue2Dbd <= (nanoLatch[ NANO_ALUE+1:NANO_ALUE] == 2'b01);
|
||||
|
||||
Nanod.dbd2Alub <= nanoLatch[ NANO_DBD2ALUB];
|
||||
Nanod.abd2Alub <= nanoLatch[ NANO_ABD2ALUB];
|
||||
|
||||
// Originally not latched. We better should because we transfer one cycle later, T3 instead of T1.
|
||||
Nanod.dobCtrl <= dobCtrl;
|
||||
// Nanod.adb2Dob <= (dobCtrl == 2'b10); Nanod.dbd2Dob <= (dobCtrl == 2'b01); Nanod.alu2Dob <= (dobCtrl == 2'b11);
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
// Update SSW at the start of Bus/Addr error ucode
|
||||
assign Nanod.updSsw = Nanod.aob2Ab;
|
||||
|
||||
assign Nanod.updTpend = (ftuCtrl == NANO_FTU_UPDTPEND);
|
||||
assign Nanod.clrTpend = (ftuCtrl == NANO_FTU_CLRTPEND);
|
||||
assign Nanod.tvn2Ftu = (ftuCtrl == NANO_FTU_TVN);
|
||||
assign Nanod.const2Ftu = (ftuCtrl == NANO_FTU_CONST);
|
||||
assign Nanod.ftu2Dbl = (ftuCtrl == NANO_FTU_DBL) | ( ftuCtrl == NANO_FTU_INL);
|
||||
assign Nanod.ftu2Abl = (ftuCtrl == NANO_FTU_2ABL);
|
||||
assign Nanod.inl2psw = (ftuCtrl == NANO_FTU_INL);
|
||||
assign Nanod.pswIToFtu = (ftuCtrl == NANO_FTU_PSWI);
|
||||
assign Nanod.ftu2Sr = (ftuCtrl == NANO_FTU_2SR);
|
||||
assign Nanod.sr2Ftu = (ftuCtrl == NANO_FTU_RDSR);
|
||||
assign Nanod.ird2Ftu = (ftuCtrl == NANO_FTU_IRD); // Used on bus/addr error
|
||||
assign Nanod.ssw2Ftu = (ftuCtrl == NANO_FTU_SSW);
|
||||
assign Nanod.initST = (ftuCtrl == NANO_FTU_INL) | (ftuCtrl == NANO_FTU_CLRTPEND) | (ftuCtrl == NANO_FTU_INIT_ST);
|
||||
assign Nanod.abl2Pren = (ftuCtrl == NANO_FTU_ABL2PREN);
|
||||
assign Nanod.updPren = (ftuCtrl == NANO_FTU_RSTPREN);
|
||||
|
||||
assign Nanod.Ir2Ird = nanoLatch[ NANO_IR2IRD];
|
||||
|
||||
// ALU control better latched later after combining with IRD decoding
|
||||
|
||||
assign Nanod.aluDctrl = nanoLatch[ NANO_ALU_DCTRL+1 : NANO_ALU_DCTRL];
|
||||
assign Nanod.aluActrl = nanoLatch[ NANO_ALU_ACTRL];
|
||||
assign Nanod.aluColumn = { nanoLatch[ NANO_ALU_COL], nanoLatch[ NANO_ALU_COL+1], nanoLatch[ NANO_ALU_COL+2]};
|
||||
wire [1:0] aluFinInit = nanoLatch[ NANO_ALU_FI+1:NANO_ALU_FI];
|
||||
assign Nanod.aluFinish = (aluFinInit == 2'b10);
|
||||
assign Nanod.aluInit = (aluFinInit == 2'b01);
|
||||
|
||||
// FTU 2 CCR encoded as both ALU Init and ALU Finish set.
|
||||
// In theory this encoding allows writes to CCR without writing to SR
|
||||
// But FTU 2 CCR and to SR are both set together at nanorom.
|
||||
assign Nanod.ftu2Ccr = ( aluFinInit == 2'b11);
|
||||
|
||||
assign Nanod.abdIsByte = nanoLatch[ NANO_ABDHRECHARGE];
|
||||
|
||||
// Not being latched on T4 creates non unique case warning!
|
||||
assign Nanod.au2Db = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b01);
|
||||
assign Nanod.au2Ab = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b10);
|
||||
assign Nanod.au2Pc = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b11);
|
||||
|
||||
assign Nanod.db2Aob = (aobCtrl == 2'b10);
|
||||
assign Nanod.ab2Aob = (aobCtrl == 2'b01);
|
||||
assign Nanod.au2Aob = (aobCtrl == 2'b11);
|
||||
|
||||
assign Nanod.dbin2Abd = nanoLatch[ NANO_DBIN2ABD];
|
||||
assign Nanod.dbin2Dbd = nanoLatch[ NANO_DBIN2DBD];
|
||||
|
||||
assign Nanod.permStart = (| aobCtrl);
|
||||
assign Nanod.isWrite = ( | dobCtrl);
|
||||
assign Nanod.waitBusFinish = nanoLatch[ NANO_TOIRC] | nanoLatch[ NANO_TODBIN] | Nanod.isWrite;
|
||||
assign Nanod.busByte = nanoLatch[ NANO_BUSBYTE];
|
||||
|
||||
assign Nanod.noLowByte = nanoLatch[ NANO_LOWBYTE];
|
||||
assign Nanod.noHighByte = nanoLatch[ NANO_HIGHBYTE];
|
||||
|
||||
// Not registered. Register at T4 after combining
|
||||
// Might be better to remove all those and combine here instead of at execution unit !!
|
||||
assign Nanod.abl2reg = nanoLatch[ NANO_ABL2REG];
|
||||
assign Nanod.abh2reg = nanoLatch[ NANO_ABH2REG];
|
||||
assign Nanod.dbl2reg = nanoLatch[ NANO_DBL2REG];
|
||||
assign Nanod.dbh2reg = nanoLatch[ NANO_DBH2REG];
|
||||
assign Nanod.reg2dbl = nanoLatch[ NANO_REG2DBL];
|
||||
assign Nanod.reg2dbh = nanoLatch[ NANO_REG2DBH];
|
||||
assign Nanod.reg2abl = nanoLatch[ NANO_REG2ABL];
|
||||
assign Nanod.reg2abh = nanoLatch[ NANO_REG2ABH];
|
||||
|
||||
assign Nanod.ssp = nanoLatch[ NANO_SSP];
|
||||
|
||||
assign Nanod.rz = nanoLatch[ NANO_RZ];
|
||||
|
||||
// Actually DTL can't happen on PC relative mode. See IR decoder.
|
||||
|
||||
wire dtldbd = 1'b0;
|
||||
wire dthdbh = 1'b0;
|
||||
wire dtlabd = 1'b0;
|
||||
wire dthabh = 1'b0;
|
||||
|
||||
wire dblSpecial = Nanod.pcldbl | dtldbd;
|
||||
wire dbhSpecial = Nanod.pchdbh | dthdbh;
|
||||
wire ablSpecial = Nanod.pclabl | dtlabd;
|
||||
wire abhSpecial = Nanod.pchabh | dthabh;
|
||||
|
||||
//
|
||||
// Combine with IRD decoding
|
||||
// Careful that IRD is updated only on T1! All output depending on IRD must be latched on T4!
|
||||
//
|
||||
|
||||
// PC used instead of RY on PC relative instuctions
|
||||
|
||||
assign Nanod.rxlDbl = nanoLatch[ NANO_RXL_DBL];
|
||||
wire isPcRel = Irdecod.isPcRel & !Nanod.rz;
|
||||
wire pcRelDbl = isPcRel & !nanoLatch[ NANO_RXL_DBL];
|
||||
wire pcRelDbh = isPcRel & !nanoLatch[ NANO_RXH_DBH];
|
||||
wire pcRelAbl = isPcRel & nanoLatch[ NANO_RXL_DBL];
|
||||
wire pcRelAbh = isPcRel & nanoLatch[ NANO_RXH_DBH];
|
||||
|
||||
assign Nanod.pcldbl = nanoLatch[ NANO_PCLDBL] | pcRelDbl;
|
||||
assign Nanod.pchdbh = (nanoLatch[ NANO_PCH+1:NANO_PCH] == 2'b01) | pcRelDbh;
|
||||
|
||||
assign Nanod.pclabl = nanoLatch[ NANO_PCLABL] | pcRelAbl;
|
||||
assign Nanod.pchabh = (nanoLatch[ NANO_PCH+1:NANO_PCH] == 2'b10) | pcRelAbh;
|
||||
|
||||
// Might be better not to register these signals to allow latching RX/RY mux earlier!
|
||||
// But then must latch Irdecod.isPcRel on T3!
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( enT4) begin
|
||||
Nanod.rxl2db <= Nanod.reg2dbl & !dblSpecial & nanoLatch[ NANO_RXL_DBL];
|
||||
Nanod.rxl2ab <= Nanod.reg2abl & !ablSpecial & !nanoLatch[ NANO_RXL_DBL];
|
||||
|
||||
Nanod.dbl2rxl <= Nanod.dbl2reg & !dblSpecial & nanoLatch[ NANO_RXL_DBL];
|
||||
Nanod.abl2rxl <= Nanod.abl2reg & !ablSpecial & !nanoLatch[ NANO_RXL_DBL];
|
||||
|
||||
Nanod.rxh2dbh <= Nanod.reg2dbh & !dbhSpecial & nanoLatch[ NANO_RXH_DBH];
|
||||
Nanod.rxh2abh <= Nanod.reg2abh & !abhSpecial & !nanoLatch[ NANO_RXH_DBH];
|
||||
|
||||
Nanod.dbh2rxh <= Nanod.dbh2reg & !dbhSpecial & nanoLatch[ NANO_RXH_DBH];
|
||||
Nanod.abh2rxh <= Nanod.abh2reg & !abhSpecial & !nanoLatch[ NANO_RXH_DBH];
|
||||
|
||||
Nanod.dbh2ryh <= Nanod.dbh2reg & !dbhSpecial & !nanoLatch[ NANO_RXH_DBH];
|
||||
Nanod.abh2ryh <= Nanod.abh2reg & !abhSpecial & nanoLatch[ NANO_RXH_DBH];
|
||||
|
||||
Nanod.dbl2ryl <= Nanod.dbl2reg & !dblSpecial & !nanoLatch[ NANO_RXL_DBL];
|
||||
Nanod.abl2ryl <= Nanod.abl2reg & !ablSpecial & nanoLatch[ NANO_RXL_DBL];
|
||||
|
||||
Nanod.ryl2db <= Nanod.reg2dbl & !dblSpecial & !nanoLatch[ NANO_RXL_DBL];
|
||||
Nanod.ryl2ab <= Nanod.reg2abl & !ablSpecial & nanoLatch[ NANO_RXL_DBL];
|
||||
|
||||
Nanod.ryh2dbh <= Nanod.reg2dbh & !dbhSpecial & !nanoLatch[ NANO_RXH_DBH];
|
||||
Nanod.ryh2abh <= Nanod.reg2abh & !abhSpecial & nanoLatch[ NANO_RXH_DBH];
|
||||
end
|
||||
|
||||
// Originally isTas only delayed on T2 (and seems only a late mask rev fix)
|
||||
// Better latch the combination on T4
|
||||
if( enT4)
|
||||
Nanod.isRmc <= Irdecod.isTas & nanoLatch[ NANO_BUSBYTE];
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -1,23 +0,0 @@
|
||||
// bin to one-hot, 4 bits to 16-bit bitmap
|
||||
module onehotEncoder4( input [3:0] bin, output reg [15:0] bitMap);
|
||||
always_comb begin
|
||||
case( bin)
|
||||
'b0000: bitMap = 16'h0001;
|
||||
'b0001: bitMap = 16'h0002;
|
||||
'b0010: bitMap = 16'h0004;
|
||||
'b0011: bitMap = 16'h0008;
|
||||
'b0100: bitMap = 16'h0010;
|
||||
'b0101: bitMap = 16'h0020;
|
||||
'b0110: bitMap = 16'h0040;
|
||||
'b0111: bitMap = 16'h0080;
|
||||
'b1000: bitMap = 16'h0100;
|
||||
'b1001: bitMap = 16'h0200;
|
||||
'b1010: bitMap = 16'h0400;
|
||||
'b1011: bitMap = 16'h0800;
|
||||
'b1100: bitMap = 16'h1000;
|
||||
'b1101: bitMap = 16'h2000;
|
||||
'b1110: bitMap = 16'h4000;
|
||||
'b1111: bitMap = 16'h8000;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
@@ -1,25 +0,0 @@
|
||||
// priority encoder
|
||||
// used by MOVEM regmask
|
||||
// this might benefit from device specific features
|
||||
// MOVEM doesn't need speed, will read the result 2 CPU cycles after each update.
|
||||
module pren( mask, hbit);
|
||||
parameter size = 16;
|
||||
parameter outbits = 4;
|
||||
|
||||
input [size-1:0] mask;
|
||||
output reg [outbits-1:0] hbit;
|
||||
// output reg idle;
|
||||
|
||||
always @( mask) begin
|
||||
integer i;
|
||||
hbit = 0;
|
||||
// idle = 1;
|
||||
for( i = size-1; i >= 0; i = i - 1) begin
|
||||
if( mask[ i]) begin
|
||||
hbit = i;
|
||||
// idle = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,139 +0,0 @@
|
||||
// Decodes IRD into ALU row (1-15)
|
||||
// Slow, but no need to optimize for speed since IRD is latched at least two CPU cycles before it is used
|
||||
// We also register the result after combining with column from nanocode
|
||||
//
|
||||
// Many opcodes are not decoded because they either don't do any ALU op,
|
||||
// or use only columns 1 and 5 that are the same for all rows.
|
||||
|
||||
module rowDecoder( input [15:0] ird,
|
||||
output logic [15:0] row, output noCcrEn, output logic isArX);
|
||||
|
||||
|
||||
// Addr or data register direct
|
||||
wire eaRdir = (ird[ 5:4] == 2'b00);
|
||||
// Addr register direct
|
||||
wire eaAdir = (ird[ 5:3] == 3'b001);
|
||||
wire size11 = ird[7] & ird[6];
|
||||
|
||||
always_comb begin
|
||||
case( ird[15:12])
|
||||
'h4,
|
||||
'h9,
|
||||
'hd:
|
||||
isArX = row[10] | row[12];
|
||||
default:
|
||||
isArX = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
unique case( ird[15:12])
|
||||
|
||||
'h4: begin
|
||||
if( ird[8])
|
||||
row = `ALU_ROW_06; // chk (or lea)
|
||||
else case( ird[11:9])
|
||||
'b000: row = `ALU_ROW_10; // negx
|
||||
'b001: row = `ALU_ROW_04; // clr
|
||||
'b010: row = `ALU_ROW_05; // neg
|
||||
'b011: row = `ALU_ROW_11; // not
|
||||
'b100: row = (ird[7]) ? `ALU_ROW_08 : `ALU_ROW_09; // nbcd/swap/ext(or pea)
|
||||
'b101: row = `ALU_ROW_15; // tst & tas
|
||||
default: row = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
'h0: begin
|
||||
if( ird[8]) // dynamic bit
|
||||
row = ird[7] ? `ALU_ROW_14 : `ALU_ROW_13;
|
||||
else case( ird[ 11:9])
|
||||
'b000: row = `ALU_ROW_14; // ori
|
||||
'b001: row = `ALU_ROW_04; // andi
|
||||
'b010: row = `ALU_ROW_05; // subi
|
||||
'b011: row = `ALU_ROW_02; // addi
|
||||
'b100: row = ird[7] ? `ALU_ROW_14 : `ALU_ROW_13; // static bit
|
||||
'b101: row = `ALU_ROW_13; // eori
|
||||
'b110: row = `ALU_ROW_06; // cmpi
|
||||
default: row = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
// MOVE
|
||||
// move.b originally also rows 5 & 15. Only because IRD bit 14 is not decoded.
|
||||
// It's the same for move the operations performed by MOVE.B
|
||||
|
||||
'h1,'h2,'h3: row = `ALU_ROW_02;
|
||||
|
||||
'h5:
|
||||
if( size11)
|
||||
row = `ALU_ROW_15; // As originally and easier to decode
|
||||
else
|
||||
row = ird[8] ? `ALU_ROW_05 : `ALU_ROW_02; // addq/subq
|
||||
'h6: row = 0; //bcc/bra/bsr
|
||||
'h7: row = `ALU_ROW_02; // moveq
|
||||
'h8:
|
||||
if( size11) // div
|
||||
row = `ALU_ROW_01;
|
||||
else if( ird[8] & eaRdir) // sbcd
|
||||
row = `ALU_ROW_09;
|
||||
else
|
||||
row = `ALU_ROW_14; // or
|
||||
'h9:
|
||||
if( ird[8] & ~size11 & eaRdir)
|
||||
row = `ALU_ROW_10; // subx
|
||||
else
|
||||
row = `ALU_ROW_05; // sub/suba
|
||||
'hb:
|
||||
if( ird[8] & ~size11 & ~eaAdir)
|
||||
row = `ALU_ROW_13; // eor
|
||||
else
|
||||
row = `ALU_ROW_06; // cmp/cmpa/cmpm
|
||||
'hc:
|
||||
if( size11)
|
||||
row = `ALU_ROW_07; // mul
|
||||
else if( ird[8] & eaRdir) // abcd
|
||||
row = `ALU_ROW_03;
|
||||
else
|
||||
row = `ALU_ROW_04; // and
|
||||
'hd:
|
||||
if( ird[8] & ~size11 & eaRdir)
|
||||
row = `ALU_ROW_12; // addx
|
||||
else
|
||||
row = `ALU_ROW_02; // add/adda
|
||||
'he:
|
||||
begin
|
||||
reg [1:0] stype;
|
||||
|
||||
if( size11) // memory shift/rotate
|
||||
stype = ird[ 10:9];
|
||||
else // register shift/rotate
|
||||
stype = ird[ 4:3];
|
||||
|
||||
case( {stype, ird[8]})
|
||||
0: row = `ALU_ROW_02; // ASR
|
||||
1: row = `ALU_ROW_03; // ASL
|
||||
2: row = `ALU_ROW_05; // LSR
|
||||
3: row = `ALU_ROW_04; // LSL
|
||||
4: row = `ALU_ROW_08; // ROXR
|
||||
5: row = `ALU_ROW_11; // ROXL
|
||||
6: row = `ALU_ROW_10; // ROR
|
||||
7: row = `ALU_ROW_09; // ROL
|
||||
endcase
|
||||
end
|
||||
|
||||
default: row = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Decode opcodes that don't affect flags
|
||||
// ADDA/SUBA ADDQ/SUBQ MOVEA
|
||||
|
||||
assign noCcrEn =
|
||||
// ADDA/SUBA
|
||||
( ird[15] & ~ird[13] & ird[12] & size11) |
|
||||
// ADDQ/SUBQ to An
|
||||
( (ird[15:12] == 4'h5) & eaAdir) |
|
||||
// MOVEA
|
||||
( (~ird[15] & ~ird[14] & ird[13]) & ird[8:6] == 3'b001);
|
||||
|
||||
endmodule
|
||||
@@ -1,237 +0,0 @@
|
||||
// Microcode sequencer
|
||||
|
||||
module sequencer( input s_clks Clks, input enT3,
|
||||
input [UROM_WIDTH-1:0] microLatch,
|
||||
input A0Err, BerrA, busAddrErr, Spuria, Avia,
|
||||
input Tpend, intPend, isIllegal, isPriv, excRst, isLineA, isLineF,
|
||||
input [15:0] psw,
|
||||
input prenEmpty, au05z, dcr4, ze, i11,
|
||||
input [1:0] alue01,
|
||||
input [15:0] Ird,
|
||||
input [UADDR_WIDTH-1:0] a1, a2, a3,
|
||||
output logic [3:0] tvn,
|
||||
output logic [UADDR_WIDTH-1:0] nma);
|
||||
|
||||
logic [UADDR_WIDTH-1:0] uNma;
|
||||
logic [UADDR_WIDTH-1:0] grp1Nma;
|
||||
logic [1:0] c0c1;
|
||||
reg a0Rst;
|
||||
wire A0Sel;
|
||||
wire inGrp0Exc;
|
||||
|
||||
// assign nma = Clks.extReset ? RSTP0_NMA : (A0Err ? BSER1_NMA : uNma);
|
||||
// assign nma = A0Err ? (a0Rst ? RSTP0_NMA : BSER1_NMA) : uNma;
|
||||
|
||||
// word type I: 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||||
// NMA : .. .. 09 08 01 00 05 04 03 02 07 06 .. .. .. .. ..
|
||||
|
||||
wire [UADDR_WIDTH-1:0] dbNma = { microLatch[ 14:13], microLatch[ 6:5], microLatch[ 10:7], microLatch[ 12:11]};
|
||||
|
||||
// Group 0 exception.
|
||||
// Separated block from regular NMA. Otherwise simulation might depend on order of assigments.
|
||||
always_comb begin
|
||||
if( A0Err) begin
|
||||
if( a0Rst) // Reset
|
||||
nma = RSTP0_NMA;
|
||||
else if( inGrp0Exc) // Double fault
|
||||
nma = HALT1_NMA;
|
||||
else // Bus or address error
|
||||
nma = BSER1_NMA;
|
||||
end
|
||||
else
|
||||
nma = uNma;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
// Format II (conditional) or I (direct branch)
|
||||
if( microLatch[1])
|
||||
uNma = { microLatch[ 14:13], c0c1, microLatch[ 10:7], microLatch[ 12:11]};
|
||||
else
|
||||
case( microLatch[ 3:2])
|
||||
0: uNma = dbNma; // DB
|
||||
1: uNma = A0Sel ? grp1Nma : a1;
|
||||
2: uNma = a2;
|
||||
3: uNma = a3;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Format II, conditional, NMA decoding
|
||||
wire [1:0] enl = { Ird[6], prenEmpty}; // Updated on T3
|
||||
|
||||
wire [1:0] ms0 = { Ird[8], alue01[0]};
|
||||
wire [3:0] m01 = { au05z, Ird[8], alue01};
|
||||
wire [1:0] nz1 = { psw[ NF], psw[ ZF]};
|
||||
wire [1:0] nv = { psw[ NF], psw[ VF]};
|
||||
|
||||
logic ccTest;
|
||||
wire [4:0] cbc = microLatch[ 6:2]; // CBC bits
|
||||
|
||||
always_comb begin
|
||||
unique case( cbc)
|
||||
'h0: c0c1 = {i11, i11}; // W/L offset EA, from IRC
|
||||
|
||||
'h1: c0c1 = (au05z) ? 2'b01 : 2'b11; // Updated on T3
|
||||
'h11: c0c1 = (au05z) ? 2'b00 : 2'b11;
|
||||
|
||||
'h02: c0c1 = { 1'b0, ~psw[ CF]}; // C used in DIV
|
||||
'h12: c0c1 = { 1'b1, ~psw[ CF]};
|
||||
|
||||
'h03: c0c1 = {psw[ ZF], psw[ ZF]}; // Z used in DIVU
|
||||
|
||||
'h04: // nz1, used in DIVS
|
||||
case( nz1)
|
||||
'b00: c0c1 = 2'b10;
|
||||
'b10: c0c1 = 2'b01;
|
||||
'b01,'b11: c0c1 = 2'b11;
|
||||
endcase
|
||||
|
||||
'h05: c0c1 = {psw[ NF], 1'b1}; // N used in CHK and DIV
|
||||
'h15: c0c1 = {1'b1, psw[ NF]};
|
||||
|
||||
// nz2, used in DIVS (same combination as nz1)
|
||||
'h06: c0c1 = { ~nz1[1] & ~nz1[0], 1'b1};
|
||||
|
||||
'h07: // ms0 used in MUL
|
||||
case( ms0)
|
||||
'b10, 'b00: c0c1 = 2'b11;
|
||||
'b01: c0c1 = 2'b01;
|
||||
'b11: c0c1 = 2'b10;
|
||||
endcase
|
||||
|
||||
'h08: // m01 used in MUL
|
||||
case( m01)
|
||||
'b0000,'b0001,'b0100,'b0111: c0c1 = 2'b11;
|
||||
'b0010,'b0011,'b0101: c0c1 = 2'b01;
|
||||
'b0110: c0c1 = 2'b10;
|
||||
default: c0c1 = 2'b00;
|
||||
endcase
|
||||
|
||||
// Conditional
|
||||
'h09: c0c1 = (ccTest) ? 2'b11 : 2'b01;
|
||||
'h19: c0c1 = (ccTest) ? 2'b11 : 2'b10;
|
||||
|
||||
// DCR bit 4 (high or low word)
|
||||
'h0c: c0c1 = dcr4 ? 2'b01: 2'b11;
|
||||
'h1c: c0c1 = dcr4 ? 2'b10: 2'b11;
|
||||
|
||||
// DBcc done
|
||||
'h0a: c0c1 = ze ? 2'b11 : 2'b00;
|
||||
|
||||
// nv, used in CHK
|
||||
'h0b: c0c1 = (nv == 2'b00) ? 2'b00 : 2'b11;
|
||||
|
||||
// V, used in trapv
|
||||
'h0d: c0c1 = { ~psw[ VF], ~psw[VF]};
|
||||
|
||||
// enl, combination of pren idle and word/long on IRD
|
||||
'h0e,'h1e:
|
||||
case( enl)
|
||||
2'b00: c0c1 = 'b10;
|
||||
2'b10: c0c1 = 'b11;
|
||||
// 'hx1 result 00/01 depending on condition 0e/1e
|
||||
2'b01,2'b11:
|
||||
c0c1 = { 1'b0, microLatch[ 6]};
|
||||
endcase
|
||||
|
||||
default: c0c1 = 'X;
|
||||
endcase
|
||||
end
|
||||
|
||||
// CCR conditional
|
||||
always_comb begin
|
||||
unique case( Ird[ 11:8])
|
||||
'h0: ccTest = 1'b1; // T
|
||||
'h1: ccTest = 1'b0; // F
|
||||
'h2: ccTest = ~psw[ CF] & ~psw[ ZF]; // HI
|
||||
'h3: ccTest = psw[ CF] | psw[ZF]; // LS
|
||||
'h4: ccTest = ~psw[ CF]; // CC (HS)
|
||||
'h5: ccTest = psw[ CF]; // CS (LO)
|
||||
'h6: ccTest = ~psw[ ZF]; // NE
|
||||
'h7: ccTest = psw[ ZF]; // EQ
|
||||
'h8: ccTest = ~psw[ VF]; // VC
|
||||
'h9: ccTest = psw[ VF]; // VS
|
||||
'ha: ccTest = ~psw[ NF]; // PL
|
||||
'hb: ccTest = psw[ NF]; // MI
|
||||
'hc: ccTest = (psw[ NF] & psw[ VF]) | (~psw[ NF] & ~psw[ VF]); // GE
|
||||
'hd: ccTest = (psw[ NF] & ~psw[ VF]) | (~psw[ NF] & psw[ VF]); // LT
|
||||
'he: ccTest = (psw[ NF] & psw[ VF] & ~psw[ ZF]) |
|
||||
(~psw[ NF] & ~psw[ VF] & ~psw[ ZF]); // GT
|
||||
'hf: ccTest = psw[ ZF] | (psw[ NF] & ~psw[VF]) | (~psw[ NF] & psw[VF]); // LE
|
||||
endcase
|
||||
end
|
||||
|
||||
// Exception logic
|
||||
logic rTrace, rInterrupt;
|
||||
logic rIllegal, rPriv, rLineA, rLineF;
|
||||
logic rExcRst, rExcAdrErr, rExcBusErr;
|
||||
logic rSpurious, rAutovec;
|
||||
wire grp1LatchEn, grp0LatchEn;
|
||||
|
||||
// Originally control signals latched on T4. Then exception latches updated on T3
|
||||
assign grp1LatchEn = microLatch[0] & (microLatch[1] | !microLatch[4]);
|
||||
assign grp0LatchEn = microLatch[4] & !microLatch[1];
|
||||
|
||||
assign inGrp0Exc = rExcRst | rExcBusErr | rExcAdrErr;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( grp0LatchEn & enT3) begin
|
||||
rExcRst <= excRst;
|
||||
rExcBusErr <= BerrA;
|
||||
rExcAdrErr <= busAddrErr;
|
||||
rSpurious <= Spuria;
|
||||
rAutovec <= Avia;
|
||||
end
|
||||
|
||||
// Update group 1 exception latches
|
||||
// Inputs from IR decoder updated on T1 as soon as IR loaded
|
||||
// Trace pending updated on T3 at the start of the instruction
|
||||
// Interrupt pending on T2
|
||||
if( grp1LatchEn & enT3) begin
|
||||
rTrace <= Tpend;
|
||||
rInterrupt <= intPend;
|
||||
rIllegal <= isIllegal & ~isLineA & ~isLineF;
|
||||
rLineA <= isLineA;
|
||||
rLineF <= isLineF;
|
||||
rPriv <= isPriv & !psw[ SF];
|
||||
end
|
||||
end
|
||||
|
||||
// exception priority
|
||||
always_comb begin
|
||||
grp1Nma = TRAC1_NMA;
|
||||
if( rExcRst)
|
||||
tvn = '0; // Might need to change that to signal in exception
|
||||
else if( rExcBusErr | rExcAdrErr)
|
||||
tvn = { 1'b1, rExcAdrErr};
|
||||
|
||||
// Seudo group 0 exceptions. Just for updating TVN
|
||||
else if( rSpurious | rAutovec)
|
||||
tvn = rSpurious ? TVN_SPURIOUS : TVN_AUTOVEC;
|
||||
|
||||
else if( rTrace)
|
||||
tvn = 9;
|
||||
else if( rInterrupt) begin
|
||||
tvn = TVN_INTERRUPT;
|
||||
grp1Nma = ITLX1_NMA;
|
||||
end
|
||||
else begin
|
||||
unique case( 1'b1) // Can't happen more than one of these
|
||||
rIllegal: tvn = 4;
|
||||
rPriv: tvn = 8;
|
||||
rLineA: tvn = 10;
|
||||
rLineF: tvn = 11;
|
||||
default: tvn = 1; // Signal no group 0/1 exception
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
assign A0Sel = rIllegal | rLineF | rLineA | rPriv | rTrace | rInterrupt;
|
||||
|
||||
always_ff @( posedge Clks.clk) begin
|
||||
if( Clks.extReset)
|
||||
a0Rst <= 1'b1;
|
||||
else if( enT3)
|
||||
a0Rst <= 1'b0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,91 +0,0 @@
|
||||
// Provides ucode routine entries (A1/A3) for each opcode
|
||||
// Also checks for illegal opcode and priv violation
|
||||
|
||||
// This is one of the slowest part of the processor.
|
||||
// But no need to optimize or pipeline because the result is not needed until at least 4 cycles.
|
||||
// IR updated at the least one microinstruction earlier.
|
||||
// Just need to configure the timing analizer correctly.
|
||||
|
||||
module uaddrDecode(
|
||||
input [15:0] opcode,
|
||||
output [UADDR_WIDTH-1:0] a1, a2, a3,
|
||||
output logic isPriv, isIllegal, isLineA, isLineF,
|
||||
output [15:0] lineBmap);
|
||||
|
||||
wire [3:0] line = opcode[15:12];
|
||||
logic [3:0] eaCol, movEa;
|
||||
|
||||
onehotEncoder4 irLineDecod( line, lineBmap);
|
||||
|
||||
assign isLineA = lineBmap[ 'hA];
|
||||
assign isLineF = lineBmap[ 'hF];
|
||||
|
||||
pla_lined pla_lined( .movEa( movEa), .col( eaCol),
|
||||
.opcode( opcode), .lineBmap( lineBmap),
|
||||
.palIll( isIllegal), .plaA1( a1), .plaA2( a2), .plaA3( a3) );
|
||||
|
||||
// ea decoding
|
||||
assign eaCol = eaDecode( opcode[ 5:0]);
|
||||
assign movEa = eaDecode( {opcode[ 8:6], opcode[ 11:9]} );
|
||||
|
||||
// EA decode
|
||||
function [3:0] eaDecode;
|
||||
input [5:0] eaBits;
|
||||
begin
|
||||
unique case( eaBits[ 5:3])
|
||||
3'b111:
|
||||
case( eaBits[ 2:0])
|
||||
3'b000: eaDecode = 7; // Absolute short
|
||||
3'b001: eaDecode = 8; // Absolute long
|
||||
3'b010: eaDecode = 9; // PC displacement
|
||||
3'b011: eaDecode = 10; // PC offset
|
||||
3'b100: eaDecode = 11; // Immediate
|
||||
default: eaDecode = 12; // Invalid
|
||||
endcase
|
||||
|
||||
default: eaDecode = eaBits[5:3]; // Register based EAs
|
||||
endcase
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
/*
|
||||
Privileged instructions:
|
||||
|
||||
ANDI/EORI/ORI SR
|
||||
MOVE to SR
|
||||
MOVE to/from USP
|
||||
RESET
|
||||
RTE
|
||||
STOP
|
||||
*/
|
||||
|
||||
always_comb begin
|
||||
unique case( lineBmap)
|
||||
|
||||
// ori/andi/eori SR
|
||||
'h01: isPriv = ((opcode & 16'hf5ff) == 16'h007c);
|
||||
|
||||
'h10:
|
||||
begin
|
||||
// No priority !!!
|
||||
if( (opcode & 16'hffc0) == 16'h46c0) // move to sr
|
||||
isPriv = 1'b1;
|
||||
|
||||
else if( (opcode & 16'hfff0) == 16'h4e60) // move usp
|
||||
isPriv = 1'b1;
|
||||
|
||||
else if( opcode == 16'h4e70 || // reset
|
||||
opcode == 16'h4e73 || // rte
|
||||
opcode == 16'h4e72) // stop
|
||||
isPriv = 1'b1;
|
||||
else
|
||||
isPriv = 1'b0;
|
||||
end
|
||||
|
||||
default: isPriv = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user