diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..3fbbe35 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,6 @@ +##################################################################### +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: OTHER +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +##################################################################### +ko_fi: boogermann diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml new file mode 100644 index 0000000..3778f24 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -0,0 +1,82 @@ +##################################################################### +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: OTHER +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +##################################################################### +name: "Bug Report" +description: "Let us know about an unexpected error, a crash, or an incorrect behavior." +title: 'Title of your Bug Report' +labels: + - bug +assignees: + - boogermann +body: + - type: markdown + attributes: + value: | + Hi there, + + Thank you for opening an issue. Please note that we try to keep the issue tracker reserved for bug reports. + Make sure to [search for existing issues](https://github.com/opengateware/arcade-galivan/issues?q=label%3Abug) before filing a new one! + + - type: input + id: version + attributes: + label: Version (or build number) + placeholder: "1.0.0" + description: | + You can find the version in the about dialog. + + If you are not running the latest version, please try upgrading because your issue may have already been fixed. + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: | + Please list the full steps required to reproduce the issue + placeholder: | + - Be precise + - Include exact data used during testing for easy reference + - The steps have to be in the exact order + - Mention pre-requisites when applicable + validations: + required: false + + - type: textarea + id: expected_behavior + attributes: + label: Expected Behavior + description: If you want to include screenshots, paste them into the markdown editor below or follow up with a separate comment. + placeholder: What were you expecting? + validations: + required: false + + - type: textarea + id: actual_behavior + attributes: + label: Actual Behavior + placeholder: What happened instead? + validations: + required: true + + - type: textarea + id: bug_context + attributes: + label: Additional Context + description: | + Are there anything atypical about your situation that we should know? + validations: + required: false + + - type: input + id: bug_firmware + attributes: + label: Opened Issues and Pull Requests + placeholder: "#1234" + description: | + Are there any other GitHub issues (open or closed) or Pull Requests that should be linked here? For example: #1234 + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/QUESTION.yml b/.github/ISSUE_TEMPLATE/QUESTION.yml new file mode 100644 index 0000000..216a4da --- /dev/null +++ b/.github/ISSUE_TEMPLATE/QUESTION.yml @@ -0,0 +1,29 @@ +##################################################################### +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: OTHER +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +##################################################################### +name: "Question" +description: "Ask a question about the project." +title: 'Title of your Question' +labels: + - question +assignees: + - boogermann +body: + - type: markdown + attributes: + value: | + Hi there, + + Please note that we try to keep the issue tracker reserved for bug reports. + Make sure to [search for existing questions](https://github.com/opengateware/arcade-galivan/issues?q=label%3Aquestion) before filing a new one! + + - type: textarea + id: question + attributes: + label: Ask a question about Cosmo Police Galivan Compatible Gateware IP Core + placeholder: | + Ask your question here! Please keep the questions related to the FPGA Core only. + validations: + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..3113e01 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,44 @@ + + + + + + +## What does this do / why do we need it? + + + +{Please write here} + +Fixes # (issue) + +## Type of change + + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update +- [ ] Coding style (indentation, etc) +- [ ] {Please write custom change here} + +## What should a reviewer look out for in this PR? + + + +{Please write here} + +## Additional Comments (if any) + +{Please write here} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..22ea03c --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,53 @@ +################################################################################ +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: OTHER +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +################################################################################ +name: Build/Release +################################################################################ +# How to create a tag to launch the workflow +# git tag -a "0.1.0" -m "Release v0.1.0" +# git push origin --tags +################################################################################ +on: + push: + tags: + - "[0-9]+.[0-9]+.[0-9]+" + +jobs: + synthesis: + runs-on: ubuntu-latest + strategy: + matrix: + target: + - pocket + env: + CORE: irem_m92 + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_PAT: ${{ secrets.PAT_TOKEN }} + WEBHOOK_RAETRO: ${{ secrets.RAETRO_WEBHOOK }} + WEBHOOK_FPGAGAMING: ${{ secrets.FPGAGAMING_WEBHOOK }} + + steps: + - name: "🧰 Checkout Repository" + uses: actions/checkout@v4 + + - name: "🧰 Checkout Packybara" + uses: actions/checkout@v4 + with: + repository: "boogermann/publish" + path: ".github/publish" + token: ${{ env.GH_PAT }} + + - name: "🏗️ Compile Design" + uses: raetro/quartus-flow@v1 + with: + project: "${{ env.CORE }}_${{ matrix.target }}" + version: "${{ matrix.target }}" + + - name: "🏗️ Create Packages and Release" + env: + TARGET: ${{ matrix.target }} + run: | + pip3 install -r .github/publish/requirements.txt + python3 .github/publish/${{ matrix.TARGET }}.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f5b8aca --- /dev/null +++ b/.gitignore @@ -0,0 +1,59 @@ +db +greybox_tmp +hps_isw_handoff +incremental_db +output_files +PLLJ_PLLSPE_INFO.txt +simulation +vip +.qsys_edit +*_netlist +*_sim +*.bak +*.bsf +*.cdf +*.cmp +*.csv +*.done +*.f +*.pin +*.pof +*.ppf +*.ptf.* +*.qar +*.qarlog +*.qdf +*.qws +*.rbf +*.rbf_r +*.rpt +*.sip +*.sld +*.smsg +*.sof +*.sopc_builder +*.sopcinfo +*.spd +*.summary +*.txt +*.xml +*~ +**/.DS_Store +build_id.mif +build_id.vh +c5_pin_model_dump.txt +cr_ie_info.json +# Editor directories and files +.build +!.gateman/* +!info.txt +!.gateware.json +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +*.rom \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..745e604 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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 init, 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 . + +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: + + {project} Copyright (C) {year} {fullname} + 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 +. + + 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 +. diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..43aeed4 --- /dev/null +++ b/docs/CODE_OF_CONDUCT.md @@ -0,0 +1,64 @@ +# Code Of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and leaders pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level or type of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. +Note, however, that religion, political party, or other ideological affiliation provide no exemptions for the behavior we outline as unacceptable in this Code of Conduct. + +## Our Standards + +We are committed to providing a friendly, safe and welcoming environment for all. + +Examples of behavior that contributes to creating a positive environment include: + +- Be kind and courteous to others +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Collaborating with other community members +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and sexual attention or advances +- The use of inappropriate images, including in a community member's avatar +- The use of inappropriate language, including in a community member's nickname +- Any spamming, flaming, baiting or other attention-stealing behavior +- Excessive or unwelcome helping; answering outside the scope of the question asked +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate + +The goal of the standards and moderation guidelines outlined here is to build and maintain a respectful community. We ask that you don’t just aim to be "technically unimpeachable", but rather try to be your best self. + +We value many things beyond technical expertise, including collaboration and supporting others within our community. Providing a positive experience for other community members can have a much more significant impact than simply providing the correct answer. + +## Our Responsibilities + +Project leaders are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project leaders respect all people who contribute through reporting issues, posting feature requests, updating documentation, metadata, artwork, manuals, videos, submitting pull requests or patches, and other activities. But also have the right and responsibility to remove, edit, or reject messages, comments, commits, code, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any community member for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct and the enforcement policies listed above apply to all Rætro Community venues. This includes but is not limited to any community spaces (both public and private), the entire Rætro Discord server, and all Rætro associated GitHub repositories. Examples of Rætro Community spaces include but are not limited to meet-ups, audio chats on the Rætro Discord, or interaction at a conference. + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. As a community member, you are representing our community, and are expected to behave accordingly. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at or contact [community@raetro.org][conduct-email]. +All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. +The project team is obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html, and the Rust Code of Conduct, available at https://www.rust-lang.org/en-US/conduct.html and the Adafruit Community Code of Conduct, available at https://github.com/adafruit/Adafruit_Community_Code_of_Conduct. + +[homepage]: https://www.contributor-covenant.org +[conduct-email]: mailto:community@raetro.org diff --git a/docs/Flyers and Manuals/bmaster.png b/docs/Flyers and Manuals/bmaster.png new file mode 100644 index 0000000..cbcc580 Binary files /dev/null and b/docs/Flyers and Manuals/bmaster.png differ diff --git a/docs/Flyers and Manuals/crossbld.png b/docs/Flyers and Manuals/crossbld.png new file mode 100644 index 0000000..0401eb0 Binary files /dev/null and b/docs/Flyers and Manuals/crossbld.png differ diff --git a/docs/Flyers and Manuals/dsocc94.jpg b/docs/Flyers and Manuals/dsocc94.jpg new file mode 100644 index 0000000..af20675 Binary files /dev/null and b/docs/Flyers and Manuals/dsocc94.jpg differ diff --git a/docs/Flyers and Manuals/geostorm.png b/docs/Flyers and Manuals/geostorm.png new file mode 100644 index 0000000..73e5fe8 Binary files /dev/null and b/docs/Flyers and Manuals/geostorm.png differ diff --git a/docs/Flyers and Manuals/gunforce.png b/docs/Flyers and Manuals/gunforce.png new file mode 100644 index 0000000..9760aa6 Binary files /dev/null and b/docs/Flyers and Manuals/gunforce.png differ diff --git a/docs/Flyers and Manuals/gunhohki.png b/docs/Flyers and Manuals/gunhohki.png new file mode 100644 index 0000000..02af6b8 Binary files /dev/null and b/docs/Flyers and Manuals/gunhohki.png differ diff --git a/docs/Flyers and Manuals/hook.png b/docs/Flyers and Manuals/hook.png new file mode 100644 index 0000000..3b6da75 Binary files /dev/null and b/docs/Flyers and Manuals/hook.png differ diff --git a/docs/Flyers and Manuals/inthunt.png b/docs/Flyers and Manuals/inthunt.png new file mode 100644 index 0000000..00a37c6 Binary files /dev/null and b/docs/Flyers and Manuals/inthunt.png differ diff --git a/docs/Flyers and Manuals/lethalth.png b/docs/Flyers and Manuals/lethalth.png new file mode 100644 index 0000000..7ae52c6 Binary files /dev/null and b/docs/Flyers and Manuals/lethalth.png differ diff --git a/docs/Flyers and Manuals/mysticri.png b/docs/Flyers and Manuals/mysticri.png new file mode 100644 index 0000000..90680d0 Binary files /dev/null and b/docs/Flyers and Manuals/mysticri.png differ diff --git a/docs/Flyers and Manuals/nbbatman.png b/docs/Flyers and Manuals/nbbatman.png new file mode 100644 index 0000000..a2fb272 Binary files /dev/null and b/docs/Flyers and Manuals/nbbatman.png differ diff --git a/docs/Flyers and Manuals/psoldier.png b/docs/Flyers and Manuals/psoldier.png new file mode 100644 index 0000000..88b07ac Binary files /dev/null and b/docs/Flyers and Manuals/psoldier.png differ diff --git a/docs/Flyers and Manuals/rtypeleo.png b/docs/Flyers and Manuals/rtypeleo.png new file mode 100644 index 0000000..ca0435b Binary files /dev/null and b/docs/Flyers and Manuals/rtypeleo.png differ diff --git a/docs/Flyers and Manuals/skingame.png b/docs/Flyers and Manuals/skingame.png new file mode 100644 index 0000000..5ddbb8b Binary files /dev/null and b/docs/Flyers and Manuals/skingame.png differ diff --git a/docs/Flyers and Manuals/ssoldier.png b/docs/Flyers and Manuals/ssoldier.png new file mode 100644 index 0000000..7a9cb3b Binary files /dev/null and b/docs/Flyers and Manuals/ssoldier.png differ diff --git a/docs/Flyers and Manuals/uccops.png b/docs/Flyers and Manuals/uccops.png new file mode 100644 index 0000000..4e554ab Binary files /dev/null and b/docs/Flyers and Manuals/uccops.png differ diff --git a/docs/Marquee/mysticri.png b/docs/Marquee/mysticri.png new file mode 100644 index 0000000..01c8f0b Binary files /dev/null and b/docs/Marquee/mysticri.png differ diff --git a/docs/Marquee/nbbatman.png b/docs/Marquee/nbbatman.png new file mode 100644 index 0000000..7f6c6c6 Binary files /dev/null and b/docs/Marquee/nbbatman.png differ diff --git a/docs/Marquee/uccops.png b/docs/Marquee/uccops.png new file mode 100644 index 0000000..e8b94a5 Binary files /dev/null and b/docs/Marquee/uccops.png differ diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..f192aea --- /dev/null +++ b/docs/README.md @@ -0,0 +1,162 @@ +![Irem M92](./irem_m92-logo.png) + +[![Active Development](https://img.shields.io/badge/Maintenance%20Level-Actively%20Developed-brightgreen.svg)](#status-of-features) +[![Build](https://github.com/opengateware/arcade-irem_m92/actions/workflows/build.yml/badge.svg)](https://github.com/opengateware/arcade-irem_m92/actions/workflows/build.yml) +[![release](https://img.shields.io/github/release/opengateware/arcade-irem_m92.svg)](https://github.com/opengateware/arcade-irem_m92/releases) +[![license](https://img.shields.io/github/license/opengateware/arcade-irem_m92.svg?label=License&color=yellow)](#legal-notices) +[![issues](https://img.shields.io/github/issues/opengateware/arcade-irem_m92.svg?label=Issues&color=red)](https://github.com/opengateware/arcade-irem_m92/issues) +[![stars](https://img.shields.io/github/stars/opengateware/arcade-irem_m92.svg?label=Project%20Stars)](https://github.com/opengateware/arcade-irem_m92/stargazers) +[![discord](https://img.shields.io/discord/676418475635507210.svg?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://chat.raetro.org) +[![Twitter Follow](https://img.shields.io/twitter/follow/marcusjordan?style=social)](https://twitter.com/marcusjordan) + +# Irem M92 Compatible Gateware IP Core + +> This Implementation of a compatible Irem M92 arcade hardware in HDL is the work of [Martin Donlon]. + +## Overview + +Launched by Irem in 1991, the M92 was an advanced arcade system that offered robust graphics and sound capabilities. + +The M92 system was known for its cutting-edge graphical and sound technologies that enhanced the arcade gaming experience, paving the way for future innovations in the industry. The diverse array of games it supported showcased the hardware's capabilities, making it a popular choice for arcade operators and a fond memory for gamers. + +Notable Games: + +- R-Type Leo: Horizontally-scrolling shoot-em-up and is the third and final arcade release of this classic series. +- GunForce: Run-and-gun shooter where players battle against an army of robots and machines to save the world. +- Blade Master: Side-scrolling fantasy action game featuring two warriors battling through various mythological creatures. +- Undercover Cops: Beat 'em up game set in a future where players fight against urban decay and crime. +- In the Hunt: A submarine-based shoot 'em up with detailed, rich graphics depicting underwater environments. +- Ninja Baseball Bat Man: Side-scrolling beat-em-up for in which up to four players control a team of robotic baseball-star ninjas who must fight their way through a variety of levels, defeating the game's many enemies. + +## Technical specifications + +- **Main CPU:** NEC V33 @ 9 MHz +- **Sound CPU:** NEC V35 @ 14.318181 MHz +- **Sound Chip:** YM2151 OPM @ 3.579545 MHz +- **Sound Chip:** Irem GA20 @ 3.579545 MHz +- **Resolution:** 320×240 @ 6.666 MHz, 32,768 colors (15 bits) +- **Aspect Ratio:** 4:3 +- **Orientation:** Horizontal/Vertical +- **Players:** Up to 4 players (solo, 2-4 concurrents) +- **Control:** 8-way joystick +- **Buttons:** 6 + +## Compatible Platforms + +- Analogue Pocket + +## Compatible Games + +> **Notice Regarding ROMs:** This repository does not contain any ROMs or game files, nor will any links or pre-assembled ROMs be provided by OpenGateware in any form. Users must ensure they have the legal authority to use these titles in their jurisdiction. By using this core, you agree to supply your own ROMs. We do not condone or support the unauthorized use or distribution of copyrighted or any other intellectual property-protected materials. + +| **Game** | Status | +| :---------------------------------------------------- | :----: | +| Blade Master (World) | ✅ | +| Dream Soccer '94 (Japan, M92 hardware) | ✅ | +| Gun Force II (US) | ✅ | +| Gunforce - Battle Fire Engulfed Terror Island (World) | ✅ | +| Hook (World) | ✅ | +| In The Hunt (World) | ✅ | +| Lethal Thunder (World) | ✅ | +| Major Title 2 (World, Set 1) | ✅ | +| Mystic Riders (World) | ✅ | +| Ninja Baseball Bat Man (World) | ✅ | +| R-Type Leo (World) | ✅ | +| Superior Soldiers (US) | ✅ | +| Undercover Cops (World) | ✅ | +| Undercover Cops - Alpha Renewal Version (World) | ✅ | + +### ROM Instructions + +
+ Click to expand + +1. Download and Install [ORCA](https://github.com/opengateware/tools-orca/releases/latest) (Open ROM Conversion Assistant) +2. Download the [ROM Recipes](https://github.com/opengateware/arcade-irem_m92/releases/latest) and extract to your computer. +3. Copy the required MAME `.zip` file(s) into the `roms` folder. +4. Inside the `tools` folder execute the script related to your system. + 1. **Windows:** right click `make_roms.ps1` and select `Run with Powershell`. + 2. **Linux and MacOS:** run script `make_roms.sh`. +5. After the conversion is completed, copy the `Assets` folder to the Root of your SD Card. +6. **Optional:** an `.md5` file is included to verify if the hash of the ROMs are valid. (eg: `md5sum -c checklist.md5`) + +> **Note:** Make sure your `.rom` files are in the `Assets/irem_m92/common` directory. +
+ +## Status of Features + +> **WARNING**: This repository is in active development. There are no guarantees about stability. Breaking changes might occur until a stable `1.0` release is made and announced. + +- [ ] NVRAM/HiScore Save + +## Credits and acknowledgment + +- [Martin Donlon] +- [Jose Tejada] +- [Gyorgy Szombathelyi] + +## Support + +Please consider showing your support for this and future projects by contributing to the developers. While it isn't necessary, it's greatly appreciated. + +- OpenGateware: [Marcus Andrade](https://ko-fi.com/boogermann) + +## Powered by Open-Source Software + +This project borrowed and use code from several other projects. A great thanks to their efforts! + +| Modules | Copyright/Developer | +| :------------------------- | :---------------------- | +| [Irem M92 RTL] | 2023 (c) Martin Donlon | +| [V30] | 2021 (c) Robert Peip | +| [JT51] | 2017 (c) Jose Tejada | + +## License + +This work is licensed under multiple licenses. + +- All original source code is licensed under [GNU General Public License v3.0 or later] unless implicit indicated. +- All documentation is licensed under [Creative Commons Attribution Share Alike 4.0 International] Public License. +- Some configuration and data files are licensed under [Creative Commons Zero v1.0 Universal]. + +Open Gateware and any contributors reserve all others rights, whether under their respective copyrights, patents, or trademarks, whether by implication, estoppel or otherwise. + +Individual files may contain the following SPDX license tags as a shorthand for the above copyright and warranty notices: + +```text +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-License-Identifier: CC-BY-SA-4.0 +SPDX-License-Identifier: CC0-1.0 +``` + +This eases machine processing of licensing information based on the SPDX License Identifiers that are available at . + +## Legal Notices + +- Blade Master / Cross Blades! (c) 1991 Irem Corp. All rights reserved. +- Dream Soccer 94 (c) 1994 Irem Corp. All rights reserved. +- Gunforce (c) 1991 Irem Corp. All rights reserved. +- Gunforce 2 / Geostorm (c) 1994 Irem Corp. All rights reserved. +- Hook (c) 1992 Irem Corp. All rights reserved. +- In The Hunt / Kaitei Daisensou (c) 1993 Irem Corp. All rights reserved. +- Lethal Thunder / Thunder Blaster (c) 1991 Irem Corp. All rights reserved. +- Major Title 2 / The Irem Skins Game (c) 1992 Irem Corp. All rights reserved. +- Mystic Riders / Mahou Keibitai Gun Hohki (c) 1992 Irem Corp. All rights reserved. +- Ninja Baseball Batman / Yakyuu Kakutou League-Man (c) 1993 Irem America Corp. All rights reserved. +- Perfect Soldiers / Superior Soldiers (c) 1993 Irem Corp. All rights reserved. +- R-Type Leo (Japan) (c) 1992 Irem Corp. All rights reserved. +- Undercover Cops (c) 1992 Irem Corp. All rights reserved. + +The Open Gateware authors and contributors or any of its maintainers are in no way associated with or endorsed by IREM SOFTWARE ENGINEERING INC® or any other company not implicit indicated. +All other brands or product names are the property of their respective holders. + +[Irem M92 RTL]: https://github.com/MiSTer-devel/Arcade-IremM92_MiSTer/tree/main/rtl +[JT51]: https://github.com/jotego/jt51 +[V30]: https://github.com/RobertPeip +[Martin Donlon]: https://github.com/wickerwaka +[Gyorgy Szombathelyi]: https://github.com/gyurco +[Jose Tejada]: https://github.com/jotego + +[GNU General Public License v3.0 or later]: https://spdx.org/licenses/GPL-3.0-or-later.html +[Creative Commons Attribution Share Alike 4.0 International]: https://spdx.org/licenses/CC-BY-SA-4.0.html +[Creative Commons Zero v1.0 Universal]: https://spdx.org/licenses/CC0-1.0.html diff --git a/docs/git-social.png b/docs/git-social.png new file mode 100644 index 0000000..5846568 Binary files /dev/null and b/docs/git-social.png differ diff --git a/docs/irem_m92-logo.png b/docs/irem_m92-logo.png new file mode 100644 index 0000000..82ee6f5 Binary files /dev/null and b/docs/irem_m92-logo.png differ diff --git a/gateware.json b/gateware.json new file mode 100644 index 0000000..b159109 --- /dev/null +++ b/gateware.json @@ -0,0 +1,47 @@ +{ + "name": "irem_m92", + "displayName": "Irem M-92", + "description": "Irem M-92 Arcade Compatible Gateware IP Core", + "author": "opengateware", + "version": "0.1.0", + "license": "GPL-3.0-or-later", + "repository": "https://github.com/opengateware/arcade-irem_m92", + "keywords": [ + "ecosystem:gateman" + ], + "scripts": { + "verilator": "echo \"Error: no simulation specified\" && exit 1", + "build:pocket": "quartus_sh --flow compile projects/irem_m92_pocket.qpf", + "program:pocket": "quartus_pgm -m jtag -c 1 -o \"p;projects/output_files/irem_m92_pocket.sof@1\"" + }, + "hardware": { + "id": "irem_m92", + "category": "Arcade", + "name": "Irem M92", + "year": 1991, + "manufacturer": "Irem" + }, + "release": { + "image": "docs/git-social.jpg", + "folders": { + "output_folder": "projects/output_files", + "pkg_folder": "pkg", + "meta_folder": "pkg/meta", + "stage_folder": "staging", + "release_folder": "release" + }, + "target": { + "pocket": { + "release_file": "{author}.{core}_{version}_{date}-{target}", + "metadata_file": "{author}.{core}_{version}_{date}-metadata" + } + } + }, + "platforms": { + "pocket": "2.0.0" + }, + "modules": { + "cpu-v30": "1.0.0", + "sound-jt51": "1.0.0" + } +} \ No newline at end of file diff --git a/modules/cpu-v30/bus_savestates.vhd b/modules/cpu-v30/bus_savestates.vhd new file mode 100644 index 0000000..1f5dccf --- /dev/null +++ b/modules/cpu-v30/bus_savestates.vhd @@ -0,0 +1,105 @@ +----------------------------------------------------------------- +--------------- Bus Package -------------------------------- +----------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +package pBus_savestates is + + constant SSBUS_buswidth : integer := 64; + constant SSBUS_busadr : integer := 7; + + type savestate_type is record + Adr : integer range 0 to (2**SSBUS_busadr)-1; + upper : integer range 0 to SSBUS_buswidth-1; + lower : integer range 0 to SSBUS_buswidth-1; + size : integer range 0 to (2**SSBUS_busadr)-1; + defval : std_logic_vector(SSBUS_buswidth-1 downto 0); + end record; + +end package; + +----------------------------------------------------------------- +--------------- Reg Interface ----------------------------------- +----------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library work; +use work.pBus_savestates.all; + +entity eReg_SS is + generic + ( + Reg : savestate_type; + index : integer := 0 + ); + port + ( + clk : in std_logic; + BUS_Din : in std_logic_vector(SSBUS_buswidth-1 downto 0); + BUS_Adr : in std_logic_vector(SSBUS_busadr-1 downto 0); + BUS_wren : in std_logic; + BUS_rst : in std_logic; + BUS_Dout : out std_logic_vector(SSBUS_buswidth-1 downto 0) := (others => '0'); + Din : in std_logic_vector(Reg.upper downto Reg.lower); + Dout : out std_logic_vector(Reg.upper downto Reg.lower) + ); +end entity; + +architecture arch of eReg_SS is + + signal Dout_buffer : std_logic_vector(Reg.upper downto Reg.lower) := Reg.defval(Reg.upper downto Reg.lower); + + signal AdrI : std_logic_vector(BUS_Adr'left downto 0); + +begin + + AdrI <= std_logic_vector(to_unsigned(Reg.Adr + index, BUS_Adr'length)); + + process (clk) + begin + if rising_edge(clk) then + + if (BUS_rst = '1') then + + Dout_buffer <= Reg.defval(Reg.upper downto Reg.lower); + + else + + if (BUS_Adr = AdrI and BUS_wren = '1') then + for i in Reg.lower to Reg.upper loop + Dout_buffer(i) <= BUS_Din(i); + end loop; + end if; + + end if; + + end if; + end process; + + Dout <= Dout_buffer; + + goutputbit: for i in Reg.lower to Reg.upper generate + BUS_Dout(i) <= Din(i) when BUS_Adr = AdrI else '0'; + end generate; + + glowzero_required: if Reg.lower > 0 generate + glowzero: for i in 0 to Reg.lower - 1 generate + BUS_Dout(i) <= '0'; + end generate; + end generate; + + ghighzero_required: if Reg.upper < SSBUS_buswidth-1 generate + ghighzero: for i in Reg.upper + 1 to SSBUS_buswidth-1 generate + BUS_Dout(i) <= '0'; + end generate; + end generate; + +end architecture; + + diff --git a/modules/cpu-v30/cpu.vhd b/modules/cpu-v30/cpu.vhd new file mode 100644 index 0000000..75077d7 --- /dev/null +++ b/modules/cpu-v30/cpu.vhd @@ -0,0 +1,3221 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +package whatever is + type cpu_export_type is record + reg_ax : unsigned(15 downto 0); + reg_cx : unsigned(15 downto 0); + reg_dx : unsigned(15 downto 0); + reg_bx : unsigned(15 downto 0); + reg_sp : unsigned(15 downto 0); + reg_bp : unsigned(15 downto 0); + reg_si : unsigned(15 downto 0); + reg_di : unsigned(15 downto 0); + reg_es : unsigned(15 downto 0); + reg_cs : unsigned(15 downto 0); + reg_ss : unsigned(15 downto 0); + reg_ds : unsigned(15 downto 0); + reg_ip : unsigned(15 downto 0); + reg_f : unsigned(15 downto 0); + opcodebyte_last : std_logic_vector(7 downto 0); + end record; +end package; + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +-- use work.pexport.all; +use work.pBus_savestates.all; +use work.pReg_savestates.all; + +use work.whatever.all; + +entity v30 is + generic + ( + INTACK_DELAY : integer := 22 + ); + port + ( + clk : in std_logic; + ce : in std_logic; + ce_4x : in std_logic; + reset : in std_logic; + turbo : in std_logic; + SLOWTIMING : in std_logic; -- only used in simulation to sync up with prefetching + + cpu_idle : out std_logic; + cpu_halt : out std_logic; + cpu_irqrequest : out std_logic; + cpu_prefix : out std_logic; + dma_active : in std_logic; + sdma_request : in std_logic; + canSpeedup : out std_logic; + + bus_read : out std_logic := '0'; + bus_write : out std_logic := '0'; + bus_prefetch : out std_logic := '0'; + bus_be : out std_logic_vector(1 downto 0) := "00"; + bus_addr : out unsigned(19 downto 0) := (others => '0'); + bus_datawrite : out std_logic_vector(15 downto 0) := (others => '0'); + bus_dataread : in std_logic_vector(15 downto 0); + + irqrequest_in : in std_logic; + irqvector_in : in unsigned(9 downto 0) := (others => '0'); + irqrequest_ack : out std_logic := '0'; + irqrequest_fini : out std_logic := '0'; + + load_savestate : in std_logic; + + cpu_done : out std_logic := '0'; + cpu_export_opcode : out std_logic_vector(7 downto 0); + cpu_export_reg_cs : out unsigned(15 downto 0); + cpu_export_reg_ip : out unsigned(15 downto 0); + + secure : in std_logic := '0'; + secure_wr : in std_logic; + secure_addr : in unsigned(7 downto 0); + secure_data : in std_logic_vector(7 downto 0); + + -- register + RegBus_Din : out std_logic_vector(7 downto 0) := (others => '0'); + RegBus_Adr : out std_logic_vector(7 downto 0) := (others => '0'); + RegBus_wren : out std_logic := '0'; + RegBus_rden : out std_logic := '0'; + RegBus_Dout : in std_logic_vector(7 downto 0); + + -- savestates + sleep_savestate : in std_logic; + + SSBUS_Din : in std_logic_vector(SSBUS_buswidth-1 downto 0); + SSBUS_Adr : in std_logic_vector(SSBUS_busadr-1 downto 0); + SSBUS_wren : in std_logic; + SSBUS_rst : in std_logic; + SSBUS_Dout : out std_logic_vector(SSBUS_buswidth-1 downto 0) + ); +end entity; + +architecture arch of v30 is + + -- push/pop + constant REGPOS_ax : std_logic_vector(15 downto 0) := x"0001"; + constant REGPOS_cx : std_logic_vector(15 downto 0) := x"0002"; + constant REGPOS_dx : std_logic_vector(15 downto 0) := x"0004"; + constant REGPOS_bx : std_logic_vector(15 downto 0) := x"0008"; + constant REGPOS_sp : std_logic_vector(15 downto 0) := x"0010"; + constant REGPOS_bp : std_logic_vector(15 downto 0) := x"0020"; + constant REGPOS_si : std_logic_vector(15 downto 0) := x"0040"; + constant REGPOS_di : std_logic_vector(15 downto 0) := x"0080"; + constant REGPOS_es : std_logic_vector(15 downto 0) := x"0100"; + constant REGPOS_f : std_logic_vector(15 downto 0) := x"0200"; + constant REGPOS_cs : std_logic_vector(15 downto 0) := x"0400"; + constant REGPOS_ss : std_logic_vector(15 downto 0) := x"0800"; + constant REGPOS_ds : std_logic_vector(15 downto 0) := x"1000"; + constant REGPOS_ip : std_logic_vector(15 downto 0) := x"2000"; + constant REGPOS_mem : std_logic_vector(15 downto 0) := x"4000"; + constant REGPOS_imm : std_logic_vector(15 downto 0) := x"8000"; + + type tPrefetchState is + ( + PREFETCH_IDLE, + PREFETCH_READ, + PREFETCH_WAIT, + PREFETCH_RECEIVE + ); + signal prefetchState : tPrefetchState; + + type tCPUSTAGE is + ( + CPUSTAGE_IDLE, + CPUSTAGE_DECODEOP, + CPUSTAGE_MODRM, + CPUSTAGE_CHECKDATAREADY, + CPUSTAGE_FETCHDATA1_8, + CPUSTAGE_FETCHDATA1_16, + CPUSTAGE_FETCHDATA2_8, + CPUSTAGE_FETCHDATA2_16, + CPUSTAGE_FETCHMEM_REQ, + CPUSTAGE_FETCHMEM_WAIT, + CPUSTAGE_FETCHMEM_REC, + CPUSTAGE_IRQVECTOR_REQ, + CPUSTAGE_IRQVECTOR_WAIT, + CPUSTAGE_IRQVECTOR_REC, + CPUSTAGE_PUSH, + CPUSTAGE_POP_REQ, + CPUSTAGE_POP_WAIT, + CPUSTAGE_POP_REC, + CPUSTAGE_EXECUTE + ); + signal cpustage : tCPUSTAGE; + + type tCPU_Opcode is + ( + --modrm + OP_MEMIMM1, + OP_MEMIMM2, + OP_MEMIMM3, + OP_MEMIMM4, + -- final + OP_MOVMEM, + OP_MOVREG, + OP_EXCHANGE, + OP_BOUND, + OP_OPIN, + OP_OPOUT, + OP_BCDSTRING, + OP_STRINGLOAD, + OP_STRINGCOMPARE, + OP_STRINGSTORE, + OP_ENTER, + OP_JUMPIF, + OP_JUMP, + OP_JUMPABS, + OP_JUMPFAR, + OP_RETURNFAR, + OP_IRQ, + OP_IRQREQUEST, + OP_FLAGSFROMACC, + OP_FLAGSTOACC, + OP_DIV, + OP_DIVI, + OP_MULADJUST, + OP_DIVADJUST, + OP_NOP, + OP_INVALID + ); + + type tOPSOURCE is + ( + OPSOURCE_FETCHVALUE8, + OPSOURCE_FETCHVALUE16, + OPSOURCE_MEM, + OPSOURCE_MODRM_REG, + OPSOURCE_MODRM_ADDR, + OPSOURCE_ACC, + OPSOURCE_IMMIDIATE, + OPSOURCE_POPVALUE, + OPSOURCE_STRINGLOAD1, + OPSOURCE_STRINGLOAD2, + OPSOURCE_IRQVECTOR, + OPSOURCE_REG_ax, + OPSOURCE_REG_cx, + OPSOURCE_REG_dx, + OPSOURCE_REG_bx, + OPSOURCE_REG_sp, + OPSOURCE_REG_bp, + OPSOURCE_REG_si, + OPSOURCE_REG_di, + OPSOURCE_INVALID + ); + + type tOPTARGET is + ( + OPTARGET_DECODE, + OPTARGET_MEM, + OPTARGET_MODRM_REG, + OPTARGET_NONE + ); + + type tCPU_REG is + ( + CPU_REG_al, + CPU_REG_ah, + CPU_REG_ax, + CPU_REG_bl, + CPU_REG_bh, + CPU_REG_bx, + CPU_REG_cl, + CPU_REG_ch, + CPU_REG_cx, + CPU_REG_dl, + CPU_REG_dh, + CPU_REG_dx, + CPU_REG_sp, + CPU_REG_bp, + CPU_REG_si, + CPU_REG_di, + CPU_REG_es, + CPU_REG_cs, + CPU_REG_ss, + CPU_REG_ds, + CPU_REG_ip, + CPU_REG_f, + CPU_REG_NONE + ); + + type tALU_OP is + ( + ALU_OP_AND, + ALU_OP_OR, + ALU_OP_XOR, + ALU_OP_NOT, + ALU_OP_NEG, + ALU_OP_ADD, + ALU_OP_ADC, + ALU_OP_INC, + ALU_OP_SUB, + ALU_OP_SBB, + ALU_OP_DEC, + ALU_OP_CMP, + ALU_OP_TST, + ALU_OP_ROL, + ALU_OP_ROR, + ALU_OP_RCL, + ALU_OP_RCR, + ALU_OP_SHL, + ALU_OP_SHR, + ALU_OP_SAL, + ALU_OP_SAR, + ALU_OP_MUL, + ALU_OP_MULI, + ALU_OP_DIV, + ALU_OP_DIVI, + ALU_OP_SXT, + ALU_OP_DECADJUST, + ALU_OP_ASCIIADJUST, + ALU_OP_SET1, + ALU_OP_CLR1, + ALU_OP_NOT1, + ALU_OP_TEST1, + ALU_OP_ROR4, + ALU_OP_ROL4, + ALU_OP_NOTHING + ); + + type tBCD_OP is + ( + BCD_OP_ADD, + BCD_OP_SUB, + BCD_OP_CMP + ); + + + -- decodedInstruction + signal opcode : tCPU_Opcode; + signal opcodeNext : tCPU_Opcode; + signal source1 : tOPSOURCE; + signal source2 : tOPSOURCE; + signal optarget : tOPTARGET; + signal optarget2 : tOPTARGET; + signal target_reg : tCPU_REG; + signal target_reg2 : tCPU_REG; + signal target_decode : tCPU_REG; + signal Repeat : std_logic; + signal RepeatNext : std_logic; + signal PrefixIP : unsigned(3 downto 0); + signal segmentaccess : std_logic; + signal prefixSegmentES : std_logic; + signal prefixSegmentCS : std_logic; + signal prefixSegmentSS : std_logic; + signal prefixSegmentDS : std_logic; + signal aluop : tALU_OP; + signal bcdOp : tBCD_OP; + signal useAluResult : std_logic; + signal memSegment : unsigned(15 downto 0); + signal pushlist : std_logic_vector(15 downto 0); + signal poplist : std_logic_vector(15 downto 0); + signal reg_sp_push : unsigned(15 downto 0); + signal fetchedSource1 : std_logic; + signal fetchedSource2 : std_logic; + signal opsign : std_logic; + signal irqBlocked : std_logic; + signal reqModRM : std_logic; + signal repeatZero : std_logic; + signal opsize : std_logic; + signal instantFetch : std_logic; + signal fetch1Val : unsigned(15 downto 0); + signal fetch2Val : unsigned(15 downto 0); + signal memFetchValue1 : unsigned(15 downto 0); + signal memFetchValue2 : unsigned(15 downto 0); + signal MODRM_value_reg : unsigned(15 downto 0); + signal memAddr : unsigned(15 downto 0); + signal immidiate8 : unsigned( 7 downto 0); + signal poptarget : integer range 0 to 14; + signal popval : unsigned(15 downto 0); + signal stringLoad : unsigned(15 downto 0); + signal stringLoad2 : unsigned(15 downto 0); + signal unaligned1 : std_logic; + signal unaligned2 : std_logic; + signal irqrequest : std_logic; + signal irqExtern : std_logic; + signal irqvector : unsigned(9 downto 0); + signal irqIP : unsigned(15 downto 0); + signal irqCS : unsigned(15 downto 0); + signal adjustNegate : std_logic; + signal enterCnt : unsigned(5 downto 0); + signal bcdOffset : unsigned(6 downto 0); + signal bcdAccLow : unsigned(4 downto 0); + signal bcdAccHigh : unsigned(4 downto 0); + signal bcdAcc : unsigned(7 downto 0); + + type tMemAccessType is + ( + MEMACC_NONE, + MEMACC_PREFETCH, + MEMACC_MEMFETCH, + MEMACC_MEMWRITE, + MEMACC_POP, + MEMACC_STRINGLOAD1, + MEMACC_STRINGLOAD2, + MEMACC_IRQFETCH1, + MEMACC_IRQFETCH2 + ); + signal MemAccessType : tMemAccessType; + + type tRegister is record + reg_ax : unsigned(15 downto 0); + reg_cx : unsigned(15 downto 0); + reg_dx : unsigned(15 downto 0); + reg_bx : unsigned(15 downto 0); + reg_sp : unsigned(15 downto 0); + reg_bp : unsigned(15 downto 0); + reg_si : unsigned(15 downto 0); + reg_di : unsigned(15 downto 0); + reg_es : unsigned(15 downto 0); + reg_cs : unsigned(15 downto 0); + reg_ss : unsigned(15 downto 0); + reg_ds : unsigned(15 downto 0); + reg_ip : unsigned(15 downto 0); + FlagCar : std_logic; + FlagPar : std_logic; + FlagHaC : std_logic; + FlagZer : std_logic; + FlagSgn : std_logic; + FlagBrk : std_logic; + FlagIrq : std_logic; + FlagDir : std_logic; + FlagOvf : std_logic; + FlagMod : std_logic; + end record; + signal regs : tRegister; + signal Reg_f : unsigned(15 downto 0); + + -- prefetch + signal prefetchCount : integer range 0 to 15; + signal prefetchBuffer : std_logic_vector(127 downto 0); + signal prefetchAddr : unsigned(19 downto 0); + signal prefetchAddrOld : unsigned(19 downto 0); + signal prefetch1byte : std_logic; + signal clearPrefetch : std_logic; + signal consumePrefetch : integer range 0 to 3; + signal prefetchAllow : std_logic; + signal prefetchDisturb : std_logic; + + -- control and decode + signal delay : integer range 0 to 31; + signal dbuf : integer range 0 to 7; + signal opcodebyte : std_logic_vector(7 downto 0); + signal exOpcodebyte : std_logic_vector(7 downto 0); + signal halt : std_logic := '0'; + signal memFirst : std_logic := '0'; + signal lastaddr : unsigned(19 downto 0); + signal cpu_finished : std_logic := '0'; + signal opstep : integer range 0 to 7; + signal waitexe : std_logic; + signal pushFirst : std_logic; + signal popFirst : std_logic; + signal popUnalnByte : std_logic_vector(7 downto 0); + signal flagCarry : std_logic; + + attribute keep : string; + attribute keep of exOpcodebyte : signal is "true"; + + + -- divider + signal DIVstart : std_logic; + signal DIVdividend : signed(32 downto 0); + signal DIVdivisor : signed(32 downto 0); + signal DIVquotient : signed(32 downto 0); + signal DIVremainder : signed(32 downto 0); + + type arr_opcode IS ARRAY (0 to 255) OF std_logic_vector(7 downto 0); + signal decryption_table : arr_opcode; + attribute ramstyle : string; + --attribute ramstyle OF decryption_table : signal is "logic"; + signal decryption_addr : unsigned(7 downto 0); + signal decryption_q : std_logic_vector(7 downto 0); + + -- savestates + signal SS_CPU1 : std_logic_vector(REG_SAVESTATE_CPU1.upper downto REG_SAVESTATE_CPU1.lower); + signal SS_CPU2 : std_logic_vector(REG_SAVESTATE_CPU2.upper downto REG_SAVESTATE_CPU2.lower); + signal SS_CPU3 : std_logic_vector(REG_SAVESTATE_CPU3.upper downto REG_SAVESTATE_CPU3.lower); + signal SS_CPU4 : std_logic_vector(REG_SAVESTATE_CPU4.upper downto REG_SAVESTATE_CPU4.lower); + signal SS_CPU_BACK1 : std_logic_vector(REG_SAVESTATE_CPU1.upper downto REG_SAVESTATE_CPU1.lower); + signal SS_CPU_BACK2 : std_logic_vector(REG_SAVESTATE_CPU2.upper downto REG_SAVESTATE_CPU2.lower); + signal SS_CPU_BACK3 : std_logic_vector(REG_SAVESTATE_CPU3.upper downto REG_SAVESTATE_CPU3.lower); + signal SS_CPU_BACK4 : std_logic_vector(REG_SAVESTATE_CPU4.upper downto REG_SAVESTATE_CPU4.lower); + + type t_ss_wired_or is array(0 to 3) of std_logic_vector(63 downto 0); + signal ss_wired_or : t_ss_wired_or; + + -- debug + signal executeDone : std_logic := '0'; + signal dma_active_1 : std_logic := '0'; + + signal testcmd : unsigned(31 downto 0); + signal testpcsum : unsigned(63 downto 0); + + +begin + + cpu_idle <= '1' when cpustage = CPUSTAGE_IDLE else '0'; + cpu_halt <= halt; + cpu_irqrequest <= irqrequest; + cpu_prefix <= '1' when PrefixIP > 0 else '0'; + bus_prefetch <= '0' when (prefetchAllow = '0' or prefetchState = PREFETCH_IDLE or prefetchState = PREFETCH_RECEIVE) else '1'; + + canSpeedup <= '1'; + + Reg_f(0 ) <= regs.FlagCar; + Reg_f(1 ) <= '1' ; + Reg_f(2 ) <= regs.FlagPar; + Reg_f(3 ) <= '0' ; + Reg_f(4 ) <= regs.FlagHaC; + Reg_f(5 ) <= '0' ; + Reg_f(6 ) <= regs.FlagZer; + Reg_f(7 ) <= regs.FlagSgn; + Reg_f(8 ) <= regs.FlagBrk; + Reg_f(9 ) <= regs.FlagIrq; + Reg_f(10) <= regs.FlagDir; + Reg_f(11) <= regs.FlagOvf; + Reg_f(12) <= '1' ; + Reg_f(13) <= '1' ; + Reg_f(14) <= '1' ; + Reg_f(15) <= regs.FlagMod; + + -- savestate + iSS_CPU1 : entity work.eReg_SS generic map ( REG_SAVESTATE_CPU1 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, ss_wired_or(0), SS_CPU_BACK1, SS_CPU1); + iSS_CPU2 : entity work.eReg_SS generic map ( REG_SAVESTATE_CPU2 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, ss_wired_or(1), SS_CPU_BACK2, SS_CPU2); + iSS_CPU3 : entity work.eReg_SS generic map ( REG_SAVESTATE_CPU3 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, ss_wired_or(2), SS_CPU_BACK3, SS_CPU3); + iSS_CPU4 : entity work.eReg_SS generic map ( REG_SAVESTATE_CPU4 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, ss_wired_or(3), SS_CPU_BACK4, SS_CPU4); + + process (ss_wired_or) + variable wired_or : std_logic_vector(63 downto 0); + begin + wired_or := ss_wired_or(0); + for i in 1 to (ss_wired_or'length - 1) loop + wired_or := wired_or or ss_wired_or(i); + end loop; + SSBUS_Dout <= wired_or; + end process; + + SS_CPU_BACK1(15 downto 0) <= std_logic_vector(regs.reg_ip); + SS_CPU_BACK1(31 downto 16) <= std_logic_vector(regs.reg_ax); + SS_CPU_BACK1(47 downto 32) <= std_logic_vector(regs.reg_cx); + SS_CPU_BACK1(63 downto 48) <= std_logic_vector(regs.reg_dx); + SS_CPU_BACK2(15 downto 0) <= std_logic_vector(regs.reg_bx); + SS_CPU_BACK2(31 downto 16) <= std_logic_vector(regs.reg_sp); + SS_CPU_BACK2(47 downto 32) <= std_logic_vector(regs.reg_bp); + SS_CPU_BACK2(63 downto 48) <= std_logic_vector(regs.reg_si); + SS_CPU_BACK3(15 downto 0) <= std_logic_vector(regs.reg_di); + SS_CPU_BACK3(31 downto 16) <= std_logic_vector(regs.reg_es); + SS_CPU_BACK3(47 downto 32) <= std_logic_vector(regs.reg_cs); + SS_CPU_BACK3(63 downto 48) <= std_logic_vector(regs.reg_ss); + SS_CPU_BACK4(15 downto 0) <= std_logic_vector(regs.reg_ds); + SS_CPU_BACK4(31 downto 16) <= std_logic_vector(Reg_f); + + decryption_addr <= secure_addr when secure_wr = '1' else + unsigned(prefetchBuffer(15 downto 8)) when consumePrefetch = 1 else unsigned(prefetchBuffer(7 downto 0)); + process (clk) begin + if falling_edge(clk) then + decryption_q <= decryption_table(to_integer(decryption_addr)); + end if; + end process; + + process (clk) + variable varPrefetchCount : integer range 0 to 15; + variable varprefetchBuffer : std_logic_vector(127 downto 0); + variable isPrefix : std_logic; + variable usePrefix : std_logic; + variable source1Val : unsigned(15 downto 0); + variable source2Val : unsigned(15 downto 0); + variable op2value : unsigned(15 downto 0); + variable resultval : unsigned(15 downto 0); + variable target : tCPU_REG; + variable result : unsigned(15 downto 0); + variable result17 : unsigned(16 downto 0); + variable result32 : unsigned(31 downto 0); + variable result8 : unsigned(7 downto 0); + variable result8h : unsigned(7 downto 0); + variable result9 : unsigned(8 downto 0); + variable newZero : std_logic; + variable newParity : std_logic; + variable newSign : std_logic; + variable carryWork1 : std_logic; + variable carryWork2 : std_logic; + variable cond : std_logic; + variable exeDone : std_logic; + variable pushValue : std_logic_vector(15 downto 0); + variable pushindex : integer range 0 to 15; + variable popindex : integer range 0 to 15; + variable popValue : std_logic_vector(15 downto 0); + variable popDone : std_logic; + variable MODRM_mem : unsigned(2 downto 0); + variable MODRM_reg : unsigned(2 downto 0); + variable MODRM_mod : unsigned(1 downto 0); + variable varoptarget : tOPTARGET; + variable varsource1 : tOPSOURCE; + variable varsource2 : tOPSOURCE; + variable varfetchedSource1 : std_logic; + variable varfetchedSource2 : std_logic; + variable vartarget_reg : tCPU_REG; + variable varmemSegment : unsigned(15 downto 0); + variable varmemaddr : unsigned(15 downto 0); + variable varpushlist : std_logic_vector(15 downto 0); + variable fetchedRMMODData : unsigned(15 downto 0); + variable newDelay : integer range 0 to 31; + variable newBuf : integer range 0 to 7; + variable newModDelay : integer range 0 to 31; + variable newExeDelay : integer range 0 to 31; + variable endRepeat : std_logic; + variable newRepeat : std_logic; + variable jumpNow : std_logic; + variable jumpAddr : unsigned(15 downto 0); + variable bcdResultLow : unsigned(4 downto 0); + variable bcdResultHigh : unsigned(4 downto 0); + variable wordAligned : std_logic; + begin + if rising_edge(clk) then + + DIVstart <= '0'; + cpu_done <= '0'; + + bus_read <= '0'; + bus_write <= '0'; + + if (ce_4x = '1') then + clearPrefetch <= '0'; + consumePrefetch <= 0; + end if; + + if (ce = '1') then + prefetchAllow <= '1'; + RegBus_wren <= '0'; + RegBus_rden <= '0'; + irqrequest_ack <= '0'; + irqrequest_fini <= '0'; + end if; + + if (secure_wr = '1') then + decryption_table(to_integer(decryption_addr)) <= secure_data; + end if; + --if (testpcsum(63) = '1' and testcmd(31) = '1') then + -- DIVstart <= '1'; + --end if; + + if (sleep_savestate = '1') then + prefetchDisturb <= '1'; + end if; + + if (reset = '1') then + + regs.reg_ip <= x"0000"; + regs.reg_ax <= x"0000"; + regs.reg_cx <= x"0000"; + regs.reg_dx <= x"0000"; + regs.reg_bx <= x"0000"; + regs.reg_sp <= x"2000"; + regs.reg_bp <= x"0000"; + regs.reg_si <= x"0000"; + regs.reg_di <= x"0000"; + regs.reg_es <= x"0000"; + regs.reg_cs <= x"FFFF"; + regs.reg_ss <= x"0000"; + regs.reg_ds <= x"0000"; + + regs.FlagCar <= '0'; + regs.FlagPar <= '0'; + regs.FlagHaC <= '0'; + regs.FlagZer <= '0'; + regs.FlagSgn <= '0'; + regs.FlagBrk <= '0'; + regs.FlagIrq <= '0'; + regs.FlagDir <= '0'; + regs.FlagOvf <= '0'; + regs.FlagMod <= '1'; + + halt <= '0'; + cpustage <= CPUSTAGE_IDLE; + opcodebyte <= (others => '0'); + exOpcodebyte <= (others => '0'); + + clearPrefetch <= '1'; + + delay <= 8; -- fill prefetch buffer + dbuf <= 0; + + repeat <= '0'; + repeatNext <= '0'; + + irqrequest <= '0'; + irqBlocked <= '0'; + irqrequest_ack <= '0'; + + prefixSegmentES <= '0'; + prefixSegmentCS <= '0'; + prefixSegmentSS <= '0'; + prefixSegmentDS <= '0'; + + prefixIP <= (others => '0'); + + testcmd <= (others => '0'); + testpcsum <= (others => '0'); + + RegBus_wren <= '0'; + RegBus_rden <= '0'; + + elsif (ce_4x = '1') then + + dma_active_1 <= dma_active; + + if (ce = '1' and irqrequest_in = '1' and irqBlocked = '0' and cpustage = CPUSTAGE_IDLE) then + halt <= '0'; + end if; + + if (cpu_finished = '1' and dma_active = '0' and dma_active_1 = '1') then + cpu_finished <= '0'; + cpu_done <= '1'; + end if; + + if (dma_active = '1') then + delay <= 0; + end if; + + if (ce = '1' and delay > 0) then + + delay <= delay - 1; + + if (delay = 1 and cpu_finished = '1' and dma_active = '0') then + cpu_finished <= '0'; + cpu_done <= '1'; + end if; + + else + + case (cpustage) is + + when CPUSTAGE_IDLE => + if (ce = '1' and sdma_request = '0') then + + if (irqrequest = '1') then + irqrequest <= '0'; + repeat <= '0'; + delay <= INTACK_DELAY; + cpustage <= CPUSTAGE_IRQVECTOR_REQ; + pushlist <= REGPOS_f or REGPOS_cs or REGPOS_ip; + poplist <= (others => '0'); + pushFirst <= '1'; + opcode <= OP_IRQ; + aluop <= ALU_OP_NOTHING; + source1 <= OPSOURCE_IRQVECTOR; + source2 <= OPSOURCE_IRQVECTOR; + fetchedSource1 <= '0'; + fetchedSource2 <= '0'; + memFirst <= '1'; + + elsif (irqrequest_in = '1' and irqBlocked = '0' and regs.FlagIrq = '1') then + + irqrequest <= '1'; + irqrequest_ack <= '1'; + irqExtern <= '1'; + halt <= '0'; + + elsif (halt = '1') then + null; + elsif (prefetchCount > 3 + consumePrefetch) then + testpcsum <= testpcsum + regs.reg_ip; + testcmd <= testcmd + 1; + + if (repeat = '0') then + exOpcodebyte <= x"00"; + if (consumePrefetch = 1) then + if (secure) then + opcodebyte <= decryption_q; + else + opcodebyte <= prefetchBuffer(15 downto 8); + end if; + else + if (secure) then + opcodebyte <= decryption_q; + else + opcodebyte <= prefetchBuffer(7 downto 0); + end if; + end if; + if (repeatNext = '0') then + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + PrefixIP <= (others => '0'); + end if; + end if; + cpustage <= CPUSTAGE_DECODEOP; + + if (dBuf > 6) then + dBuf <= 6; + end if; + + end if; + + end if; + + when CPUSTAGE_DECODEOP => + + newRepeat := '0'; + if (repeatNext = '1') then + if (opcodebyte = x"26" or opcodebyte = x"2E" or opcodebyte = x"36" or opcodebyte = x"3E") then + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + else + RepeatNext <= '0'; + Repeat <= '1'; + newRepeat := '1'; + end if; + end if; + + opcode <= OP_INVALID; + opcodeNext <= OP_INVALID; + source1 <= OPSOURCE_INVALID; + source2 <= OPSOURCE_INVALID; + optarget <= OPTARGET_NONE; + optarget2 <= OPTARGET_NONE; + target_reg <= CPU_REG_NONE; + target_reg2 <= CPU_REG_NONE; + segmentaccess <= '0'; + aluop <= ALU_OP_NOTHING; + useAluResult <= '0'; + memSegment <= Regs.reg_ds; + pushlist <= (others => '0'); + poplist <= (others => '0'); + reg_sp_push <= Regs.reg_sp; + instantFetch <= '0'; + fetchedSource1 <= '0'; + fetchedSource2 <= '0'; + opsign <= '0'; + irqBlocked <= '0'; + unaligned1 <= '0'; + unaligned2 <= '0'; + memFirst <= '1'; + opstep <= 0; + waitexe <= '0'; + enterCnt <= (others => '0'); + irqExtern <= '0'; + pushFirst <= '1'; + popFirst <= '1'; + flagCarry <= regs.FlagCar; + + isPrefix := '0'; + usePrefix := '0'; + + newDelay := 0; + newBuf := dbuf; + + case (opcodebyte) is + + when x"00" => opcode <= OP_MOVMEM; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= '0'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"01" => opcode <= OP_MOVMEM; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= '1'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"02" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"03" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"04" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= '0'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; + when x"05" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= '1'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; + + when x"06" => pushlist <= REGPOS_es; cpustage <= CPUSTAGE_CHECKDATAREADY; + when x"07" => poplist <= REGPOS_es; cpustage <= CPUSTAGE_CHECKDATAREADY; newDelay := 1; + + when x"08" => opcode <= OP_MOVMEM; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= '0'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"09" => opcode <= OP_MOVMEM; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= '1'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"0A" => opcode <= OP_MOVREG; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"0B" => opcode <= OP_MOVREG; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"0C" => opcode <= OP_MOVREG; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= '0'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; + when x"0D" => opcode <= OP_MOVREG; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= '1'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; + + when x"0E" => pushlist <= REGPOS_cs; cpustage <= CPUSTAGE_CHECKDATAREADY; + when x"0F" => + exOpcodebyte <= prefetchBuffer(15 downto 8); + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + case (prefetchBuffer(15 downto 8)) is + -- TEST1 + when x"10" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_NOP; aluop <= ALU_OP_TEST1; opsize <= '0'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; + when x"11" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_NOP; aluop <= ALU_OP_TEST1; opsize <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; + when x"18" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_NOP; aluop <= ALU_OP_TEST1; opsize <= '0'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; + when x"19" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_NOP; aluop <= ALU_OP_TEST1; opsize <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; + -- CLR1 + when x"12" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_CLR1; opsize <= '0'; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"13" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_CLR1; opsize <= '1'; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"1a" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_CLR1; opsize <= '0'; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"1b" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_CLR1; opsize <= '1'; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + -- SET1 + when x"14" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_SET1; opsize <= '0'; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"15" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_SET1; opsize <= '1'; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"1c" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_SET1; opsize <= '0'; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"1d" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_SET1; opsize <= '1'; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + -- NOT1 + when x"16" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_NOT1; opsize <= '0'; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"17" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_NOT1; opsize <= '1'; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"1e" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_NOT1; opsize <= '0'; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + when x"1f" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_NOT1; opsize <= '1'; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + -- ADD4S + when x"20" => cpustage <= CPUSTAGE_EXECUTE; opcode <= OP_BCDSTRING; bcdOp <= BCD_OP_ADD; bcdOffset <= (others => '0'); regs.FlagCar <= '0'; regs.FlagZer <= '1'; + -- SUB4S + when x"22" => cpustage <= CPUSTAGE_EXECUTE; opcode <= OP_BCDSTRING; bcdOp <= BCD_OP_SUB; bcdOffset <= (others => '0'); regs.FlagCar <= '0'; regs.FlagZer <= '1'; + -- CMP4S + when x"26" => cpustage <= CPUSTAGE_EXECUTE; opcode <= OP_BCDSTRING; bcdOp <= BCD_OP_CMP; bcdOffset <= (others => '0'); regs.FlagCar <= '0'; regs.FlagZer <= '1'; + -- ROL4 + when x"28" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_ROL4; opsize <= '0'; useAluResult <= '1'; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + -- ROR4 + when x"2a" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_ROR4; opsize <= '0'; useAluResult <= '1'; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; + -- INS + when x"31" => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; + -- EXT + when x"33" => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; + -- INS + when x"39" => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; + -- FINT + when x"92" => newDelay := 2; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; irqrequest_fini <= '1'; + -- BRKEM + when x"ff" => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; + + when others => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; + end case; + + + when x"10" => opcode <= OP_MOVMEM; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= '0'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"11" => opcode <= OP_MOVMEM; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= '1'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"12" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"13" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"14" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= '0'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; + when x"15" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= '1'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; + + when x"16" => pushlist <= REGPOS_ss; cpustage <= CPUSTAGE_CHECKDATAREADY; + when x"17" => poplist <= REGPOS_ss; cpustage <= CPUSTAGE_CHECKDATAREADY; newDelay := 1; irqBlocked <= '1'; + + when x"18" => opcode <= OP_MOVMEM; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= '0'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"19" => opcode <= OP_MOVMEM; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= '1'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"1A" => opcode <= OP_MOVREG; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"1B" => opcode <= OP_MOVREG; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"1C" => opcode <= OP_MOVREG; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= '0'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; + when x"1D" => opcode <= OP_MOVREG; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= '1'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; + + when x"1E" => pushlist <= REGPOS_ds; cpustage <= CPUSTAGE_CHECKDATAREADY; + when x"1F" => poplist <= REGPOS_ds; cpustage <= CPUSTAGE_CHECKDATAREADY; newDelay := 1; + + when x"20" => opcode <= OP_MOVMEM; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= '0'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"21" => opcode <= OP_MOVMEM; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= '1'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"22" => opcode <= OP_MOVREG; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"23" => opcode <= OP_MOVREG; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"24" => opcode <= OP_MOVREG; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= '0'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; + when x"25" => opcode <= OP_MOVREG; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= '1'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; + + when x"26" => prefixSegmentES <= '1'; isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; cpu_done <= '1'; newBuf := dbuf + 1; cpustage <= CPUSTAGE_IDLE; + + when x"27" => opcode <= OP_MOVREG; aluop <= ALU_OP_DECADJUST; useAluResult <= '1'; newDelay := 9; opsize <= '0'; cpustage <= CPUSTAGE_EXECUTE; target_decode <= CPU_REG_al; optarget <= OPTARGET_DECODE; adjustNegate <= '0'; + + when x"28" => opcode <= OP_MOVMEM; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= '0'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"29" => opcode <= OP_MOVMEM; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= '1'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"2A" => opcode <= OP_MOVREG; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"2B" => opcode <= OP_MOVREG; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"2C" => opcode <= OP_MOVREG; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= '0'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; + when x"2D" => opcode <= OP_MOVREG; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= '1'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; + + when x"2E" => prefixSegmentCS <= '1'; isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; cpu_done <= '1'; newBuf := dbuf + 1; cpustage <= CPUSTAGE_IDLE; + + when x"2F" => opcode <= OP_MOVREG; aluop <= ALU_OP_DECADJUST; useAluResult <= '1'; newDelay := 10; opsize <= '0'; cpustage <= CPUSTAGE_EXECUTE; target_decode <= CPU_REG_al; optarget <= OPTARGET_DECODE; adjustNegate <= '1'; + + when x"30" => opcode <= OP_MOVMEM; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= '0'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"31" => opcode <= OP_MOVMEM; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= '1'; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; + when x"32" => opcode <= OP_MOVREG; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"33" => opcode <= OP_MOVREG; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"34" => opcode <= OP_MOVREG; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= '0'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; + when x"35" => opcode <= OP_MOVREG; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= '1'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; + + when x"36" => prefixSegmentSS <= '1'; isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; cpu_done <= '1'; newBuf := dbuf + 1; cpustage <= CPUSTAGE_IDLE; + + when x"37" => opcode <= OP_MOVREG; aluop <= ALU_OP_ASCIIADJUST; useAluResult <= '1'; newDelay := 8; opsize <= '1'; cpustage <= CPUSTAGE_EXECUTE; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; adjustNegate <= '0'; + + when x"38" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= '0'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; + when x"39" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= '1'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; + when x"3A" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; + when x"3B" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; + when x"3C" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= '0'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; + when x"3D" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= '1'; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; + + when x"3E" => prefixSegmentDS <= '1'; isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; cpu_done <= '1'; newBuf := dbuf + 1; cpustage <= CPUSTAGE_IDLE; + + when x"3F" => opcode <= OP_MOVREG; aluop <= ALU_OP_ASCIIADJUST; useAluResult <= '1'; newDelay := 8; opsize <= '1'; cpustage <= CPUSTAGE_EXECUTE; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; adjustNegate <= '1'; + + when x"40" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_ax; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"41" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_cx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_cx; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"42" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_dx; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"43" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_bx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_bx; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"44" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_sp; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_sp; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"45" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_bp; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_bp; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"46" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_si; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_si; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"47" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_di; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_di; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"48" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_ax; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"49" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_cx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_cx; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"4A" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_dx; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"4B" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_bx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_bx; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"4C" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_sp; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_sp; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"4D" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_bp; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_bp; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"4E" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_si; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_si; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + when x"4F" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_di; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_di; optarget <= OPTARGET_DECODE; opsize <= '1'; useAluResult <= '1'; + + when x"50" => pushlist <= REGPOS_ax; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"51" => pushlist <= REGPOS_cx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"52" => pushlist <= REGPOS_dx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"53" => pushlist <= REGPOS_bx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"54" => pushlist <= REGPOS_sp; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"55" => pushlist <= REGPOS_bp; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"56" => pushlist <= REGPOS_si; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"57" => pushlist <= REGPOS_di; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"58" => poplist <= REGPOS_ax; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"59" => poplist <= REGPOS_cx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"5A" => poplist <= REGPOS_dx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"5B" => poplist <= REGPOS_bx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"5C" => poplist <= REGPOS_sp; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"5D" => poplist <= REGPOS_bp; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"5E" => poplist <= REGPOS_si; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + when x"5F" => poplist <= REGPOS_di; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; + + when x"60" => pushlist <= REGPOS_ax or REGPOS_cx or REGPOS_dx or REGPOS_bx or REGPOS_sp or REGPOS_bp or REGPOS_si or REGPOS_di; cpustage <= CPUSTAGE_CHECKDATAREADY; + when x"61" => poplist <= REGPOS_ax or REGPOS_cx or REGPOS_dx or REGPOS_bx or REGPOS_bp or REGPOS_si or REGPOS_di; cpustage <= CPUSTAGE_CHECKDATAREADY; newDelay := 1; + + when x"62" => opcode <= OP_BOUND; newDelay := 4; opsize <= '1'; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MEM; + + -- when x"63" => ? + -- when x"64" => repnc + -- when x"65" => repc + -- when x"66" => fpo2 + -- when x"67" => fpo2 + + when x"68" => pushlist <= REGPOS_imm; cpustage <= CPUSTAGE_PUSH; opsize <= '1'; newBuf := dbuf + 1; fetch1Val <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; + when x"69" => opcode <= OP_MOVREG; aluop <= ALU_OP_MULI; newDelay := 3; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + when x"6A" => pushlist <= REGPOS_imm; cpustage <= CPUSTAGE_PUSH; opsize <= '0'; newBuf := dbuf + 1; fetch1Val <= x"00" & unsigned(prefetchBuffer(15 downto 8)); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; + when x"6B" => opcode <= OP_MOVREG; aluop <= ALU_OP_MULI; newDelay := 3; useAluResult <= '1'; opsize <= '1'; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; + + when x"6C" => opcode <= OP_OPIN; newDelay := 5; opcodeNext <= OP_STRINGSTORE; opsize <= '0'; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_MEM; + when x"6D" => opcode <= OP_OPIN; newDelay := 4; opcodeNext <= OP_STRINGSTORE; opsize <= '1'; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_MEM; + when x"6E" => opcode <= OP_STRINGLOAD; newDelay := 5; opcodeNext <= OP_OPOUT; opsize <= '0'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_STRINGLOAD1; + when x"6F" => opcode <= OP_STRINGLOAD; newDelay := 1; opcodeNext <= OP_OPOUT; opsize <= '1'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_STRINGLOAD1; + + when x"70" | x"71" | x"72" | x"73" | x"74" | x"75" | x"76" | x"77" | x"78" | x"79" | x"7a" | x"7b" | x"7c" | x"7d" | x"7e" | x"7f" => + opcode <= OP_JUMPIF; source1 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA1_8; + + when x"80" => opcode <= OP_MEMIMM1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; optarget <= OPTARGET_MEM; useAluResult <= '1'; opsize <= '0'; opsign <= '0'; + when x"81" => opcode <= OP_MEMIMM1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE16; optarget <= OPTARGET_MEM; useAluResult <= '1'; opsize <= '1'; opsign <= '0'; + when x"82" => opcode <= OP_MEMIMM1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; optarget <= OPTARGET_MEM; useAluResult <= '1'; opsize <= '0'; opsign <= '1'; + when x"83" => opcode <= OP_MEMIMM1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; optarget <= OPTARGET_MEM; useAluResult <= '1'; opsize <= '1'; opsign <= '1'; + + when x"84" => opcode <= OP_NOP; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; aluop <= ALU_OP_TST; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; + when x"85" => opcode <= OP_NOP; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; aluop <= ALU_OP_TST; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; + + when x"86" => opcode <= OP_MOVMEM; newDelay := 2; opcodeNext <= OP_MOVREG; opsize <= '0'; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; optarget2 <= OPTARGET_MODRM_REG; + when x"87" => opcode <= OP_MOVMEM; newDelay := 2; opcodeNext <= OP_MOVREG; opsize <= '1'; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; optarget2 <= OPTARGET_MODRM_REG; + + when x"88" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; source1 <= OPSOURCE_MODRM_REG; optarget <= OPTARGET_MEM; + when x"89" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; optarget <= OPTARGET_MEM; + when x"8A" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; newBuf := dbuf + 1; + when x"8B" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; newBuf := dbuf + 1; + + when x"8C" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MODRM_REG; segmentaccess <= '1'; optarget <= OPTARGET_MEM; irqBlocked <= '1'; + + when x"8D" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MODRM_ADDR; optarget <= OPTARGET_MODRM_REG; + + when x"8E" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; segmentaccess <= '1'; newDelay := 1; + + when x"8F" => opcode <= OP_MOVMEM; poplist <= REGPOS_mem; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_POPVALUE; optarget <= OPTARGET_MEM; opsize <= '1'; newDelay := 1; + + -- when x"90" => NOP + + when x"91" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; + when x"92" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; + when x"93" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; + when x"94" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; + when x"95" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; + when x"96" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; + when x"97" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; + + when x"98" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_SXT; source1 <= OPSOURCE_ACC; opsize <= '1'; useAluResult <= '1'; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; + when x"99" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_SXT; source1 <= OPSOURCE_ACC; opsize <= '1'; useAluResult <= '1'; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_dx; + + when x"9A" => opcode <= OP_JUMPFAR; newDelay := 4; cpustage <= CPUSTAGE_FETCHDATA1_16; pushlist <= REGPOS_cs or REGPOS_ip; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_FETCHVALUE16; + + -- when x"9B" => wait + + when x"9C" => pushlist <= REGPOS_f; cpustage <= CPUSTAGE_CHECKDATAREADY; + when x"9D" => poplist <= REGPOS_f; cpustage <= CPUSTAGE_CHECKDATAREADY; irqBlocked <= '1'; newDelay := 1; + + when x"9E" => opcode <= OP_FLAGSFROMACC; newDelay := 3; cpustage <= CPUSTAGE_EXECUTE; + when x"9F" => opcode <= OP_FLAGSTOACC; newDelay := 1; cpustage <= CPUSTAGE_EXECUTE; + + when x"A0" => opcode <= OP_MOVREG; newBuf := dbuf + 1; memAddr <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; cpustage <= CPUSTAGE_CHECKDATAREADY; opsize <= '0'; source1 <= OPSOURCE_MEM; target_decode <= CPU_REG_al; optarget <= OPTARGET_DECODE; + when x"A1" => opcode <= OP_MOVREG; newBuf := dbuf + 1; memAddr <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; cpustage <= CPUSTAGE_CHECKDATAREADY; opsize <= '1'; source1 <= OPSOURCE_MEM; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; + when x"A2" => opcode <= OP_MOVMEM; memAddr <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; cpustage <= CPUSTAGE_CHECKDATAREADY; opsize <= '0'; source1 <= OPSOURCE_ACC; optarget <= OPTARGET_MEM; + when x"A3" => opcode <= OP_MOVMEM; memAddr <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; cpustage <= CPUSTAGE_CHECKDATAREADY; opsize <= '1'; source1 <= OPSOURCE_ACC; optarget <= OPTARGET_MEM; + + when x"A4" => opcode <= OP_STRINGLOAD; newDelay := 3; opcodeNext <= OP_STRINGSTORE; opsize <= '0'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_STRINGLOAD1; usePrefix := '1'; + when x"A5" => opcode <= OP_STRINGLOAD; newDelay := 1; opcodeNext <= OP_STRINGSTORE; opsize <= '1'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_STRINGLOAD1; usePrefix := '1'; + + when x"A6" => opcode <= OP_STRINGLOAD; newDelay := 2; opcodeNext <= OP_STRINGCOMPARE; opsize <= '0'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_STRINGLOAD1; source2 <= OPSOURCE_STRINGLOAD2; usePrefix := '1'; + when x"A7" => opcode <= OP_STRINGLOAD; opcodeNext <= OP_STRINGCOMPARE; opsize <= '1'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_STRINGLOAD1; source2 <= OPSOURCE_STRINGLOAD2; usePrefix := '1'; + + when x"A8" => opcode <= OP_NOP; opsize <= '0'; cpustage <= CPUSTAGE_FETCHDATA1_8 ; aluop <= ALU_OP_TST; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_ACC; instantFetch <= '1'; + when x"A9" => opcode <= OP_NOP; opsize <= '1'; cpustage <= CPUSTAGE_FETCHDATA1_16; aluop <= ALU_OP_TST; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_ACC; instantFetch <= '1'; + + when x"AA" => opcode <= OP_STRINGSTORE; newDelay := 2; opsize <= '0'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_ACC; usePrefix := '1'; + when x"AB" => opcode <= OP_STRINGSTORE; newDelay := 1; opsize <= '1'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_ACC; usePrefix := '1'; + + when x"AC" => opcode <= OP_STRINGLOAD; newDelay := 1; opcodeNext <= OP_MOVREG; opsize <= '0'; source1 <= OPSOURCE_STRINGLOAD1; cpustage <= CPUSTAGE_EXECUTE; usePrefix := '1'; target_decode <= CPU_REG_al; optarget <= OPTARGET_DECODE; + when x"AD" => opcode <= OP_STRINGLOAD; opcodeNext <= OP_MOVREG; opsize <= '1'; source1 <= OPSOURCE_STRINGLOAD1; cpustage <= CPUSTAGE_EXECUTE; usePrefix := '1'; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; + + when x"AE" => opcode <= OP_STRINGCOMPARE; newDelay := 1; opsize <= '0'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_STRINGLOAD2; usePrefix := '1'; + when x"AF" => opcode <= OP_STRINGCOMPARE; opsize <= '1'; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_STRINGLOAD2; usePrefix := '1'; + + when x"B0" => opcode <= OP_MOVREG; target_decode <= CPU_REG_al; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= '0'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B1" => opcode <= OP_MOVREG; target_decode <= CPU_REG_cl; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= '0'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B2" => opcode <= OP_MOVREG; target_decode <= CPU_REG_dl; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= '0'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B3" => opcode <= OP_MOVREG; target_decode <= CPU_REG_bl; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= '0'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B4" => opcode <= OP_MOVREG; target_decode <= CPU_REG_ah; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= '0'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B5" => opcode <= OP_MOVREG; target_decode <= CPU_REG_ch; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= '0'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B6" => opcode <= OP_MOVREG; target_decode <= CPU_REG_dh; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= '0'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B7" => opcode <= OP_MOVREG; target_decode <= CPU_REG_bh; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= '0'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B8" => opcode <= OP_MOVREG; target_decode <= CPU_REG_ax; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= '1'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"B9" => opcode <= OP_MOVREG; target_decode <= CPU_REG_cx; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= '1'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"BA" => opcode <= OP_MOVREG; target_decode <= CPU_REG_dx; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= '1'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"BB" => opcode <= OP_MOVREG; target_decode <= CPU_REG_bx; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= '1'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"BC" => opcode <= OP_MOVREG; target_decode <= CPU_REG_sp; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= '1'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"BD" => opcode <= OP_MOVREG; target_decode <= CPU_REG_bp; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= '1'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"BE" => opcode <= OP_MOVREG; target_decode <= CPU_REG_si; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= '1'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + when x"BF" => opcode <= OP_MOVREG; target_decode <= CPU_REG_di; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= '1'; optarget <= OPTARGET_DECODE; instantFetch <= '1'; + + when x"C0" => opcode <= OP_MEMIMM2; newDelay := 2; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; useAluResult <= '1'; optarget <= OPTARGET_MEM; + when x"C1" => opcode <= OP_MEMIMM2; newDelay := 2; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; useAluResult <= '1'; optarget <= OPTARGET_MEM; + + when x"C2" => opcode <= OP_RETURNFAR; opsize <= '1'; source1 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA1_16; newDelay := 1; poplist <= REGPOS_ip; + + when x"C3" => newDelay := 1; poplist <= REGPOS_ip; cpustage <= CPUSTAGE_CHECKDATAREADY; + + when x"C4" => opcode <= OP_MOVREG; newDelay := 3; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; + when x"C5" => opcode <= OP_MOVREG; newDelay := 3; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; + + when x"C6" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; source1 <= OPSOURCE_FETCHVALUE8; optarget <= OPTARGET_MEM; newBuf := dbuf + 1; + when x"C7" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_FETCHVALUE16; optarget <= OPTARGET_MEM; newBuf := dbuf + 1; + + when x"C8" => opcode <= OP_ENTER; cpustage <= CPUSTAGE_FETCHDATA1_16; newDelay := 6; pushlist <= REGPOS_bp; opsize <= '0'; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_FETCHVALUE8; + when x"C9" => opcode <= OP_MOVREG; regs.reg_sp <= regs.reg_bp; poplist <= REGPOS_MEM; cpustage <= CPUSTAGE_POP_REQ; source1 <= OPSOURCE_POPVALUE; target_decode <= CPU_REG_bp; optarget <= OPTARGET_DECODE; + + when x"CA" => opcode <= OP_RETURNFAR; opsize <= '1'; source1 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA1_16; poplist <= REGPOS_cs or REGPOS_ip; + + when x"CB" => newDelay := 2; poplist <= REGPOS_cs or REGPOS_ip; cpustage <= CPUSTAGE_CHECKDATAREADY; + + when x"CC" => opcode <= OP_IRQREQUEST; newDelay := 9; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"03"; + when x"CD" => opcode <= OP_IRQREQUEST; newDelay := 10; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; + when x"CE" => opcode <= OP_IRQREQUEST; newDelay := 6; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"04"; + + when x"CF" => newDelay := 3; poplist <= REGPOS_cs or REGPOS_ip or REGPOS_f; cpustage <= CPUSTAGE_CHECKDATAREADY; irqBlocked <= '1'; + + when x"D0" => opcode <= OP_MEMIMM2; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_IMMIDIATE; useAluResult <= '1'; optarget <= OPTARGET_MEM; newDelay := 1; immidiate8 <= x"01"; + when x"D1" => opcode <= OP_MEMIMM2; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_IMMIDIATE; useAluResult <= '1'; optarget <= OPTARGET_MEM; newDelay := 1; immidiate8 <= x"01"; + when x"D2" => opcode <= OP_MEMIMM2; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_IMMIDIATE; useAluResult <= '1'; optarget <= OPTARGET_MEM; newDelay := 3; immidiate8 <= regs.reg_cx(7 downto 0); + when x"D3" => opcode <= OP_MEMIMM2; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_IMMIDIATE; useAluResult <= '1'; optarget <= OPTARGET_MEM; newDelay := 3; immidiate8 <= regs.reg_cx(7 downto 0); + + when x"D4" => opcode <= OP_MULADJUST; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; newDelay := 2; opsize <= '1'; + when x"D5" => opcode <= OP_DIVADJUST; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; newDelay := 4; opsize <= '1'; + + when x"D6" | x"D7" => + opcode <= OP_MOVREG; cpustage <= CPUSTAGE_CHECKDATAREADY; source1 <= OPSOURCE_MEM; opsize <= '0'; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; newDelay := 3; + memSegment <= regs.reg_ds; + if (prefixSegmentES = '1') then memSegment <= regs.reg_es; end if; + if (prefixSegmentCS = '1') then memSegment <= regs.reg_cs; end if; + if (prefixSegmentSS = '1') then memSegment <= regs.reg_ss; end if; + if (prefixSegmentDS = '1') then memSegment <= regs.reg_ds; end if; + memAddr <= regs.reg_bx + regs.reg_ax(7 downto 0); + if (opcodebyte = x"D6") then newDelay := 6; else newDelay := 3; end if; + + -- when x"D8" => fpo1 + -- when x"D9" => fpo1 + -- when x"DA" => fpo1 + -- when x"DB" => fpo1 + -- when x"DC" => fpo1 + -- when x"DD" => fpo1 + -- when x"DE" => fpo1 + -- when x"DF" => fpo1 + + when x"E0" => opcode <= OP_JUMPIF; newDelay := 2; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; + when x"E1" => opcode <= OP_JUMPIF; newDelay := 2; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; + when x"E2" => opcode <= OP_JUMPIF; newDelay := 1; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; + when x"E3" => opcode <= OP_JUMPIF; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; + + when x"E4" => opcode <= OP_OPIN; newDelay := 5; cpustage <= CPUSTAGE_FETCHDATA1_8; opsize <= '0'; source1 <= OPSOURCE_FETCHVALUE8; + when x"E5" => opcode <= OP_OPIN; newDelay := 4; cpustage <= CPUSTAGE_FETCHDATA1_8; opsize <= '1'; source1 <= OPSOURCE_FETCHVALUE8; + when x"E6" => opcode <= OP_OPOUT; newDelay := 4; cpustage <= CPUSTAGE_FETCHDATA1_8; opsize <= '0'; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_ACC; + when x"E7" => opcode <= OP_OPOUT; newDelay := 3; cpustage <= CPUSTAGE_FETCHDATA1_8; opsize <= '1'; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_ACC; + + when x"E8" => opcode <= OP_JUMP; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; pushlist <= REGPOS_ip; + when x"E9" => opcode <= OP_JUMP; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; + when x"EA" => opcode <= OP_JUMPFAR; newDelay := 3; opsize <= '1'; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_FETCHVALUE16; + when x"EB" => opcode <= OP_JUMPIF; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; + + when x"EC" => opcode <= OP_OPIN; newDelay := 4; cpustage <= CPUSTAGE_EXECUTE; opsize <= '0'; source1 <= OPSOURCE_REG_dx; + when x"ED" => opcode <= OP_OPIN; newDelay := 4; cpustage <= CPUSTAGE_EXECUTE; opsize <= '1'; source1 <= OPSOURCE_REG_dx; + when x"EE" => opcode <= OP_OPOUT; newDelay := 3; cpustage <= CPUSTAGE_EXECUTE; opsize <= '0'; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_ACC; + when x"EF" => opcode <= OP_OPOUT; newDelay := 2; cpustage <= CPUSTAGE_EXECUTE; opsize <= '1'; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_ACC; + + when x"F0" => isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; -- lock + + --when x"F1" => ? + + when x"F2" => newDelay := 4; RepeatNext <= '1'; isPrefix := '1'; repeatZero <= '0'; irqBlocked <= '1'; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; + when x"F3" => newDelay := 4; RepeatNext <= '1'; isPrefix := '1'; repeatZero <= '1'; irqBlocked <= '1'; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; + + when x"F4" => newDelay := 8; halt <= '1'; cpustage <= CPUSTAGE_IDLE; + + when x"F5" => opcode <= OP_NOP; newDelay := 3; regs.FlagCar <= not regs.FlagCar; cpustage <= CPUSTAGE_EXECUTE; + + when x"F6" => opcode <= OP_MEMIMM3; source1 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; + when x"F7" => opcode <= OP_MEMIMM3; source1 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; + + when x"F8" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagCar <= '0'; + when x"F9" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagCar <= '1'; + when x"FA" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagIrq <= '0'; + when x"FB" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagIrq <= '1'; irqBlocked <= '1'; + when x"FC" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagDir <= '0'; + when x"FD" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagDir <= '1'; + + when x"FE" => opcode <= OP_MEMIMM4; source1 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; opsize <= '0'; + when x"FF" => opcode <= OP_MEMIMM4; source1 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; opsize <= '1'; + + when others => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; + + end case; + + if (turbo = '1') then + delay <= 0; + dbuf <= 0; + elsif (newBuf = 0) then + delay <= newDelay; + dbuf <= 0; + elsif (newBuf > newDelay) then + delay <= 0; + dbuf <= newBuf - newDelay; + else + delay <= newDelay - newBuf; + dbuf <= 0; + end if; + + if (isPrefix = '1') then + PrefixIP <= PrefixIP + 1; + end if; + + if ((repeat = '1' or newRepeat = '1') and usePrefix = '0') then + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + Repeat <= '0'; + PrefixIP <= (others => '0'); + end if; + +-- #################################################################################### +-- ############################## MODRM ########################################## +-- #################################################################################### + + when CPUSTAGE_MODRM => + if (consumePrefetch = 0 and prefetchCount > 2) then + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + MODRM_mem := unsigned(prefetchBuffer(2 downto 0)); + MODRM_reg := unsigned(prefetchBuffer(5 downto 3)); + MODRM_mod := unsigned(prefetchBuffer(7 downto 6)); + + if (opcodebyte = x"8E" and MODRM_reg = 3) then irqBlocked <= '1'; end if; + + newModDelay := delay; + + if (MODRM_mod = 0 and MODRM_mem = 6) then + if (SLOWTIMING = '1') then newModDelay := newModDelay + 1; end if; + consumePrefetch <= 3; + regs.reg_ip <= regs.reg_ip + 3; + memAddr <= unsigned(prefetchBuffer(23 downto 8)); + else + varmemaddr := x"0000"; + case (to_integer(MODRM_mem)) is + when 0 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_bx + regs.reg_si; + when 1 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_bx + regs.reg_di; + when 2 => memSegment <= regs.reg_ss; varmemaddr := regs.reg_bp + regs.reg_si; + when 3 => memSegment <= regs.reg_ss; varmemaddr := regs.reg_bp + regs.reg_di; + when 4 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_si; + when 5 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_di; + when 6 => memSegment <= regs.reg_ss; varmemaddr := regs.reg_bp; + when 7 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_bx; + when others => null; + end case; + if (MODRM_mod = 1) then + if (SLOWTIMING = '1') then newModDelay := newModDelay + 1; end if; + consumePrefetch <= 2; + regs.reg_ip <= regs.reg_ip + 2; + varmemaddr := to_unsigned(to_integer(varmemaddr) + to_integer(signed(prefetchBuffer(15 downto 8))), 16); + elsif (MODRM_mod = 2) then + if (SLOWTIMING = '1') then newModDelay := newModDelay + 1; end if; + consumePrefetch <= 3; + regs.reg_ip <= regs.reg_ip + 3; + varmemaddr := varmemaddr + unsigned(prefetchBuffer(23 downto 8)); + end if; + memaddr <= varmemaddr; + end if; + + -- set target reg + varoptarget := optarget; + varsource1 := source1; + varsource2 := source2; + vartarget_reg := CPU_REG_NONE; + varpushlist := pushlist; + if (segmentaccess = '1') then + case (to_integer(MODRM_reg(1 downto 0))) is + when 0 => vartarget_reg := CPU_REG_es; + when 1 => vartarget_reg := CPU_REG_cs; + when 2 => vartarget_reg := CPU_REG_ss; + when 3 => vartarget_reg := CPU_REG_ds; + when others => null; + end case; + else + if (opsize = '0') then + case (to_integer(MODRM_reg)) is + when 0 => vartarget_reg := CPU_REG_al; + when 1 => vartarget_reg := CPU_REG_cl; + when 2 => vartarget_reg := CPU_REG_dl; + when 3 => vartarget_reg := CPU_REG_bl; + when 4 => vartarget_reg := CPU_REG_ah; + when 5 => vartarget_reg := CPU_REG_ch; + when 6 => vartarget_reg := CPU_REG_dh; + when 7 => vartarget_reg := CPU_REG_bh; + when others => null; + end case; + elsif (opsize = '1') then + case (to_integer(MODRM_reg)) is + when 0 => vartarget_reg := CPU_REG_ax; + when 1 => vartarget_reg := CPU_REG_cx; + when 2 => vartarget_reg := CPU_REG_dx; + when 3 => vartarget_reg := CPU_REG_bx; + when 4 => vartarget_reg := CPU_REG_sp; + when 5 => vartarget_reg := CPU_REG_bp; + when 6 => vartarget_reg := CPU_REG_si; + when 7 => vartarget_reg := CPU_REG_di; + when others => null; + end case; + end if; + end if; + target_reg <= vartarget_reg; + + -- get reg + if (segmentaccess = '1') then + case (to_integer(MODRM_reg(1 downto 0))) is + when 0 => MODRM_value_reg <= regs.reg_es; + when 1 => MODRM_value_reg <= regs.reg_cs; + when 2 => MODRM_value_reg <= regs.reg_ss; + when 3 => MODRM_value_reg <= regs.reg_ds; + when others => null; + end case; + else + if (opsize = '0') then + case (to_integer(MODRM_reg)) is + when 0 => MODRM_value_reg <= x"00" & regs.reg_ax( 7 downto 0); + when 1 => MODRM_value_reg <= x"00" & regs.reg_cx( 7 downto 0); + when 2 => MODRM_value_reg <= x"00" & regs.reg_dx( 7 downto 0); + when 3 => MODRM_value_reg <= x"00" & regs.reg_bx( 7 downto 0); + when 4 => MODRM_value_reg <= x"00" & regs.reg_ax(15 downto 8); + when 5 => MODRM_value_reg <= x"00" & regs.reg_cx(15 downto 8); + when 6 => MODRM_value_reg <= x"00" & regs.reg_dx(15 downto 8); + when 7 => MODRM_value_reg <= x"00" & regs.reg_bx(15 downto 8); + when others => null; + end case; + elsif (opsize = '1') then + case (to_integer(MODRM_reg)) is + when 0 => MODRM_value_reg <= regs.reg_ax; + when 1 => MODRM_value_reg <= regs.reg_cx; + when 2 => MODRM_value_reg <= regs.reg_dx; + when 3 => MODRM_value_reg <= regs.reg_bx; + when 4 => MODRM_value_reg <= regs.reg_sp; + when 5 => MODRM_value_reg <= regs.reg_bp; + when 6 => MODRM_value_reg <= regs.reg_si; + when 7 => MODRM_value_reg <= regs.reg_di; + when others => null; + end case; + end if; + end if; + + -- second decode + case (opcode) is + when OP_MEMIMM1 => + opcode <= OP_MOVMEM; + case (to_integer(MODRM_reg)) is + when 0 => aluop <= ALU_OP_ADD; + when 1 => aluop <= ALU_OP_OR; + when 2 => aluop <= ALU_OP_ADC; + when 3 => aluop <= ALU_OP_SBB; + when 4 => aluop <= ALU_OP_AND; + when 5 => aluop <= ALU_OP_SUB; + when 6 => aluop <= ALU_OP_XOR; + when 7 => aluop <= ALU_OP_CMP; opcode <= OP_NOP; + when others => null; + end case; + + when OP_MEMIMM2 => + opcode <= OP_MOVMEM; + case (to_integer(MODRM_reg)) is + when 0 => aluop <= ALU_OP_ROL; + when 1 => aluop <= ALU_OP_ROR; + when 2 => aluop <= ALU_OP_RCL; + when 3 => aluop <= ALU_OP_RCR; + when 4 => aluop <= ALU_OP_SHL; + when 5 => aluop <= ALU_OP_SHR; + when 6 => aluop <= ALU_OP_SAL; + when 7 => aluop <= ALU_OP_SAR; + when others => null; + end case; + + when OP_MEMIMM3 => + case (to_integer(MODRM_reg)) is + when 0 | 1 => + opcode <= OP_NOP; aluop <= ALU_OP_TST; + if (opsize = '1') then varsource2 := OPSOURCE_FETCHVALUE16; else varsource2 := OPSOURCE_FETCHVALUE8; end if; + dbuf <= dbuf + 1; + when 2 => opcode <= OP_MOVMEM; varoptarget := OPTARGET_MEM; aluop <= ALU_OP_NOT; useAluResult <= '1'; if (MODRM_mod /= 3) then newModDelay := newModDelay + 1; end if; + when 3 => opcode <= OP_MOVMEM; varoptarget := OPTARGET_MEM; aluop <= ALU_OP_NEG; useAluResult <= '1'; if (MODRM_mod /= 3) then newModDelay := newModDelay + 1; end if; + when 4 => opcode <= OP_NOP; varsource1 := OPSOURCE_ACC; varsource2 := OPSOURCE_MEM; aluop <= ALU_OP_MUL; useAluResult <= '1'; newModDelay := newModDelay + 2; + when 5 => opcode <= OP_NOP; varsource1 := OPSOURCE_ACC; varsource2 := OPSOURCE_MEM; aluop <= ALU_OP_MULI; useAluResult <= '1'; newModDelay := newModDelay + 2; + when 6 => opcode <= OP_DIV; varsource1 := OPSOURCE_ACC; varsource2 := OPSOURCE_MEM; + if (opsize = '0') then newModDelay := newModDelay + 2; else newModDelay := newModDelay + 11; end if; + when 7 => opcode <= OP_DIVI; varsource1 := OPSOURCE_ACC; varsource2 := OPSOURCE_MEM; + if (opsize = '0') then newModDelay := newModDelay + 4; else newModDelay := newModDelay + 12; end if; + when others => null; + end case; + + when OP_MEMIMM4 => + case (to_integer(MODRM_reg)) is + when 0 => opcode <= OP_MOVMEM; varoptarget := OPTARGET_MEM; aluop <= ALU_OP_INC; varsource2 := OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; useAluResult <= '1'; if (MODRM_mod /= 3) then newModDelay := newModDelay + 1; end if; + when 1 => opcode <= OP_MOVMEM; varoptarget := OPTARGET_MEM; aluop <= ALU_OP_DEC; varsource2 := OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; useAluResult <= '1'; if (MODRM_mod /= 3) then newModDelay := newModDelay + 1; end if; + when 2 => opcode <= OP_JUMPABS; newModDelay := newModDelay + 1; varpushlist := REGPOS_ip; + when 3 => opcode <= OP_JUMPFAR; varsource2 := OPSOURCE_MEM; varpushlist := REGPOS_cs or REGPOS_ip; newModDelay := newModDelay + 6; + when 4 => opcode <= OP_JUMPABS; newModDelay := newModDelay + 1; + when 5 => opcode <= OP_JUMPFAR; varsource2 := OPSOURCE_MEM; newModDelay := newModDelay + 6; + when 6 | 7 => opcode <= OP_NOP; varpushlist := REGPOS_mem; dbuf <= dbuf + 1; + when others => null; + end case; + + when others => null; + + end case; + + varfetchedSource1 := fetchedSource1; + varfetchedSource2 := fetchedSource2; + + --set target mem + if (varoptarget = OPTARGET_MEM and MODRM_mod = 3) then + target_reg2 <= vartarget_reg; + varoptarget := OPTARGET_MODRM_REG; + opcode <= OP_MOVREG; + if (opcodebyte = x"8F") then --special case: PopMem + opcode <= OP_NOP; + end if; + if (opcode = OP_MEMIMM1 and to_integer(MODRM_reg) = 7) then -- special case: CMP + opcode <= OP_NOP; + end if; + if (opsize = '0') then + case (to_integer(MODRM_mem)) is + when 0 => target_reg <= CPU_REG_al; + when 1 => target_reg <= CPU_REG_cl; + when 2 => target_reg <= CPU_REG_dl; + when 3 => target_reg <= CPU_REG_bl; + when 4 => target_reg <= CPU_REG_ah; + when 5 => target_reg <= CPU_REG_ch; + when 6 => target_reg <= CPU_REG_dh; + when 7 => target_reg <= CPU_REG_bh; + when others => null; + end case; + elsif (opsize = '1') then + case (to_integer(MODRM_mem)) is + when 0 => target_reg <= CPU_REG_ax; + when 1 => target_reg <= CPU_REG_cx; + when 2 => target_reg <= CPU_REG_dx; + when 3 => target_reg <= CPU_REG_bx; + when 4 => target_reg <= CPU_REG_sp; + when 5 => target_reg <= CPU_REG_bp; + when 6 => target_reg <= CPU_REG_si; + when 7 => target_reg <= CPU_REG_di; + when others => null; + end case; + end if; + + if (opcode = OP_MEMIMM1) then + varfetchedSource2 := '1'; + if (source2 = OPSOURCE_FETCHVALUE8) then + if (opsign = '1') then + fetch2Val <= unsigned(resize(signed(prefetchBuffer(15 downto 8)), 16)); + else + fetch2Val <= x"00" & unsigned(prefetchBuffer(15 downto 8)); + end if; + consumePrefetch <= 2; + regs.reg_ip <= regs.reg_ip + 2; + else + fetch2Val <= unsigned(prefetchBuffer(23 downto 8)); + consumePrefetch <= 3; + regs.reg_ip <= regs.reg_ip + 3; + end if; + end if; + + end if; + + optarget <= varoptarget; + + + -- instant fetching if memory access degrades to register access + fetchedRMMODData := x"0000"; + if (opsize = '0') then + case (to_integer(MODRM_mem)) is + when 0 => fetchedRMMODData := x"00" & regs.reg_ax( 7 downto 0); + when 1 => fetchedRMMODData := x"00" & regs.reg_cx( 7 downto 0); + when 2 => fetchedRMMODData := x"00" & regs.reg_dx( 7 downto 0); + when 3 => fetchedRMMODData := x"00" & regs.reg_bx( 7 downto 0); + when 4 => fetchedRMMODData := x"00" & regs.reg_ax(15 downto 8); + when 5 => fetchedRMMODData := x"00" & regs.reg_cx(15 downto 8); + when 6 => fetchedRMMODData := x"00" & regs.reg_dx(15 downto 8); + when 7 => fetchedRMMODData := x"00" & regs.reg_bx(15 downto 8); + when others => null; + end case; + elsif (opsize = '1') then + case (to_integer(MODRM_mem)) is + when 0 => fetchedRMMODData := regs.reg_ax; + when 1 => fetchedRMMODData := regs.reg_cx; + when 2 => fetchedRMMODData := regs.reg_dx; + when 3 => fetchedRMMODData := regs.reg_bx; + when 4 => fetchedRMMODData := regs.reg_sp; + when 5 => fetchedRMMODData := regs.reg_bp; + when 6 => fetchedRMMODData := regs.reg_si; + when 7 => fetchedRMMODData := regs.reg_di; + when others => null; + end case; + end if; + + if (varsource1 = OPSOURCE_MEM and MODRM_mod = 3) then varfetchedSource1 := '1'; memFetchValue1 <= fetchedRMMODData; end if; + if (varsource2 = OPSOURCE_MEM and MODRM_mod = 3) then varfetchedSource2 := '1'; memFetchValue2 <= fetchedRMMODData; end if; + + source1 <= varsource1; + source2 <= varsource2; + + fetchedSource1 <= varfetchedSource1; + fetchedSource2 <= varfetchedSource2; + + pushlist <= varpushlist; + + delay <= newModDelay; + + if (turbo = '1') then + delay <= 0; + end if; + cpustage <= CPUSTAGE_CHECKDATAREADY; + end if; -- consumePrefetch = 0 + +-- #################################################################################### +-- ############################## Source 1 + 2 ######################################## +-- #################################################################################### + + when CPUSTAGE_CHECKDATAREADY => + if (ce = '1' or delay = 0) then + if (fetchedSource1 = '0' and source1 <= OPSOURCE_FETCHVALUE8 ) then cpustage <= CPUSTAGE_FETCHDATA1_8; + elsif (fetchedSource1 = '0' and source1 <= OPSOURCE_FETCHVALUE16) then cpustage <= CPUSTAGE_FETCHDATA1_16; + elsif (fetchedSource1 = '0' and source1 <= OPSOURCE_MEM ) then cpustage <= CPUSTAGE_FETCHMEM_REQ; + + elsif (fetchedSource2 = '0' and source2 <= OPSOURCE_FETCHVALUE8 ) then cpustage <= CPUSTAGE_FETCHDATA2_8; + elsif (fetchedSource2 = '0' and source2 <= OPSOURCE_FETCHVALUE16) then cpustage <= CPUSTAGE_FETCHDATA2_16; + elsif (fetchedSource2 = '0' and source2 <= OPSOURCE_MEM ) then cpustage <= CPUSTAGE_FETCHMEM_REQ; + + elsif (pushlist /= x"0000") then cpustage <= CPUSTAGE_PUSH; + elsif (poplist /= x"0000") then cpustage <= CPUSTAGE_POP_REQ; + + else cpustage <= CPUSTAGE_EXECUTE; + end if; + end if; + + when CPUSTAGE_FETCHDATA1_8 => + if ((ce = '1' or instantFetch = '1') and (prefetchCount - consumePrefetch) > 0) then + fetchedSource1 <= '1'; + if (instantFetch = '1') then + cpustage <= CPUSTAGE_EXECUTE; + else + cpustage <= CPUSTAGE_CHECKDATAREADY; + end if; + if (consumePrefetch = 1) then + if (opsign = '1') then fetch1Val <= unsigned(resize(signed(prefetchBuffer(15 downto 8)), 16)); + else fetch1Val <= x"00" & unsigned(prefetchBuffer(15 downto 8)); end if; + else + if (opsign = '1') then fetch1Val <= unsigned(resize(signed(prefetchBuffer(7 downto 0)), 16)); + else fetch1Val <= x"00" & unsigned(prefetchBuffer(7 downto 0)); end if; + end if; + regs.reg_ip <= Regs.reg_ip + 1; + consumePrefetch <= 1; + end if; + + when CPUSTAGE_FETCHDATA1_16 => + if ((ce = '1' or instantFetch = '1') and (prefetchCount - consumePrefetch) > 1) then + fetchedSource1 <= '1'; + if (instantFetch = '1') then + cpustage <= CPUSTAGE_EXECUTE; + else + cpustage <= CPUSTAGE_CHECKDATAREADY; + end if; + if (consumePrefetch = 1) then + fetch1Val <= unsigned(prefetchBuffer(23 downto 8)); + else + fetch1Val <= unsigned(prefetchBuffer(15 downto 0)); + end if; + regs.reg_ip <= regs.reg_ip + 2; + consumePrefetch <= 2; + if (SLOWTIMING = '1') then delay <= 1; end if; + end if; + + when CPUSTAGE_FETCHDATA2_8 => + if ((ce = '1' or instantFetch = '1') and (prefetchCount - consumePrefetch) > 0) then + fetchedSource2 <= '1'; + if (instantFetch = '1') then + cpustage <= CPUSTAGE_EXECUTE; + else + cpustage <= CPUSTAGE_CHECKDATAREADY; + end if; + if (consumePrefetch = 1) then + if (opsign = '1') then fetch2Val <= unsigned(resize(signed(prefetchBuffer(15 downto 8)), 16)); + else fetch2Val <= x"00" & unsigned(prefetchBuffer(15 downto 8)); end if; + else + if (opsign = '1') then fetch2Val <= unsigned(resize(signed(prefetchBuffer(7 downto 0)), 16)); + else fetch2Val <= x"00" & unsigned(prefetchBuffer(7 downto 0)); end if; + end if; + regs.reg_ip <= Regs.reg_ip + 1; + consumePrefetch <= 1; + end if; + + when CPUSTAGE_FETCHDATA2_16 => + if ((ce = '1' or instantFetch = '1') and (prefetchCount - consumePrefetch) > 1) then + fetchedSource2 <= '1'; + if (instantFetch = '1') then + cpustage <= CPUSTAGE_EXECUTE; + else + cpustage <= CPUSTAGE_CHECKDATAREADY; + end if; + if (consumePrefetch = 1) then + fetch2Val <= unsigned(prefetchBuffer(23 downto 8)); + else + fetch2Val <= unsigned(prefetchBuffer(15 downto 0)); + end if; + regs.reg_ip <= regs.reg_ip + 2; + consumePrefetch <= 2; + if (SLOWTIMING = '1') then delay <= 1; end if; + end if; + +-- #################################################################################### +-- ############################## FETCH Mem ########################################## +-- #################################################################################### + + when CPUSTAGE_FETCHMEM_REQ => + if (ce = '1') then + cpustage <= CPUSTAGE_FETCHMEM_WAIT; + varmemSegment := memSegment; + if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; + if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; + if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; + if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; + if (source1 = OPSOURCE_MEM and fetchedSource1 = '0') then + if (unaligned1 = '1') then + bus_addr <= resize(varmemSegment * 16 + memAddr + 1, 20); + else + bus_addr <= resize(varmemSegment * 16 + memAddr, 20); + end if; + bus_read <= '1'; + prefetchAllow <= '0'; + elsif (source2 = OPSOURCE_MEM and fetchedSource2 = '0') then + if (unaligned2 = '1') then + bus_addr <= resize(varmemSegment * 16 + memAddr + 1, 20); + else + bus_addr <= resize(varmemSegment * 16 + memAddr, 20); + end if; + bus_read <= '1'; + prefetchAllow <= '0'; + end if; + end if; + + when CPUSTAGE_FETCHMEM_WAIT => + cpustage <= CPUSTAGE_FETCHMEM_REC; + + when CPUSTAGE_FETCHMEM_REC => + if (source1 = OPSOURCE_MEM and fetchedSource1 = '0') then + if (opsize = '0') then + memFetchValue1 <= x"00" & unsigned(bus_dataread(7 downto 0)); + if (source2 = OPSOURCE_MEM) then memAddr <= memAddr + 1; end if; + fetchedSource1 <= '1'; + cpustage <= CPUSTAGE_CHECKDATAREADY; + if (pushlist /= x"0000" or (fetchedSource2 = '0' and (source2 <= OPSOURCE_FETCHVALUE8 or source2 <= OPSOURCE_FETCHVALUE16 or source2 <= OPSOURCE_MEM))) then + cpustage <= CPUSTAGE_CHECKDATAREADY; + else + cpustage <= CPUSTAGE_EXECUTE; + end if; + else + if (unaligned1 = '1') then + if (source2 = OPSOURCE_MEM) then memAddr <= memAddr + 2; end if; + fetchedSource1 <= '1'; + memFetchValue1(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); + if (pushlist /= x"0000" or (fetchedSource2 = '0' and (source2 <= OPSOURCE_FETCHVALUE8 or source2 <= OPSOURCE_FETCHVALUE16 or source2 <= OPSOURCE_MEM))) then + cpustage <= CPUSTAGE_CHECKDATAREADY; + else + cpustage <= CPUSTAGE_EXECUTE; + end if; + else + memFetchValue1 <= unsigned(bus_dataread); + if (memAddr(0) = '1') then + unaligned1 <= '1'; + cpustage <= CPUSTAGE_FETCHMEM_REQ; + else + if (source2 = OPSOURCE_MEM) then memAddr <= memAddr + 2; end if; + if (SLOWTIMING = '1') then delay <= 1; end if; + fetchedSource1 <= '1'; + if (pushlist /= x"0000" or (fetchedSource2 = '0' and (source2 <= OPSOURCE_FETCHVALUE8 or source2 <= OPSOURCE_FETCHVALUE16 or source2 <= OPSOURCE_MEM))) then + cpustage <= CPUSTAGE_CHECKDATAREADY; + else + cpustage <= CPUSTAGE_EXECUTE; + end if; + end if; + end if; + end if; + elsif (source2 = OPSOURCE_MEM and fetchedSource2 = '0') then + if (opsize = '0') then + memFetchValue2 <= x"00" & unsigned(bus_dataread(7 downto 0)); + fetchedSource2 <= '1'; + if (pushlist /= x"0000") then + cpustage <= CPUSTAGE_CHECKDATAREADY; + else + cpustage <= CPUSTAGE_EXECUTE; + end if; + else + if (unaligned2 = '1') then + fetchedSource2 <= '1'; + memFetchValue2(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); + if (pushlist /= x"0000") then + cpustage <= CPUSTAGE_CHECKDATAREADY; + else + cpustage <= CPUSTAGE_EXECUTE; + end if; + else + memFetchValue2 <= unsigned(bus_dataread); + if (memAddr(0) = '1') then + unaligned2 <= '1'; + cpustage <= CPUSTAGE_FETCHMEM_REQ; + else + if (SLOWTIMING = '1') then delay <= 1; end if; + fetchedSource2 <= '1'; + if (pushlist /= x"0000") then + cpustage <= CPUSTAGE_CHECKDATAREADY; + else + cpustage <= CPUSTAGE_EXECUTE; + end if; + end if; + end if; + end if; + end if; + +-- #################################################################################### +-- ############################## FETCH IRQ Vector #################################### +-- #################################################################################### + + when CPUSTAGE_IRQVECTOR_REQ => + if (ce = '1') then + if (irqExtern = '1') then + if (memFirst = '1') then + bus_addr <= resize(irqvector_in, 20); + else + bus_addr <= resize(irqvector_in + 2, 20); + end if; + else + if (memFirst = '1') then + bus_addr <= resize(irqvector, 20); + else + bus_addr <= resize(irqvector + 2, 20); + end if; + end if; + + bus_read <= '1'; + prefetchAllow <= '0'; + cpustage <= CPUSTAGE_IRQVECTOR_WAIT; + end if; + + when CPUSTAGE_IRQVECTOR_WAIT => + cpustage <= CPUSTAGE_IRQVECTOR_REC; + + when CPUSTAGE_IRQVECTOR_REC => + memFirst <= '0'; + if (memFirst = '1') then + irqIP <= unsigned(bus_dataread); + cpustage <= CPUSTAGE_IRQVECTOR_REQ; + else + irqCS <= unsigned(bus_dataread); + cpustage <= CPUSTAGE_CHECKDATAREADY; + end if; + +-- #################################################################################### +-- ############################## Push ########################################## +-- #################################################################################### + + when CPUSTAGE_PUSH => + if (ce = '1') then + pushindex := 0; + for i in 15 downto 0 loop + if (pushlist(i) = '1') then + pushindex := i; + end if; + end loop; + + pushValue := x"0000"; + + case (pushindex) is + when 0 => pushValue := std_logic_vector(regs.reg_ax); + when 1 => pushValue := std_logic_vector(regs.reg_cx); + when 2 => pushValue := std_logic_vector(regs.reg_dx); + when 3 => pushValue := std_logic_vector(regs.reg_bx); + when 4 => pushValue := std_logic_vector(reg_sp_push); + when 5 => pushValue := std_logic_vector(regs.reg_bp); + when 6 => pushValue := std_logic_vector(regs.reg_si); + when 7 => pushValue := std_logic_vector(regs.reg_di); + when 8 => pushValue := std_logic_vector(regs.reg_es); + when 9 => pushValue := std_logic_vector(reg_f); + when 10 => pushValue := std_logic_vector(regs.reg_cs); + when 11 => pushValue := std_logic_vector(regs.reg_ss); + when 12 => pushValue := std_logic_vector(regs.reg_ds); + when 13 => pushValue := std_logic_vector(regs.reg_ip - prefixIP); + when 14 => pushValue := std_logic_vector(memFetchValue1); + when 15 => + if (opsize = '0') then + pushValue := std_logic_vector(resize(signed(fetch1Val(7 downto 0)), 16)); + else + pushValue := std_logic_vector(fetch1Val); + end if; + when others => null; + end case; + + if (pushFirst = '1') then + if (regs.reg_sp(0) = '0') then -- aligned + regs.reg_sp <= regs.reg_sp - 2; + bus_read <= '0'; + bus_write <= '1'; + bus_be <= "11"; + bus_addr <= resize(regs.reg_ss * 16 + resize(regs.reg_sp - 2,16), 20); + bus_datawrite <= pushValue; + prefetchAllow <= '0'; + cpustage <= CPUSTAGE_CHECKDATAREADY; + pushlist(pushindex) <= '0'; + else + bus_read <= '0'; + bus_write <= '1'; + bus_be <= "01"; + bus_addr <= resize(regs.reg_ss * 16 + resize(regs.reg_sp - 2,16), 20); + bus_datawrite <= pushValue; + prefetchAllow <= '0'; + pushFirst <= '0'; + end if; + else + regs.reg_sp <= regs.reg_sp - 2; + bus_read <= '0'; + bus_write <= '1'; + bus_be <= "01"; + bus_addr <= resize(regs.reg_ss * 16 + resize(regs.reg_sp - 1,16), 20); + bus_datawrite <= x"00" & pushValue(15 downto 8); + prefetchAllow <= '0'; + cpustage <= CPUSTAGE_CHECKDATAREADY; + pushFirst <= '1'; + pushlist(pushindex) <= '0'; + end if; + + end if; + +-- #################################################################################### +-- ############################## Pop ########################################## +-- #################################################################################### + + when CPUSTAGE_POP_REQ => + if (ce = '1') then + cpustage <= CPUSTAGE_POP_WAIT; + + popindex := 0; + for i in 0 to 15 loop + if (poplist(i) = '1') then + popindex := i; + end if; + end loop; + poptarget <= popindex; + + bus_read <= '1'; + bus_write <= '0'; + if (popFirst = '1') then + bus_addr <= resize(regs.reg_ss * 16 + regs.reg_sp, 20); + else + bus_addr <= resize(regs.reg_ss * 16 + resize(regs.reg_sp + 1, 16), 20); + end if; + prefetchAllow <= '0'; + + end if; + + when CPUSTAGE_POP_WAIT => + cpustage <= CPUSTAGE_POP_REC; + if (popFirst = '0' or regs.reg_sp(0) = '0') then + poplist(poptarget) <= '0'; + end if; + + when CPUSTAGE_POP_REC => + cpustage <= CPUSTAGE_POP_REQ; + + popValue := bus_dataread; + popDone := '0'; + if (popFirst = '1') then + if (regs.reg_sp(0) = '0') then -- aligned + popDone := '1'; + else + popFirst <= '0'; + popUnalnByte <= bus_dataread(7 downto 0); + end if; + else + popDone := '1'; + popValue := bus_dataread(7 downto 0) & popUnalnByte; + end if; + + if (popDone = '1') then + + popFirst <= '1'; + + if (opcodebyte = x"61" and popindex = 5) then + regs.reg_sp <= regs.reg_sp + 4; + else + regs.reg_sp <= regs.reg_sp + 2; + end if; + + case (poptarget) is + when 0 => regs.reg_ax <= unsigned(popValue); + when 1 => regs.reg_cx <= unsigned(popValue); + when 2 => regs.reg_dx <= unsigned(popValue); + when 3 => regs.reg_bx <= unsigned(popValue); + when 4 => regs.reg_sp <= unsigned(popValue); + when 5 => regs.reg_bp <= unsigned(popValue); + when 6 => regs.reg_si <= unsigned(popValue); + when 7 => regs.reg_di <= unsigned(popValue); + when 8 => regs.reg_es <= unsigned(popValue); + when 9 => + regs.FlagCar <= popValue(0); + regs.FlagPar <= popValue(2); + regs.FlagHaC <= popValue(4); + regs.FlagZer <= popValue(6); + regs.FlagSgn <= popValue(7); + regs.FlagBrk <= popValue(8); + regs.FlagIrq <= popValue(9); + regs.FlagDir <= popValue(10); + regs.FlagOvf <= popValue(11); + regs.FlagMod <= popValue(15); + when 10 => regs.reg_cs <= unsigned(popValue); + when 11 => regs.reg_ss <= unsigned(popValue); + when 12 => regs.reg_ds <= unsigned(popValue); + when 13 => regs.reg_ip <= unsigned(popValue); + when 14 => popVal <= unsigned(popValue); + when others => null; + end case; + + if (poplist = x"0000") then + cpustage <= CPUSTAGE_EXECUTE; + if (SLOWTIMING = '1') then delay <= 1; end if; + if (opcodebyte = x"C2" or opcodebyte = x"C3" or opcodebyte = x"CA" or opcodebyte = x"CB" or opcodebyte = x"CF") then + clearPrefetch <= '1'; + delay <= 3; + end if; + end if; + + end if; + + +-- #################################################################################### +-- ############################## EXECUTE ########################################## +-- #################################################################################### + + when CPUSTAGE_EXECUTE => + + source1Val := x"0000"; + case (source1) is + when OPSOURCE_FETCHVALUE8 => source1Val := fetch1Val; + when OPSOURCE_FETCHVALUE16 => source1Val := fetch1Val; + when OPSOURCE_IRQVECTOR => source1Val := fetch1Val; + when OPSOURCE_MEM => source1Val := memFetchValue1; + when OPSOURCE_MODRM_REG => source1Val := MODRM_value_reg; + when OPSOURCE_MODRM_ADDR => source1Val := memAddr; + when OPSOURCE_ACC => if (opsize = '0') then source1Val := x"00" & regs.reg_ax(7 downto 0); else source1Val := regs.reg_ax; end if; + when OPSOURCE_STRINGLOAD1 => source1Val := stringLoad; + when OPSOURCE_STRINGLOAD2 => source1Val := stringLoad2; + when OPSOURCE_IMMIDIATE => source1Val := x"00" & immidiate8; + when OPSOURCE_POPVALUE => source1Val := popVal; + when OPSOURCE_REG_ax => source1Val := regs.reg_ax; + when OPSOURCE_REG_cx => source1Val := regs.reg_cx; + when OPSOURCE_REG_dx => source1Val := regs.reg_dx; + when OPSOURCE_REG_bx => source1Val := regs.reg_bx; + when OPSOURCE_REG_sp => source1Val := regs.reg_sp; + when OPSOURCE_REG_bp => source1Val := regs.reg_bp; + when OPSOURCE_REG_si => source1Val := regs.reg_si; + when OPSOURCE_REG_di => source1Val := regs.reg_di; + when others => null; + end case; + + source2Val := x"0000"; + case (source2) is + when OPSOURCE_FETCHVALUE8 => source2Val := fetch2Val; + when OPSOURCE_FETCHVALUE16 => source2Val := fetch2Val; + when OPSOURCE_IRQVECTOR => source2Val := fetch2Val; + when OPSOURCE_MEM => source2Val := memFetchValue2; + when OPSOURCE_MODRM_REG => source2Val := MODRM_value_reg; + when OPSOURCE_ACC => if (opsize = '0') then source2Val := x"00" & regs.reg_ax(7 downto 0); else source2Val := regs.reg_ax; end if; + when OPSOURCE_STRINGLOAD1 => source2Val := stringLoad; + when OPSOURCE_STRINGLOAD2 => source2Val := stringLoad2; + when OPSOURCE_IMMIDIATE => source2Val := x"00" & immidiate8; + when OPSOURCE_REG_cx => source2Val := regs.reg_cx; + when others => null; + end case; + + target := CPU_REG_ip; + case (optarget) is + when OPTARGET_DECODE => target := target_decode; + --when OPTARGET_MEM => target := target_mem; + when OPTARGET_MODRM_REG => target := target_reg; + when others => null; + end case; + +-- #################################################################################### +-- ############################## CALC ########################################## +-- #################################################################################### + + result := x"0000"; + newZero := '0'; + newParity := '0'; + newSign := '0'; + + if (aluop /= ALU_OP_NOTHING) then + case (aluop) is + when ALU_OP_SET1 => + if (opsize = '0') then + op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(2 downto 0))); + else + op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(3 downto 0))); + end if; + result := source1Val or op2value; + + when ALU_OP_CLR1 => + if (opsize = '0') then + op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(2 downto 0))); + else + op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(3 downto 0))); + end if; + result := source1Val and (not op2value); + + when ALU_OP_TEST1 => + if (opsize = '0') then + op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(2 downto 0))); + else + op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(3 downto 0))); + end if; + result := source1Val and op2value; + regs.FlagCar <= '0'; regs.FlagOvf <= '0'; regs.FlagHaC <= '0'; + newZero := '1'; newParity := '1'; newSign := '1'; + + when ALU_OP_NOT1 => + if (opsize = '0') then + op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(2 downto 0))); + else + op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(3 downto 0))); + end if; + result := source1Val xor op2value; + + when ALU_OP_ROR4 => + result := x"00" & regs.reg_ax(3 downto 0) & source1Val(7 downto 4); + regs.reg_ax(7 downto 0) <= regs.reg_ax(7 downto 4) & source1Val(3 downto 0); + + when ALU_OP_ROL4 => + result := x"00" & source1Val(3 downto 0) & regs.reg_ax(3 downto 0); + regs.reg_ax(7 downto 0) <= regs.reg_ax(7 downto 4) & source1Val(7 downto 4); + + when ALU_OP_AND | ALU_OP_TST => + result := source1Val and source2Val; + regs.FlagCar <= '0'; regs.FlagOvf <= '0'; regs.FlagHaC <= '0'; + newZero := '1'; newParity := '1'; newSign := '1'; + + when ALU_OP_OR => + result := source1Val or source2Val; + regs.FlagCar <= '0'; regs.FlagOvf <= '0'; regs.FlagHaC <= '0'; + newZero := '1'; newParity := '1'; newSign := '1'; + + when ALU_OP_XOR => + result := source1Val xor source2Val; + regs.FlagCar <= '0'; regs.FlagOvf <= '0'; regs.FlagHaC <= '0'; + newZero := '1'; newParity := '1'; newSign := '1'; + + when ALU_OP_NOT => + result := not source1Val; + + when ALU_OP_NEG => + result := 0 - source1Val; + if (source1Val > 0) then regs.FlagCar <= '1'; else regs.FlagCar <= '0'; end if; + if (source1Val(3 downto 0) > 0) then regs.FlagHaC <= '1'; else regs.FlagHaC <= '0'; end if; + regs.FlagOvf <= '0'; + if (opsize = '0' and source1Val(7 downto 0) = x"80") then regs.FlagOvf <= '1'; end if; + if (opsize = '1' and source1Val = x"8000") then regs.FlagOvf <= '1'; end if; + newZero := '1'; newParity := '1'; newSign := '1'; + + when ALU_OP_ADD | ALU_OP_INC | ALU_OP_ADC => + op2value := source2Val; + if (aluop = ALU_OP_ADC and flagCarry = '1') then + op2value := op2value + 1; + end if; + newZero := '1'; newParity := '1'; newSign := '1'; + result := source1Val + op2value; + if (aluop /= ALU_OP_INC) then + regs.FlagCar <= '0'; + if (opsize = '0' and to_integer(source1Val) + to_integer(op2value) > 16#FF#) then regs.FlagCar <= '1'; end if; + if (opsize = '1' and to_integer(source1Val) + to_integer(op2value) > 16#FFFF#) then regs.FlagCar <= '1'; end if; + end if; + if (to_integer(source1Val(3 downto 0)) + to_integer(op2value(3 downto 0)) >= 16) then regs.FlagHaC <= '1'; else regs.FlagHaC <= '0'; end if; + if (opsize = '0') then + regs.FlagOvf <= (source1Val(7) xor result(7)) and (op2value(7) xor result(7)); + else + regs.FlagOvf <= (source1Val(15) xor result(15)) and (op2value(15) xor result(15)); + end if; + + when ALU_OP_SUB | ALU_OP_CMP | ALU_OP_DEC | ALU_OP_SBB => + op2value := source2Val; + if (aluop = ALU_OP_SBB and flagCarry = '1') then + op2value := op2value + 1; + end if; + newZero := '1'; newParity := '1'; newSign := '1'; + result := source1Val - op2value; + if (aluop /= ALU_OP_DEC) then + if (op2value > source1Val) then regs.FlagCar <= '1'; else regs.FlagCar <= '0'; end if; + end if; + if (op2value(3 downto 0) > source1Val(3 downto 0)) then regs.FlagHaC <= '1'; else regs.FlagHaC <= '0'; end if; + if (opsize = '0') then + regs.FlagOvf <= (source1Val(7) xor op2value(7)) and (source1Val(7) xor result(7)); + else + regs.FlagOvf <= (source1Val(15) xor op2value(15)) and (source1Val(15) xor result(15)); + end if; + + when ALU_OP_ROL => + result17 := resize(source1Val, 17) sll to_integer(source2Val(4 downto 0)); + if (opsize = '0') then + result(7 downto 0) := source1Val(7 downto 0) rol to_integer(source2Val(4 downto 0)); + regs.FlagCar <= result17(8); + regs.FlagOvf <= source1Val(7) xor result(7); + else + result17 := resize(source1Val, 17) sll to_integer(source2Val(4 downto 0)); + result := resize(source1Val, 16) rol to_integer(source2Val(4 downto 0)); + regs.FlagCar <= result17(16); + regs.FlagOvf <= source1Val(15) xor result(15); + end if; + + when ALU_OP_ROR => + result17 := (source1Val & '0') srl to_integer(source2Val(4 downto 0)); + result := result17(16 downto 1); + regs.FlagCar <= result17(0); + if (opsize = '0') then + result(7 downto 0) := source1Val(7 downto 0) ror to_integer(source2Val(4 downto 0)); + regs.FlagOvf <= source1Val(7) xor result(7); + else + result := resize(source1Val, 16) ror to_integer(source2Val(4 downto 0)); + regs.FlagOvf <= source1Val(15) xor result(15); + end if; + + when ALU_OP_RCL => + carryWork1 := flagCarry; + result := source1Val; + for i in 0 to 31 loop + if (i < source2Val(4 downto 0)) then + if (opsize = '0') then + carryWork2 := result(7); + else + carryWork2 := result(15); + end if; + result := result(14 downto 0) & carryWork1; + carryWork1 := carryWork2; + end if; + end loop; + regs.FlagCar <= carryWork1; + if (opsize = '0') then + regs.FlagOvf <= (source1Val(7) xor result(7)); + else + regs.FlagOvf <= (source1Val(15) xor result(15)); + end if; + + when ALU_OP_RCR => + carryWork1 := flagCarry; + result := source1Val; + for i in 0 to 31 loop + if (i < source2Val(4 downto 0)) then + carryWork2 := result(0); + result := '0' & result(15 downto 1); + if (opsize = '0') then + result(7) := carryWork1; + else + result(15) := carryWork1; + end if; + carryWork1 := carryWork2; + end if; + end loop; + regs.FlagCar <= carryWork1; + if (opsize = '0') then + regs.FlagOvf <= (source1Val(7) xor result(7)); + else + regs.FlagOvf <= (source1Val(15) xor result(15)); + end if; + + when ALU_OP_SHL | ALU_OP_SAL => + result17 := resize(source1Val, 17) sll to_integer(source2Val(4 downto 0)); + if (opsize = '0') then regs.FlagCar <= result17(8); end if; + if (opsize = '1') then regs.FlagCar <= result17(16); end if; + if (aluop = ALU_OP_SAL) then + regs.FlagOvf <= '0'; + else + if (opsize = '0') then + regs.FlagOvf <= source1Val(7) xor result17(7); + else + regs.FlagOvf <= source1Val(15) xor result17(15); + end if; + end if; + result := result17(15 downto 0); + newZero := '1'; newParity := '1'; newSign := '1'; + + when ALU_OP_SHR => + result17 := (source1Val & '0') srl to_integer(source2Val(4 downto 0)); + result := result17(16 downto 1); + regs.FlagCar <= result17(0); + if (opsize = '0') then + regs.FlagOvf <= source1Val(7) xor result(7); + else + regs.FlagOvf <= source1Val(15) xor result(15); + end if; + newZero := '1'; newParity := '1'; newSign := '1'; + + when ALU_OP_SAR => + if (source2Val(4) = '1') then + if ((opsize = '0' and source1Val(7) = '1') or (opsize = '1' and source1Val(15) = '1')) then + result := x"FFFF"; + regs.FlagCar <= '1'; + else + result := x"0000"; + regs.FlagCar <= '0'; + end if; + else + result17 := (source1Val & '0') srl to_integer(source2Val(4 downto 0)); + regs.FlagCar <= result17(0); + if (opsize = '0') then + result := x"00" & unsigned(shift_right(signed(source1Val(7 downto 0)),to_integer(source2Val(4 downto 0)))); + else + result := unsigned(shift_right(signed(source1Val),to_integer(source2Val(4 downto 0)))); + end if; + regs.FlagOvf <= '0'; + newZero := '1'; newParity := '1'; newSign := '1'; + end if; + + + when ALU_OP_MUL => + regs.FlagCar <= '0'; regs.FlagOvf <= '0'; + if (opsize = '0') then + result32 := resize(source1Val(7 downto 0) * memFetchValue2, 32); + regs.reg_ax <= result32(15 downto 0); + if (result32(31 downto 8) /= x"000000") then + regs.FlagCar <= '1'; regs.FlagOvf <= '1'; + end if; + else + result32 := source1Val * memFetchValue2; + regs.reg_ax <= result32(15 downto 0); + regs.reg_dx <= result32(31 downto 16); + if (result32(31 downto 16) /= x"0000") then + regs.FlagCar <= '1'; regs.FlagOvf <= '1'; + end if; + end if; + + when ALU_OP_MULI => + regs.FlagCar <= '0'; regs.FlagOvf <= '0'; + if (opsize = '0') then + result32 := unsigned(to_signed(to_integer(signed(source1Val(7 downto 0))) * to_integer(signed(memFetchValue2(7 downto 0))), 32)); + if (opcode = OP_NOP) then regs.reg_ax <= result32(15 downto 0); end if; + if (result32(31 downto 8) /= x"000000") then + regs.FlagCar <= '1'; regs.FlagOvf <= '1'; + end if; + else + if (source1 = OPSOURCE_FETCHVALUE8) then + result32 := unsigned(to_signed(to_integer(signed(source1Val(7 downto 0))) * to_integer(signed(memFetchValue2)), 32)); + else + result32 := unsigned(to_signed(to_integer(signed(source1Val)) * to_integer(signed(memFetchValue2)), 32)); + end if; + if (opcode = OP_NOP) then + regs.reg_ax <= result32(15 downto 0); + regs.reg_dx <= result32(31 downto 16); + end if; + if (result32(31 downto 16) /= x"0000") then + regs.FlagCar <= '1'; regs.FlagOvf <= '1'; + end if; + end if; + result := result32(15 downto 0); + + when ALU_OP_DECADJUST => + result9 := resize(regs.reg_ax(7 downto 0), 9); + regs.FlagCar <= '0'; + if (regs.FlagHaC = '1' or regs.reg_ax(3 downto 0) > x"9") then + if (adjustNegate = '1') then + result9 := result9 - 6; + else + result9 := result9 + 6; + end if; + regs.FlagHaC <= '1'; + regs.FlagCar <= flagCarry or result9(8); + end if; + if (flagCarry = '1' or regs.reg_ax(7 downto 0) > x"99") then + if (adjustNegate = '1') then + result9 := result9 - 16#60#; + else + result9 := result9 + 16#60#; + end if; + regs.FlagCar <= '1'; + end if; + result := x"00" & result9(7 downto 0); + newZero := '1'; newParity := '1'; newSign := '1'; + + when ALU_OP_ASCIIADJUST => + result8 := regs.reg_ax(7 downto 0); + result8h := regs.reg_ax(15 downto 8); + if (regs.FlagHaC = '1' or regs.reg_ax(3 downto 0) > x"9") then + if (adjustNegate = '1') then + result8 := result8 - 6; + result8h := result8h - 1; + else + result8 := result8 + 6; + result8h := result8h + 1; + end if; + regs.FlagHaC <= '1'; + regs.FlagCar <= '1'; + else + regs.FlagHaC <= '0'; + regs.FlagCar <= '0'; + end if; + result8(7 downto 4) := x"0"; + result := result8h & result8; + + when ALU_OP_SXT => + if (opcodebyte = x"98") then + if (regs.reg_ax(7) = '1') then + result := x"FF" & regs.reg_ax(7 downto 0); + else + result := x"00" & regs.reg_ax(7 downto 0); + end if; + else + if (regs.reg_ax(15) = '1') then + result := x"FFFF"; + else + result := x"0000"; + end if; + end if; + + when others => null; + end case; + end if; + + -- flags + if (opsize = '0') then + result(15 downto 8) := x"00"; + end if; + + if (newZero = '1') then + if (result = 0) then regs.FlagZer <= '1'; else regs.FlagZer <= '0'; end if; + end if; + + if (newSign = '1') then + if (opsize = '0') then regs.FlagSgn <= result(7); else regs.FlagSgn <= result(15); end if; + end if; + + if (newParity = '1') then + regs.FlagPar <= not(result(7) xor result(6) xor result(5) xor result(4) xor result(3) xor result(2) xor result(1) xor result(0)); + end if; + + -- mux result + if (useAluResult = '1') then + resultval := result; + else + resultval := source1Val; + end if; + +-- #################################################################################### +-- ############################## OPCodes ########################################## +-- #################################################################################### + + exeDone := '0'; + newExeDelay := delay; + endRepeat := '0'; + jumpNow := '0'; + jumpAddr := (others => '0'); + + case (opcode) is + + when OP_MOVMEM => + if (optarget /= OPTARGET_NONE) then + prefetchAllow <= '0'; + if (bus_read = '0' and bus_write = '0' and (waitexe = '0' or ce = '1')) then + memFirst <= '0'; + waitexe <= '1'; + + varmemSegment := memSegment; + if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; + if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; + if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; + if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; + bus_read <= '0'; + bus_write <= '1'; + + if (memFirst = '0') then + bus_addr <= resize(varmemSegment * 16 + memAddr + 1, 20); + bus_datawrite <= x"00" & std_logic_vector(resultval(15 downto 8)); + bus_be <= "01"; + elsif (opsize = '1' and memAddr(0) = '0') then + bus_addr <= resize(varmemSegment * 16 + memAddr, 20); + bus_datawrite <= std_logic_vector(resultval); + bus_be <= "11"; + else + bus_addr <= resize(varmemSegment * 16 + memAddr, 20); + bus_datawrite <= std_logic_vector(resultval); + bus_be <= "01"; + end if; + + if (opsize = '0' or memFirst = '0' or memAddr(0) = '0') then + if (SLOWTIMING = '1') then newExeDelay := newExeDelay + 1; end if; + if (opcodeNext /= OP_INVALID) then + if (target_reg2 /= CPU_REG_NONE) then + target_reg <= target_reg2; + end if; + optarget <= optarget2; + source1 <= source2; + memFetchValue1 <= memFetchValue2; + opcode <= opcodeNext; + opcodeNext <= OP_INVALID; + else + exeDone := '1'; + end if; + end if; + elsif (waitexe = '1' and ce = '1') then + waitexe <= '0'; + end if; + else + exeDone := '1'; + end if; + + when OP_MOVREG => + if (optarget /= OPTARGET_NONE) then + case (target) is + when CPU_REG_al => regs.reg_ax(7 downto 0) <= resultval(7 downto 0); + when CPU_REG_ah => regs.reg_ax(15 downto 8) <= resultval(7 downto 0); + when CPU_REG_ax => regs.reg_ax <= resultval; + when CPU_REG_bl => regs.reg_bx(7 downto 0) <= resultval(7 downto 0); + when CPU_REG_bh => regs.reg_bx(15 downto 8) <= resultval(7 downto 0); + when CPU_REG_bx => regs.reg_bx <= resultval; + when CPU_REG_cl => regs.reg_cx(7 downto 0) <= resultval(7 downto 0); + when CPU_REG_ch => regs.reg_cx(15 downto 8) <= resultval(7 downto 0); + when CPU_REG_cx => regs.reg_cx <= resultval; + when CPU_REG_dl => regs.reg_dx(7 downto 0) <= resultval(7 downto 0); + when CPU_REG_dh => regs.reg_dx(15 downto 8) <= resultval(7 downto 0); + when CPU_REG_dx => regs.reg_dx <= resultval; + when CPU_REG_sp => regs.reg_sp <= resultval; + when CPU_REG_bp => regs.reg_bp <= resultval; + when CPU_REG_si => regs.reg_si <= resultval; + when CPU_REG_di => regs.reg_di <= resultval; + when CPU_REG_es => regs.reg_es <= resultval; + when CPU_REG_cs => regs.reg_cs <= resultval; + when CPU_REG_ss => regs.reg_ss <= resultval; + when CPU_REG_ds => regs.reg_ds <= resultval; + when others => null; + end case; + end if; + if (opcodebyte = x"C4") then regs.reg_es <= memFetchValue2; end if; + if (opcodebyte = x"C5") then regs.reg_ds <= memFetchValue2; end if; + if (opcodeNext /= OP_INVALID) then + if (ce = '1') then + if (target_reg2 /= CPU_REG_NONE) then + target_reg <= target_reg2; + end if; + optarget <= optarget2; + source1 <= source2; + memFetchValue1 <= memFetchValue2; + opcode <= opcodeNext; + opcodeNext <= OP_INVALID; + end if; + else + exeDone := '1'; + end if; + + when OP_EXCHANGE => + case (opcodebyte) is + when x"91" => regs.reg_ax <= regs.reg_cx; regs.reg_cx <= regs.reg_ax; + when x"92" => regs.reg_ax <= regs.reg_dx; regs.reg_dx <= regs.reg_ax; + when x"93" => regs.reg_ax <= regs.reg_bx; regs.reg_bx <= regs.reg_ax; + when x"94" => regs.reg_ax <= regs.reg_sp; regs.reg_sp <= regs.reg_ax; + when x"95" => regs.reg_ax <= regs.reg_bp; regs.reg_bp <= regs.reg_ax; + when x"96" => regs.reg_ax <= regs.reg_si; regs.reg_si <= regs.reg_ax; + when x"97" => regs.reg_ax <= regs.reg_di; regs.reg_di <= regs.reg_ax; + when others => null; + end case; + exeDone := '1'; + + when OP_BOUND => + if (MODRM_value_reg < memFetchValue1 or MODRM_value_reg > memFetchValue2) then + irqrequest <= '1'; + irqvector <= to_unsigned(20, 10); --5 * 4; + end if; + exeDone := '1'; + + when OP_OPIN => + case (opstep) is + when 0 => + RegBus_Adr <= std_logic_vector(source1Val(7 downto 0)); + RegBus_rden <= '1'; + opstep <= 1; + + when 1 => + opstep <= 2; + memFetchValue1(7 downto 0) <= unsigned(RegBus_Dout); + if (opcodeNext = OP_INVALID) then + regs.reg_ax(7 downto 0) <= unsigned(RegBus_Dout); + end if; + if (opsize = '0') then + if (opcodeNext /= OP_INVALID) then + if (ce = '1') then + source1 <= source2; + opcode <= opcodeNext; + opcodeNext <= OP_INVALID; + opstep <= 0; + end if; + else + exeDone := '1'; + end if; + else + RegBus_Adr <= std_logic_vector(source1Val(7 downto 0) + 1); + RegBus_rden <= '1'; + end if; + + when 2 => + memFetchValue1(15 downto 8) <= unsigned(RegBus_Dout); + if (opcodeNext = OP_INVALID) then + regs.reg_ax(15 downto 8) <= unsigned(RegBus_Dout); + end if; + if (opcodeNext /= OP_INVALID) then + if (ce = '1') then + source1 <= source2; + opcode <= opcodeNext; + opcodeNext <= OP_INVALID; + opstep <= 0; + end if; + else + exeDone := '1'; + end if; + + when others => null; + end case; + + when OP_OPOUT => + memFirst <= '0'; + if (opsize = '0' or memFirst = '1') then + RegBus_Din <= std_logic_vector(source2Val(7 downto 0)); + RegBus_Adr <= std_logic_vector(source1Val(7 downto 0)); + RegBus_wren <= '1'; + elsif (ce = '1') then + RegBus_Din <= std_logic_vector(source2Val(15 downto 8)); + RegBus_Adr <= std_logic_vector(source1Val(7 downto 0) + 1); + RegBus_wren <= '1'; + end if; + if (opsize = '0' or (memFirst = '0' and ce = '1')) then + exeDone := '1'; + newExeDelay := newExeDelay + 1; + end if; + + when OP_BCDSTRING => + if ((bcdOffset & "0") >= regs.reg_cx(7 downto 0)) then + exeDone := '1'; + else + case (opstep) is + when 0 => + if (ce = '1') then + opstep <= 1; + varmemSegment := regs.reg_ds; + if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; + if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; + if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; + if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; + bus_read <= '1'; + bus_write <= '0'; + bus_addr <= resize(varmemSegment * 16 + regs.reg_si + bcdOffset, 20); + prefetchAllow <= '0'; + end if; + + when 1 => opstep <= 2; -- wait + + when 2 => + opstep <= 3; + if (regs.FlagCar = '0') then + fetch1Val(7 downto 0) <= unsigned(bus_dataread(7 downto 0)); + else + fetch1Val(7 downto 0) <= unsigned(bus_dataread(7 downto 0)) + 1; + end if; + regs.FlagCar <= '0'; + + when 3 => + if (ce = '1') then + bus_read <= '1'; + bus_write <= '0'; + bus_addr <= resize(regs.reg_es * 16 + regs.reg_di + bcdOffset, 20); + prefetchAllow <= '0'; + opstep <= 4; + end if; + + when 4 => opstep <= 5; -- wait + + when 5 => + opstep <= 6; + if (bcdOp = BCD_OP_ADD) then + bcdAccLow <= resize(unsigned(bus_dataread(3 downto 0)), 5) + resize(unsigned(fetch1Val(3 downto 0)), 5); + bcdAccHigh <= resize(unsigned(bus_dataread(7 downto 4)), 5) + resize(unsigned(fetch1Val(7 downto 4)), 5); + else + bcdAccLow <= resize(unsigned(bus_dataread(3 downto 0)), 5) - resize(unsigned(fetch1Val(3 downto 0)), 5); + bcdAccHigh <= resize(unsigned(bus_dataread(7 downto 4)), 5) - resize(unsigned(fetch1Val(7 downto 4)), 5); + end if; + + when 6 => + opstep <= 7; + bcdResultLow := bcdAccLow; + bcdResultHigh := bcdAccHigh; + if (bcdResultLow > x"9") then + if (bcdOp = BCD_OP_ADD) then + bcdResultLow := bcdResultLow + 6; + bcdResultHigh := bcdResultHigh + 1; + else + bcdResultLow := bcdResultLow - 6; + bcdResultHigh := bcdResultHigh - 1; + end if; + end if; + if (bcdResultHigh > x"9") then + if (bcdOp = BCD_OP_ADD) then + bcdResultHigh := bcdResultHigh + 6; + else + bcdResultHigh := bcdResultHigh - 6; + end if; + regs.FlagCar <= '1'; + end if; + bcdAcc <= bcdResultHigh(3 downto 0) & bcdResultLow(3 downto 0); + + when 7 => + if (bcdOp = BCD_OP_CMP) then + if (bcdAcc /= x"00") then + regs.FlagZer <= '0'; + end if; + + bcdOffset <= bcdOffset + 1; + opstep <= 0; + else + prefetchAllow <= '0'; + if (bus_read = '0' and bus_write = '0' and (waitexe = '0' or ce = '1')) then + waitexe <= '1'; + bus_read <= '0'; + bus_write <= '1'; + bus_be <= "01"; + bus_datawrite <= x"00" & std_logic_vector(bcdAcc); + bus_addr <= resize(regs.reg_es * 16 + regs.reg_di + bcdOffset, 20); + + if (bcdAcc /= x"00") then + regs.FlagZer <= '0'; + end if; + + bcdOffset <= bcdOffset + 1; + opstep <= 0; + elsif (waitexe = '1' and ce = '1') then + waitexe <= '0'; + end if; + end if; + end case; + end if; + + when OP_STRINGLOAD => + if (opsize = '1') then + wordAligned := (not regs.reg_si(0)); + else + wordAligned := '0'; + end if; + if (repeat = '1' and regs.reg_cx = 0) then + repeat <= '0'; + endRepeat := '1'; + prefixIP <= (others => '0'); + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + newExeDelay := newExeDelay + 1; + exeDone := '1'; + if (opcodeNext /= OP_INVALID) then newExeDelay := newExeDelay + 2 + to_integer('0'&opsize); end if; + else + + case (opstep) is + when 0 => + if (ce = '1') then + opstep <= 1; + varmemSegment := regs.reg_ds; + if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; + if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; + if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; + if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; + bus_read <= '1'; + bus_write <= '0'; + if (memFirst = '0') then + bus_addr <= resize(varmemSegment * 16 + regs.reg_si + 1, 20); + else + bus_addr <= resize(varmemSegment * 16 + regs.reg_si, 20); + end if; + prefetchAllow <= '0'; + end if; + + when 1 => opstep <= 2; + + when 2 => + opstep <= 0; + memFirst <= '0'; + if (wordAligned = '1') then + stringLoad(15 downto 0) <= unsigned(bus_dataread(15 downto 0)); + elsif (opsize = '0' or memFirst = '1') then + stringLoad(7 downto 0) <= unsigned(bus_dataread(7 downto 0)); + if (opsize = '0') then stringLoad(15 downto 8) <= x"00"; end if; + else + stringLoad(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); + end if; + if (opsize = '0' or memFirst = '0' or wordAligned = '1') then + if (regs.FlagDir) then + regs.reg_si <= regs.reg_si - 1 - to_integer('0'&opsize); + else + regs.reg_si <= regs.reg_si + 1 + to_integer('0'&opsize); + end if; + + if (opcodeNext /= OP_INVALID) then + opcode <= opcodeNext; + opcodeNext <= OP_INVALID; + memFirst <= '1'; + else + exeDone := '1'; + if (repeat = '1') then + regs.reg_cx <= regs.reg_cx - 1; + if (regs.reg_cx = 1) then + repeat <= '0'; + endRepeat := '1'; + prefixIP <= (others => '0'); + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + end if; + end if; + end if; + end if; + + when others => null; + end case; + + end if; + + when OP_STRINGCOMPARE => + if (opsize = '1') then + wordAligned := (not regs.reg_di(0)); + else + wordAligned := '0'; + end if; + + if (repeat = '1' and regs.reg_cx = 0) then + repeat <= '0'; + endRepeat := '1'; + prefixIP <= (others => '0'); + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + exeDone := '1'; + else + + case (opstep) is + when 0 => + if (ce = '1') then + opstep <= 1; + bus_read <= '1'; + bus_write <= '0'; + if (memFirst = '0') then + bus_addr <= resize(regs.reg_es * 16 + regs.reg_di + 1, 20); + else + bus_addr <= resize(regs.reg_es * 16 + regs.reg_di, 20); + end if; + prefetchAllow <= '0'; + end if; + + when 1 => opstep <= 2; + + when 2 => + memFirst <= '0'; + if (wordAligned = '1') then + stringLoad2(15 downto 0) <= unsigned(bus_dataread(15 downto 0)); + elsif (opsize = '0' or memFirst = '1') then + stringLoad2(7 downto 0) <= unsigned(bus_dataread(7 downto 0)); + if (opsize = '0') then stringLoad2(15 downto 8) <= x"00"; end if; + else + stringLoad2(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); + end if; + if (opsize = '0' or memFirst = '0' or wordAligned = '1') then + opstep <= 3; + aluop <= ALU_OP_CMP; + else + opstep <= 0; + end if; + + when 3 => + if (ce = '1') then + exeDone := '1'; + if (regs.FlagDir) then + regs.reg_di <= regs.reg_di - 1 - to_integer('0'&opsize); + else + regs.reg_di <= regs.reg_di + 1 + to_integer('0'&opsize); + end if; + if (repeat = '1') then + regs.reg_cx <= regs.reg_cx - 1; + if (regs.reg_cx = 1 or (repeatZero = '0' and regs.FlagZer = '1') or (repeatZero = '1' and regs.FlagZer = '0')) then + repeat <= '0'; + endRepeat := '1'; + prefixIP <= (others => '0'); + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + end if; + end if; + end if; + + + when others => null; + end case; + + end if; + + when OP_STRINGSTORE => + if (opsize = '1') then + wordAligned := (not regs.reg_di(0)); + else + wordAligned := '0'; + end if; + if (repeat = '1' and regs.reg_cx = 0) then + repeat <= '0'; + endRepeat := '1'; + prefixIP <= (others => '0'); + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + newExeDelay := newExeDelay + 1; + exeDone := '1'; + else + prefetchAllow <= '0'; + if (bus_read = '0' and bus_write = '0' and (waitexe = '0' or ce = '1')) then + memFirst <= '0'; + waitexe <= '1'; + + bus_read <= '0'; + bus_write <= '1'; + bus_be <= "01"; + if (wordAligned = '1') then + bus_datawrite <= std_logic_vector(resultval(15 downto 0)); + bus_addr <= resize(regs.reg_es * 16 + regs.reg_di, 20); + bus_be <= "11"; + elsif (memFirst = '0') then + bus_datawrite <= x"00" & std_logic_vector(resultval(15 downto 8)); + bus_addr <= resize(regs.reg_es * 16 + regs.reg_di + 1, 20); + else + bus_datawrite <= x"00" & std_logic_vector(resultval(7 downto 0)); + bus_addr <= resize(regs.reg_es * 16 + regs.reg_di, 20); + end if; + + if (opsize = '0' or memFirst = '0' or wordAligned = '1') then + exeDone := '1'; + if (regs.FlagDir) then + regs.reg_di <= regs.reg_di - 1 - to_integer('0'&opsize); + else + regs.reg_di <= regs.reg_di + 1 + to_integer('0'&opsize); + end if; + if (repeat = '1') then + regs.reg_cx <= regs.reg_cx - 1; + if (regs.reg_cx = 1) then + repeat <= '0'; + endRepeat := '1'; + prefixIP <= (others => '0'); + regs.reg_ip <= regs.reg_ip + 1; + consumePrefetch <= 1; + end if; + end if; + end if; + elsif (waitexe = '1' and ce = '1') then + waitexe <= '0'; + end if; + end if; + + when OP_ENTER => + case (opstep) is + when 0 => + regs.reg_bp <= regs.reg_sp; + regs.reg_sp <= regs.reg_sp - fetch1Val; + opstep <= 1; + if (fetch2Val(4 downto 0) = 0) then + exeDone := '1'; + end if; + + when 1 => + if (ce = '1') then + opstep <= 2; + varmemSegment := regs.reg_ds; + if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; + if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; + if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; + if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; + bus_read <= '1'; + bus_write <= '0'; + if (memFirst = '1') then + bus_addr <= resize(varmemSegment * 16 + regs.reg_bp - (enterCnt * 2), 20); + else + bus_addr <= resize(varmemSegment * 16 + regs.reg_bp - (enterCnt * 2) + 1, 20); + end if; + prefetchAllow <= '0'; + end if; + + when 2 => opstep <= 3; + + when 3 => + memFirst <= '0'; + if (memFirst = '1') then + memFetchValue1(7 downto 0) <= unsigned(bus_dataread(7 downto 0)); + else + memFetchValue1(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); + end if; + if (memFirst = '0') then + enterCnt <= enterCnt + 1; + if (enterCnt = fetch2Val(4 downto 0)) then + pushlist <= REGPOS_bp; + opcode <= OP_NOP; + cpustage <= CPUSTAGE_PUSH; + else + pushlist <= REGPOS_mem; + cpustage <= CPUSTAGE_PUSH; + opstep <= 1; + memFirst <= '1'; + end if; + end if; + + when others => null; + + end case; + + when OP_JUMPIF => + cond := '0'; + case (opcodebyte) is + when x"70" => if (regs.FlagOvf = '1' ) then cond := '1'; end if; + when x"71" => if (regs.FlagOvf = '0' ) then cond := '1'; end if; + when x"72" => if (regs.FlagCar = '1' ) then cond := '1'; end if; + when x"73" => if (regs.FlagCar = '0' ) then cond := '1'; end if; + when x"74" => if (regs.FlagZer = '1' ) then cond := '1'; end if; + when x"75" => if (regs.FlagZer = '0' ) then cond := '1'; end if; + when x"76" => if (regs.FlagZer = '1' or regs.FlagCar = '1' ) then cond := '1'; end if; + when x"77" => if (regs.FlagZer = '0' and regs.FlagCar = '0' ) then cond := '1'; end if; + when x"78" => if (regs.FlagSgn = '1' ) then cond := '1'; end if; + when x"79" => if (regs.FlagSgn = '0' ) then cond := '1'; end if; + when x"7A" => if (regs.FlagPar = '1' ) then cond := '1'; end if; + when x"7B" => if (regs.FlagPar = '0' ) then cond := '1'; end if; + when x"7C" => if (regs.FlagSgn /= regs.FlagOvf and regs.FlagZer = '0') then cond := '1'; end if; + when x"7D" => if (regs.FlagSgn = regs.FlagOvf or regs.FlagZer = '1') then cond := '1'; end if; + when x"7E" => if (regs.FlagSgn /= regs.FlagOvf or regs.FlagZer = '1') then cond := '1'; end if; + when x"7F" => if (regs.FlagSgn = regs.FlagOvf and regs.FlagZer = '0') then cond := '1'; end if; + when x"E0" => if (regs.reg_cx /= 1 and regs.FlagZer = '0') then cond := '1'; end if; regs.reg_cx <= regs.reg_cx - 1; + when x"E1" => if (regs.reg_cx /= 1 and regs.FlagZer = '1') then cond := '1'; end if; regs.reg_cx <= regs.reg_cx - 1; + when x"E2" => if (regs.reg_cx /= 1) then cond := '1'; end if; regs.reg_cx <= regs.reg_cx - 1; + when x"E3" => if (regs.reg_cx = 0) then cond := '1'; end if; + when x"EB" => cond := '1'; + when others => null; + end case; + if (cond = '1') then + jumpNow := '1'; + jumpAddr := to_unsigned(to_integer(regs.reg_ip) + to_integer(signed(source1Val(7 downto 0))), 16); + end if; + exeDone := '1'; + + when OP_JUMP => + jumpNow := '1'; + jumpAddr := regs.reg_ip + source1Val; + clearPrefetch <= '1'; + exeDone := '1'; + + when OP_JUMPABS => + jumpNow := '1'; + jumpAddr := source1Val; + clearPrefetch <= '1'; + exeDone := '1'; + + when OP_JUMPFAR => + jumpNow := '1'; + jumpAddr := source1Val; + regs.reg_cs <= source2Val; + clearPrefetch <= '1'; + exeDone := '1'; + + when OP_RETURNFAR => + regs.reg_sp <= regs.reg_sp + source1Val; + clearPrefetch <= '1'; + newExeDelay := newExeDelay + 3; + exeDone := '1'; + + when OP_IRQ => + regs.FlagBrk <= '0'; + regs.FlagIrq <= '0'; + regs.FlagMod <= '1'; + jumpNow := '1'; + jumpAddr := irqIP; + regs.reg_cs <= irqCS; + clearPrefetch <= '1'; + exeDone := '1'; + + when OP_IRQREQUEST => + irqrequest <= '1'; + irqvector <= source1Val(7 downto 0) & "00"; + cpustage <= CPUSTAGE_IDLE; + + when OP_FLAGSFROMACC => + regs.FlagCar <= regs.reg_ax(8); + regs.FlagPar <= regs.reg_ax(10); + regs.FlagHaC <= regs.reg_ax(12); + regs.FlagZer <= regs.reg_ax(14); + regs.FlagSgn <= regs.reg_ax(15); + exeDone := '1'; + + when OP_FLAGSTOACC => + regs.reg_ax(15 downto 8) <= Reg_f(7 downto 0); + exeDone := '1'; + + when OP_DIV => + if (opstep = 0 and ce = '1') then + delay <= 10; + opstep <= 1; + DIVstart <= '1'; + DIVdivisor <= '0' & x"0000" & signed(memFetchValue2); + if (opsize = '0') then + DIVdividend <= '0' & x"0000" & signed(regs.reg_ax); + else + DIVdividend <= '0' & signed(regs.reg_dx) & signed(regs.reg_ax); + end if; + elsif (ce = '1') then + exeDone := '1'; + if (memFetchValue2 = 0) then + irqrequest <= '1'; + irqvector <= (others => '0'); + else + if (opsize = '0') then + regs.reg_ax <= unsigned(DIVremainder(7 downto 0)) & unsigned(DIVquotient(7 downto 0)); + else + regs.reg_ax <= unsigned(DIVquotient(15 downto 0)); + regs.reg_dx <= unsigned(DIVremainder(15 downto 0)); + end if; + end if; + end if; + + when OP_DIVI => + if (opstep = 0 and ce = '1') then + delay <= 10; + opstep <= 1; + DIVstart <= '1'; + if (opsize = '0') then + DIVdividend <= resize(signed(regs.reg_ax), 33); + DIVdivisor <= resize(signed(memFetchValue2(7 downto 0)), 33); + else + DIVdividend <= resize(signed(regs.reg_dx & regs.reg_ax), 33); + DIVdivisor <= resize(signed(memFetchValue2), 33); + end if; + elsif (ce = '1') then + exeDone := '1'; + if (memFetchValue2 = 0) then + irqrequest <= '1'; + irqvector <= (others => '0'); + else + if (opsize = '0') then + regs.reg_ax <= unsigned(DIVremainder(7 downto 0)) & unsigned(DIVquotient(7 downto 0)); + else + regs.reg_ax <= unsigned(DIVquotient(15 downto 0)); + regs.reg_dx <= unsigned(DIVremainder(15 downto 0)); + end if; + end if; + end if; + + when OP_MULADJUST => + if (opstep = 0 and ce = '1') then + delay <= 10; + opstep <= 1; + DIVstart <= '1'; + DIVdividend <= '0' & x"000000" & signed(regs.reg_ax(7 downto 0)); + DIVdivisor <= to_signed(10, 33); + elsif (ce = '1') then + exeDone := '1'; + if (fetch1Val = 0) then + irqrequest <= '1'; + irqvector <= (others => '0'); + else + regs.reg_ax <= unsigned(DIVquotient(7 downto 0)) & unsigned(DIVremainder(7 downto 0)); + if (DIVremainder(7 downto 0) = 0 and DIVquotient(7 downto 0) = 0) then regs.FlagZer <= '1'; else regs.FlagZer <= '0'; end if; + regs.FlagSgn <= DIVremainder(7); + regs.FlagPar <= not(DIVremainder(7) xor DIVremainder(6) xor DIVremainder(5) xor DIVremainder(4) xor DIVremainder(3) xor DIVremainder(2) xor DIVremainder(1) xor DIVremainder(0)); + end if; + end if; + + when OP_DIVADJUST => + result8 := regs.reg_ax(7 downto 0) + resize(regs.reg_ax(15 downto 8) * 10, 8); + regs.reg_ax( 7 downto 0) <= result8; + regs.reg_ax(15 downto 8) <= x"00"; + if (result8 = 0) then regs.FlagZer <= '1'; else regs.FlagZer <= '0'; end if; + regs.FlagSgn <='0'; + regs.FlagPar <= not(result8(7) xor result8(6) xor result8(5) xor result8(4) xor result8(3) xor result8(2) xor result8(1) xor result8(0)); + exeDone := '1'; + + when others => + exeDone := '1'; + + end case; + + if (jumpNow = '1') then + regs.reg_ip <= jumpAddr; + clearPrefetch <= '1'; + if (jumpAddr(0) = '1') then + newExeDelay := newExeDelay + 4; + else + newExeDelay := newExeDelay + 3; + end if; + end if; + + if (exeDone = '1') then + delay <= newExeDelay; + if (newExeDelay = 0) then + cpu_done <= '1'; + else + cpu_finished <= '1'; + end if; + cpustage <= CPUSTAGE_IDLE; + if (repeat = '0' or endRepeat = '1') then + prefixSegmentES <= '0'; + prefixSegmentCS <= '0'; + prefixSegmentSS <= '0'; + prefixSegmentDS <= '0'; + end if; + end if; + + when others => + null; + + end case; + + end if; + + -- prefetch + varPrefetchCount := prefetchCount; + varprefetchBuffer := prefetchBuffer; + + case (prefetchState) is + + when PREFETCH_IDLE => + if (ce = '1' and prefetchCount < 14 and dma_active = '0' and sdma_request = '0') then + prefetchState <= PREFETCH_READ; + prefetchDisturb <= '0'; + end if; + + when PREFETCH_READ => + if (prefetchAllow = '1') then + prefetchAddrOld <= prefetchAddr; + prefetchState <= PREFETCH_WAIT; + bus_addr <= prefetchAddr; + bus_read <= '1'; + if (prefetchAddr(0) = '1') then + prefetchAddr <= PrefetchAddr + 1; + prefetch1byte <= '1'; + else + prefetchAddr <= PrefetchAddr + 2; + prefetch1byte <= '0'; + end if; + else + prefetchState <= PREFETCH_IDLE; + end if; + + when PREFETCH_WAIT => prefetchState <= PREFETCH_RECEIVE; + + when PREFETCH_RECEIVE => + prefetchState <= PREFETCH_IDLE; + if (prefetchAllow = '1' and dma_active = '0' and prefetchDisturb = '0') then + varprefetchBuffer((PrefetchCount * 8) + 7 downto (PrefetchCount * 8)) := bus_dataread(7 downto 0); + if (prefetch1byte = '0') then + varprefetchBuffer((PrefetchCount * 8) + 15 downto (PrefetchCount * 8) + 8) := bus_dataread(15 downto 8); + varPrefetchCount := varPrefetchCount + 2; + else + varPrefetchCount := varPrefetchCount + 1; + end if; + else + prefetchAddr <= prefetchAddrOld; + end if; + + end case; + + if (consumePrefetch = 1) then + varprefetchBuffer := x"00" & varprefetchBuffer(127 downto 8); + varPrefetchCount := varPrefetchCount - 1; + elsif (consumePrefetch = 2) then + varprefetchBuffer := x"0000" & varprefetchBuffer(127 downto 16); + varPrefetchCount := varPrefetchCount - 2; + elsif (consumePrefetch = 3) then + varprefetchBuffer := x"000000" & varprefetchBuffer(127 downto 24); + varPrefetchCount := varPrefetchCount - 3; + end if; + + prefetchCount <= varPrefetchCount; + prefetchBuffer <= varprefetchBuffer; + + if (clearPrefetch = '1') then + if (ce = '1') then + prefetchState <= PREFETCH_READ; + else + prefetchState <= PREFETCH_IDLE; + end if; + prefetchCount <= 0; + prefetchBuffer <= (others => '0'); + prefetchAddr <= resize(regs.reg_cs * 16 + regs.reg_ip, 20); + end if; + + end if; + end if; + end process; + + idivider : entity work.divider + port map + ( + clk => clk, + start => DIVstart, + done => open, + busy => open, + dividend => DIVdividend, + divisor => DIVdivisor, + quotient => DIVquotient, + remainder => DIVremainder + ); + + cpu_export_reg_cs <= regs.reg_cs; + cpu_export_reg_ip <= regs.reg_ip; + cpu_export_opcode <= opcodebyte; + +end architecture; + + + + + + + + + + + + diff --git a/modules/cpu-v30/divider.vhd b/modules/cpu-v30/divider.vhd new file mode 100644 index 0000000..2335913 --- /dev/null +++ b/modules/cpu-v30/divider.vhd @@ -0,0 +1,123 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity divider is + port + ( + clk : in std_logic; + start : in std_logic; + done : out std_logic := '0'; + busy : out std_logic := '0'; + dividend : in signed(32 downto 0); + divisor : in signed(32 downto 0); + quotient : out signed(32 downto 0); + remainder : out signed(32 downto 0) + ); +end entity; + +architecture arch of divider is + + constant bits_per_cycle : integer := 1; + + signal dividend_u : unsigned(dividend'length downto 0); + signal divisor_u : unsigned(divisor'length downto 0); + signal quotient_u : unsigned(quotient'length downto 0); + signal Akku : unsigned (divisor'left + 1 downto divisor'right); + signal QPointer : integer range quotient_u'range; + signal done_buffer : std_logic := '0'; + +begin + + process (clk) is + variable XPointer : integer range dividend_u'range; + variable QPointerNew : integer range quotient_u'range; + variable AkkuNew : unsigned (divisor'left + 1 downto divisor'right); + variable Rdy_i : std_logic; + variable Q_bits : std_logic_vector(bits_per_cycle-1 downto 0); + variable Diff : unsigned (AkkuNew'range); + begin + if rising_edge(clk) then + + done_buffer <= '0'; + busy <= '0'; + + -- == Initialize loop =============================================== + if start = '1' then + + busy <= '1'; + + dividend_u <= '0' & unsigned(abs(dividend)); + divisor_u <= '0' & unsigned(abs(divisor)); + + QPointerNew := quotient_u'left; + XPointer := dividend_u'left; + Rdy_i := '0'; + --AkkuNew := (Akku'left downto 1 => '0') & dividend(XPointer); + AkkuNew := (others => '0'); + -- == Repeat for every Digit in Q =================================== + elsif Rdy_i = '0' then + busy <= '1'; + AkkuNew := Akku; + QPointerNew := QPointer; + + for i in 1 to bits_per_cycle loop + + -- Calculate output digit and new Akku --------------------------- + Diff := AkkuNew - divisor_u; + if Diff(Diff'left) = '0' then -- Does Y fit in Akku? + Q_bits(bits_per_cycle-i) := '1'; -- YES: Digit is '1' + AkkuNew := unsigned(shift_left(Diff,1));-- Diff -> Akku + else -- + Q_bits(bits_per_cycle-i) := '0'; -- NO : Digit is '0' + AkkuNew := unsigned(Shift_left(AkkuNew,1));-- Shift Akku + end if; + -- --------------------------------------------------------------- + if XPointer > dividend'right then -- divisor read completely? + XPointer := XPointer - 1; -- NO : Put next digit + AkkuNew(AkkuNew'right) := dividend_u(XPointer); -- in Akku + else + AkkuNew(AkkuNew'right) := '0' ; -- YES: Read Zeros (post point) + end if; + -- --------------------------------------------------------------- + if QPointerNew > quotient'right then -- Has this been the last cycle? + QPointerNew := QPointerNew - 1; -- NO : Prepare next cycle + else -- + Rdy_i := '1'; -- YES: work done + done_buffer <= '1'; + end if; + + end loop; + + quotient_u(QPointer downto QPointer-(bits_per_cycle-1)) <= unsigned(Q_bits); + end if; + + QPointer <= QPointerNew; + Akku <= AkkuNew; + + if ((dividend(dividend'left) xor divisor(divisor'left)) = '1') then + quotient <= -signed(quotient_u(quotient'left downto 0)); + else + quotient <= signed(quotient_u(quotient'left downto 0)); + end if; + if (dividend(dividend'left) = '1') then + remainder <= -signed(AkkuNew(remainder'left + 1 downto remainder'right + 1)); + else + remainder <= signed(AkkuNew(remainder'left + 1 downto remainder'right + 1)); + end if; + + done <= done_buffer; + + end if; + + + + end process; + + +end architecture; + + + + + diff --git a/modules/cpu-v30/export.vhd b/modules/cpu-v30/export.vhd new file mode 100644 index 0000000..95ec2b6 --- /dev/null +++ b/modules/cpu-v30/export.vhd @@ -0,0 +1,221 @@ +----------------------------------------------------------------- +--------------- Export Package -------------------------------- +----------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +package pexport is + + type cpu_export_type is record + reg_ax : unsigned(15 downto 0); + reg_cx : unsigned(15 downto 0); + reg_dx : unsigned(15 downto 0); + reg_bx : unsigned(15 downto 0); + reg_sp : unsigned(15 downto 0); + reg_bp : unsigned(15 downto 0); + reg_si : unsigned(15 downto 0); + reg_di : unsigned(15 downto 0); + reg_es : unsigned(15 downto 0); + reg_cs : unsigned(15 downto 0); + reg_ss : unsigned(15 downto 0); + reg_ds : unsigned(15 downto 0); + reg_ip : unsigned(15 downto 0); + reg_f : unsigned(15 downto 0); + opcodebyte_last : std_logic_vector(7 downto 0); + end record; + +end package; + +----------------------------------------------------------------- +--------------- Export module -------------------------------- +----------------------------------------------------------------- + + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use STD.textio.all; + +use work.pexport.all; + +entity export is + port + ( + clk : in std_logic; + ce : in std_logic; + reset : in std_logic; + + new_export : in std_logic; + export_cpu : in cpu_export_type; + + export_irq : in std_logic_vector(7 downto 0); + + export_8 : in std_logic_vector(7 downto 0); + export_16 : in std_logic_vector(15 downto 0); + export_32 : in std_logic_vector(31 downto 0) + ); +end entity; + +architecture arch of export is + + signal totalticks : unsigned(31 downto 0) := (others => '0'); + signal cyclenr : unsigned(31 downto 0) := x"00000001"; + + signal reset_1 : std_logic := '0'; + signal export_reset : std_logic := '0'; + signal exportnow : std_logic; + + function to_lower(c: character) return character is + variable l: character; + begin + case c is + when 'A' => l := 'a'; + when 'B' => l := 'b'; + when 'C' => l := 'c'; + when 'D' => l := 'd'; + when 'E' => l := 'e'; + when 'F' => l := 'f'; + when 'G' => l := 'g'; + when 'H' => l := 'h'; + when 'I' => l := 'i'; + when 'J' => l := 'j'; + when 'K' => l := 'k'; + when 'L' => l := 'l'; + when 'M' => l := 'm'; + when 'N' => l := 'n'; + when 'O' => l := 'o'; + when 'P' => l := 'p'; + when 'Q' => l := 'q'; + when 'R' => l := 'r'; + when 'S' => l := 's'; + when 'T' => l := 't'; + when 'U' => l := 'u'; + when 'V' => l := 'v'; + when 'W' => l := 'w'; + when 'X' => l := 'x'; + when 'Y' => l := 'y'; + when 'Z' => l := 'z'; + when others => l := c; + end case; + return l; + end to_lower; + + function to_lower(s: string) return string is + variable lowercase: string (s'range); + begin + for i in s'range loop + lowercase(i):= to_lower(s(i)); + end loop; + return lowercase; + end to_lower; + +begin + +-- synthesis translate_off + process(clk) + begin + if rising_edge(clk) then + if (reset = '1') then + totalticks <= (others => '0'); + elsif (ce = '1') then + totalticks <= totalticks + 1; + end if; + reset_1 <= reset; + end if; + end process; + + export_reset <= '1' when (reset = '0' and reset_1 = '1') else '0'; + + exportnow <= export_reset or new_export; + + process + + file outfile: text; + file outfile_irp: text; + variable f_status: FILE_OPEN_STATUS; + variable line_out : line; + variable recordcount : integer := 0; + + constant filenamebase : string := "R:\\debug_sim"; + variable filename_current : string(1 to 25); + + begin + + filename_current := filenamebase & "00000000.txt"; + + file_open(f_status, outfile, filename_current, write_mode); + file_close(outfile); + file_open(f_status, outfile, filename_current, append_mode); + + write(line_out, string'("IP F AX BX CX DX SP BP SI DI ES CS SS DS OP TICKS IQ GPU D8 D16 D32")); + writeline(outfile, line_out); + + while (true) loop + wait until rising_edge(clk); + if (reset = '1') then + cyclenr <= x"00000001"; + filename_current := filenamebase & "00000000.txt"; + file_close(outfile); + file_open(f_status, outfile, filename_current, write_mode); + file_close(outfile); + file_open(f_status, outfile, filename_current, append_mode); + write(line_out, string'("IP F AX BX CX DX SP BP SI DI ES CS SS DS OP TICKS IQ GPU D8 D16 D32")); + writeline(outfile, line_out); + end if; + + if (exportnow = '1') then + + write(line_out, to_lower(to_hstring(export_cpu.reg_ip)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_f )) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_ax)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_bx)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_cx)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_dx)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_sp)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_bp)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_si)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_di)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_es)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_cs)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_ss)) & " "); + write(line_out, to_lower(to_hstring(export_cpu.reg_ds)) & " "); + + write(line_out, to_lower(to_hstring(export_cpu.opcodebyte_last)) & " "); + write(line_out, to_lower(to_hstring(totalticks)) & " "); + + write(line_out, to_lower(to_hstring(export_irq )) & " "); + write(line_out, to_lower(to_hstring(to_unsigned(0, 12))) & " "); -- gpu + + write(line_out, to_lower(to_hstring(export_8 )) & " "); + write(line_out, to_lower(to_hstring(export_16)) & " "); + write(line_out, to_lower(to_hstring(export_32)) & " "); + + writeline(outfile, line_out); + + cyclenr <= cyclenr + 1; + + if (cyclenr mod 10000000 = 0) then + filename_current := filenamebase & to_hstring(cyclenr) & ".txt"; + file_close(outfile); + file_open(f_status, outfile, filename_current, write_mode); + file_close(outfile); + file_open(f_status, outfile, filename_current, append_mode); + write(line_out, string'("IP F AX BX CX DX SP BP SI DI ES CS SS DS OP TICKS IQ GPU D8 D16 D32")); + writeline(outfile, line_out); + end if; + + end if; + + end loop; + + end process; +-- synthesis translate_on + +end architecture; + + + + + diff --git a/modules/cpu-v30/index.qip b/modules/cpu-v30/index.qip new file mode 100644 index 0000000..c6f8103 --- /dev/null +++ b/modules/cpu-v30/index.qip @@ -0,0 +1,9 @@ +# ============================================================================== +# Quartus Prime QIP Index File +# ============================================================================== +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "bus_savestates.vhd"] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "cpu.vhd"] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "divider.vhd"] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "export.vhd"] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "registerpackage.vhd"] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "reg_savestates.vhd"] diff --git a/modules/cpu-v30/reg_savestates.vhd b/modules/cpu-v30/reg_savestates.vhd new file mode 100644 index 0000000..50a96ad --- /dev/null +++ b/modules/cpu-v30/reg_savestates.vhd @@ -0,0 +1,37 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.pBus_savestates.all; + +package pReg_savestates is + + -- ( adr upper lower size default) + + -- cpu + constant REG_SAVESTATE_CPU1 : savestate_type := ( 0, 63, 0, 1, x"0000000000000000"); -- DX_CX_AX_IP + constant REG_SAVESTATE_CPU2 : savestate_type := ( 1, 63, 0, 1, x"0000000020000000"); -- SI_BP_SP_BX + constant REG_SAVESTATE_CPU3 : savestate_type := ( 2, 63, 0, 1, x"0000FFFF00000000"); -- SS_CS_ES_DI + constant REG_SAVESTATE_CPU4 : savestate_type := ( 3, 31, 0, 1, x"00000000F0020000"); -- F_DS + + constant REG_SAVESTATE_IRQ : savestate_type := ( 5, 7, 0, 1, x"0000000000000000"); + + constant REG_SAVESTATE_GPU : savestate_type := ( 7, 15, 0, 1, x"0000000000009EFF"); + + constant REG_SAVESTATE_DMA : savestate_type := ( 11, 59, 0, 1, x"0000000000000000"); + + constant REG_SAVESTATE_SOUND3 : savestate_type := ( 15, 10, 0, 1, x"0000000000000000"); + constant REG_SAVESTATE_SOUND4 : savestate_type := ( 16, 19, 0, 1, x"0000000000000000"); + constant REG_SAVESTATE_SOUNDDMA : savestate_type := ( 17, 59, 0, 1, x"0000000000000000"); + + constant REG_SAVESTATE_EEPROMINT : savestate_type := ( 19, 16, 0, 1, x"0000000000000000"); + constant REG_SAVESTATE_EEPROMEXT : savestate_type := ( 21, 16, 0, 1, x"0000000000000000"); + + constant REG_SAVESTATE_MIXED : savestate_type := ( 23, 0, 0, 1, x"0000000000000000"); + + constant REG_SAVESTATE_TIMER : savestate_type := ( 27, 35, 0, 1, x"0000000000000000"); + + + + +end package; diff --git a/modules/cpu-v30/registerpackage.vhd b/modules/cpu-v30/registerpackage.vhd new file mode 100644 index 0000000..021e86b --- /dev/null +++ b/modules/cpu-v30/registerpackage.vhd @@ -0,0 +1,119 @@ +----------------------------------------------------------------- +--------------- Bus Package -------------------------------- +----------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +package pRegisterBus is + + constant BUS_buswidth : integer := 8; + constant BUS_busadr : integer := 8; + + type regaccess_type is + ( + readwrite, + readonly, + writeonly, + writeDone -- writeonly, but does send back done, so it is not dead + ); + + type regmap_type is record + Adr : integer range 0 to (2**BUS_busadr)-1; + upper : integer range 0 to BUS_buswidth-1; + lower : integer range 0 to BUS_buswidth-1; + size : integer range 0 to (2**BUS_busadr)-1; + defval : integer; + acccesstype : regaccess_type; + end record; + +end package; + + +----------------------------------------------------------------- +--------------- Reg Interface ---------------------------------- +----------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library work; +use work.pRegisterBus.all; + +entity eReg is + generic + ( + Reg : regmap_type; + index : integer := 0 + ); + port + ( + clk : in std_logic; + BUS_Din : in std_logic_vector(BUS_buswidth-1 downto 0); + BUS_Adr : in std_logic_vector(BUS_busadr-1 downto 0); + BUS_wren : in std_logic; + BUS_rst : in std_logic; + BUS_Dout : out std_logic_vector(BUS_buswidth-1 downto 0) := (others => '0'); + Din : in std_logic_vector(Reg.upper downto Reg.lower); + Dout : out std_logic_vector(Reg.upper downto Reg.lower); + written : out std_logic := '0' + ); +end entity; + +architecture arch of eReg is + + signal Dout_buffer : std_logic_vector(Reg.upper downto Reg.lower) := std_logic_vector(to_unsigned(Reg.defval,Reg.upper-Reg.lower+1)); + + signal AdrI : std_logic_vector(BUS_Adr'left downto 0); + +begin + + AdrI <= std_logic_vector(to_unsigned(Reg.Adr + index, BUS_Adr'length)); + + process (clk) + begin + if rising_edge(clk) then + + if (BUS_rst = '1') then + + Dout_buffer <= std_logic_vector(to_unsigned(Reg.defval,Reg.upper-Reg.lower+1)); + + else + + if (BUS_Adr = AdrI and BUS_wren = '1') then + for i in Reg.lower to Reg.upper loop + Dout_buffer(i) <= BUS_Din(i); + end loop; + end if; + + end if; + + end if; + end process; + + Dout <= Dout_buffer; + + written <= '1' when (BUS_Adr = AdrI and BUS_wren = '1') else '0'; + + goutputbit: for i in Reg.lower to Reg.upper generate + BUS_Dout(i) <= Din(i) when BUS_Adr = AdrI else '0'; + end generate; + + glowzero_required: if Reg.lower > 0 generate + glowzero: for i in 0 to Reg.lower - 1 generate + BUS_Dout(i) <= '0'; + end generate; + end generate; + + ghighzero_required: if Reg.upper < BUS_buswidth-1 generate + ghighzero: for i in Reg.upper + 1 to BUS_buswidth-1 generate + BUS_Dout(i) <= '0'; + end generate; + end generate; + +end architecture; + + + diff --git a/modules/sound-jt51/LICENSE b/modules/sound-jt51/LICENSE new file mode 100644 index 0000000..9cecc1d --- /dev/null +++ b/modules/sound-jt51/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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 . + +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: + + {project} Copyright (C) {year} {fullname} + 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 +. + + 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 +. diff --git a/modules/sound-jt51/README.md b/modules/sound-jt51/README.md new file mode 100644 index 0000000..4b12e51 --- /dev/null +++ b/modules/sound-jt51/README.md @@ -0,0 +1,67 @@ +# JT51 +YM2151 clone in verilog. FPGA proven. +(c) Jose Tejada 2016. Twitter: @topapate + +You can show your appreciation through +* [Patreon](https://patreon.com/jotego), by supporting releases +* [Paypal](https://paypal.me/topapate), with a donation + +Originally posted in opencores. The Github repository is now the main one. + +## Using JT51 in a git project + +If you are using JT51 in a git project, the best way to add it to your project is: + +1. Optionally fork JT51's repository to your own GitHub account +2. Add it as a submodule to your git project: `git submodule add https://github.com/jotego/jt51.git` +3. Now you can refer to the RTL files in **jt51/hdl** + +The advantages of a using a git submodule are: + +1. Your project contains a reference to a commit of the JT51 repository +2. As long as you do not manually update the JT51 submodule, it will keep pointing to the same commit +3. Each time you make a commit in your project, it will include a pointer to the JT51 commit used. So you will always know the JT51 that worked for you +4. If JT51 is updated and you want to get the changes, simply update the submodule using git. The new JT51 commit used will be annotated in your project's next commit. So the history of your project will reflect that change too. +5. JT51 files will be intact and you will use the files without altering them. + +## Folders + +* **jt51/doc** contains documentation related to JT51 and YM2151 +* **jt51/hdl** contains all the Verilog source code to implement JT51 on FPGA or ASIC +* **jt51/hdl/filter** contains an interpolator to use as first stage to on-chip sigma-delta DACs +* **jt51/syn** contains some use case examples. It has synthesizable projects in various platforms +* **jt51/syn/xilinx/contra** sound board of the arcade Contra. Checkout **hdl** subfolder for the verilog files + +## Usage +All files are in **jt51/hdl**. The top level file is jt51.v. You need all files in the **jt51/hdl** folder to synthesize or simulate the design. + +Alternatively you can just use the file jt51_v1.1.v at the release folder. It contains all the necessary files concatenated inside. It is generated by the script in bin/jt51_singlefile.sh + +Simulation modules are added if macros + - SIMULATION + - JT51_DEBUG +are defined + +Use macro JT51_ONLYTIMERS in order to avoid simulating the FM signal chain but keep the timer modules working. This is useful if a CPU depends on the timer interrupts but you do not want to simulate the full FM sound (to speed up sims). + +## Related Projects + +Other sound chips from the same author + +Chip | Repository +-----------------------|------------ +YM2203, YM2612, YM2610 | [JT12](https://github.com/jotego/jt12) +YM2151 | [JT51](https://github.com/jotego/jt51) +YM3526 | [JTOPL](https://github.com/jotego/jtopl) +YM2149 | [JT49](https://github.com/jotego/jt49) +sn76489an | [JT89](https://github.com/jotego/jt89) +OKI 6295 | [JT6295](https://github.com/jotego/jt6295) +OKI MSM5205 | [JT5205](https://github.com/jotego/jt5205) + +This sound core has been used at least in the following arcade cores for FPGA + +* [JTCPS1](https://github.com/jotego/jtcps1): CAPCOM SYSTEM arcade clone +* [JTDD](https://github.com/jotego/jtdd): Double Dragon 1 & 2 arcade clone +* [JTGNG](https://github.com/jotego/jt_gng): arcade clones of pre-CPS CAPCOM games. Some use YM2151 through JT51 + +More to come soon! diff --git a/modules/sound-jt51/filter/jt51_dac2.v b/modules/sound-jt51/filter/jt51_dac2.v new file mode 100644 index 0000000..99069d2 --- /dev/null +++ b/modules/sound-jt51/filter/jt51_dac2.v @@ -0,0 +1,63 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 9th 2017 + */ + +`timescale 1ns / 1ps + +/* + + input sampling rate must be the same as clk frequency + interpolate input signal accordingly to get the + right sampling rate. + + Refer to sigmadelta.ods to see how the internal width (int_w) + was determined. + +*/ + +module jt51_dac2 #(parameter width=16) +( + input clk, + input rst, + input signed [width-1:0] din, + output reg dout +); + +parameter int_w = width+5; + +reg [int_w-1:0] y, error, error_1, error_2; + +wire [width-1:0] undin = { ~din[width-1], din[width-2:0] }; + +always @(*) begin + y <= undin + { error_1, 1'b0} - error_2; + dout <= ~y[int_w-1]; + error <= y - {dout, {width{1'b0}}}; +end + +always @(posedge clk) + if( rst ) begin + error_1 <= {int_w{1'b0}}; + error_2 <= {int_w{1'b0}}; + end else begin + error_1 <= error; + error_2 <= error_1; + end + +endmodule diff --git a/modules/sound-jt51/filter/jt51_fir.v b/modules/sound-jt51/filter/jt51_fir.v new file mode 100644 index 0000000..c0b6c1b --- /dev/null +++ b/modules/sound-jt51/filter/jt51_fir.v @@ -0,0 +1,189 @@ +/* This file is part of jt51. + + jt51 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. + + jt51 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 jt51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 7th 2017 + */ + +`timescale 1ns / 1ps + +module jt51_fir +#(parameter data_width=9, output_width=12, coeff_width=9, + addr_width=7, stages=81, acc_extra=1) +( + input clk, + input rst, + input sample, + input signed [data_width-1:0] left_in, + input signed [data_width-1:0] right_in, + input signed [coeff_width-1:0] coeff, + output reg [addr_width-1:0] cnt, + output reg signed [output_width-1:0] left_out, + output reg signed [output_width-1:0] right_out, + output reg sample_out +); + +wire signed [data_width-1:0] mem_left, mem_right; + +// pointers +reg [addr_width-1:0] addr_left, addr_right, + forward, rev, in_pointer; + + +reg update, last_sample; + +reg [1:0] state; +parameter IDLE=2'b00, LEFT=2'b01, RIGHT=2'b10; + +jt51_fir_ram #(.data_width(data_width),.addr_width(addr_width)) chain_left( + .clk ( clk ), + .data ( left_in ), + .addr ( addr_left ), + .we ( update ), + .q ( mem_left ) +); + +jt51_fir_ram #(.data_width(data_width),.addr_width(addr_width)) chain_right( + .clk ( clk ), + .data ( right_in ), + .addr ( addr_right), + .we ( update ), + .q ( mem_right) +); + + +always @(posedge clk) + if( rst ) + { update, last_sample } <= 2'b00; + else begin + last_sample <= sample; + update <= sample && !last_sample; + end + +parameter mac_width=(data_width+1)+coeff_width; +parameter acc_width=output_width; // mac_width+3; +reg signed [acc_width-1:0] acc_left, acc_right; + +//integer acc,mac; +wire [addr_width-1:0] next = cnt+1'b1; + +reg signed [data_width:0] sum; + +wire last_stage = cnt==(stages-1)/2; + +reg signed [data_width-1:0] buffer_left, buffer_right; + +always @(*) begin + if( state==LEFT) begin + if( last_stage ) + sum = buffer_left; + else + sum = buffer_left + mem_left; + end + else begin + if( last_stage ) + sum = buffer_right; + else + sum = buffer_right + mem_right; + end +end + +wire signed [mac_width-1:0] mac = coeff*sum; +wire signed [acc_width-1:0] mac_trim = mac[mac_width-1:mac_width-acc_width]; +//wire signed [acc_width-1:0] mac_trimx = (coeff*sum)>>>(mac_width-acc_width); + +wire [addr_width-1:0] + in_pointer_next = in_pointer - 1'b1, + forward_next = forward+1'b1, + rev_next = rev-1'b1; + +always @(*) begin + case( state ) + default: begin + addr_left = update ? rev : in_pointer; + addr_right= in_pointer; + end + LEFT: begin + addr_left = forward_next; + addr_right= rev; + end + RIGHT: begin + if( cnt==(stages-1)/2 ) begin + addr_left = in_pointer_next; + addr_right= in_pointer_next; + end + else begin + addr_left = rev_next; + addr_right= forward; + end + end + endcase +end + +always @(posedge clk) +if( rst ) begin + sample_out <= 1'b0; + state <= IDLE; + in_pointer <= 7'd0; + //addr_left <= in_pointer; + //addr_right<= in_pointer; +end else begin + case(state) + default: begin + if( update ) begin + state <= LEFT; + buffer_left <= left_in; + //addr_left <= rev; + end + cnt <= 6'd0; + acc_left <= {acc_width{1'b0}}; + acc_right <= {acc_width{1'b0}}; + rev <= in_pointer+stages-1'b1; + forward <= in_pointer; + sample_out <= 1'b0; + end + LEFT: begin + acc_left <= acc_left + mac_trim; + //addr_left <= forward_next; + + buffer_right <= mem_right; + //addr_right <= rev; + + forward<=forward_next; + state <= RIGHT; + end + RIGHT: + if( cnt==(stages-1)/2 ) begin + left_out <= acc_left; + right_out <= acc_right + mac_trim; + sample_out <= 1'b1; + in_pointer <= in_pointer_next; + //addr_left <= in_pointer_next; + //addr_right<= in_pointer_next; + state <= IDLE; + end else begin + acc_right <= acc_right + mac_trim; + //addr_right <= forward; + + buffer_left <= mem_left; + //addr_left <= rev_next; + cnt<=next; + rev<=rev-1'b1; + state <= LEFT; + end + endcase +end +endmodule // jt51_fir8 \ No newline at end of file diff --git a/modules/sound-jt51/filter/jt51_fir4.v b/modules/sound-jt51/filter/jt51_fir4.v new file mode 100644 index 0000000..b343f4d --- /dev/null +++ b/modules/sound-jt51/filter/jt51_fir4.v @@ -0,0 +1,83 @@ +/* This file is part of jt51. + + jt51 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. + + jt51 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 jt51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 7th 2017 + */ + +`timescale 1ns / 1ps + +module jt51_fir4 +#(parameter data_width=9, output_width=12) +( + input clk, + input rst, + input sample, + input signed [data_width-1:0] left_in, + input signed [data_width-1:0] right_in, + output signed [output_width-1:0] left_out, + output signed [output_width-1:0] right_out, + output sample_out +); + +parameter coeff_width=9; +parameter stages=21; +parameter addr_width=5; +parameter acc_extra=1; + +reg signed [coeff_width-1:0] coeff; +wire [addr_width-1:0] cnt; + +jt51_fir #( + .data_width (data_width), + .output_width(output_width), + .coeff_width (coeff_width), + .stages (stages), + .addr_width (addr_width), + .acc_extra (acc_extra) +) i_jt51_fir ( + .clk (clk ), + .rst (rst ), + .sample (sample ), + .left_in (left_in ), + .right_in (right_in ), + .left_out (left_out ), + .right_out (right_out ), + .sample_out(sample_out), + .cnt (cnt ), + .coeff (coeff ) +); + + +always @(*) + case( cnt ) + 5'd0: coeff = 9'd18; + 5'd1: coeff = 9'd24; + 5'd2: coeff = 9'd40; + 5'd3: coeff = 9'd66; + 5'd4: coeff = 9'd99; + 5'd5: coeff = 9'd134; + 5'd6: coeff = 9'd171; + 5'd7: coeff = 9'd205; + 5'd8: coeff = 9'd231; + 5'd9: coeff = 9'd249; + 5'd10: coeff = 9'd255; + default: coeff = 9'd0; + endcase + + + +endmodule diff --git a/modules/sound-jt51/filter/jt51_fir8.v b/modules/sound-jt51/filter/jt51_fir8.v new file mode 100644 index 0000000..256cf05 --- /dev/null +++ b/modules/sound-jt51/filter/jt51_fir8.v @@ -0,0 +1,111 @@ +/* This file is part of jt51. + + jt51 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. + + jt51 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 jt51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 7th 2017 + */ + +`timescale 1ns / 1ps + +module jt51_fir8 +#(parameter data_width=9, output_width=12) +( + input clk, + input rst, + input sample, + input signed [data_width-1:0] left_in, + input signed [data_width-1:0] right_in, + output signed [output_width-1:0] left_out, + output signed [output_width-1:0] right_out, + output sample_out +); + +parameter coeff_width=9; +parameter stages=81; +parameter addr_width=7; +parameter acc_extra=1; + +reg signed [coeff_width-1:0] coeff; +wire [addr_width-1:0] cnt; + +jt51_fir #( + .data_width (data_width), + .output_width(output_width), + .coeff_width (coeff_width), + .stages (stages), + .addr_width (addr_width), + .acc_extra (acc_extra) +) i_jt51_fir ( + .clk (clk ), + .rst (rst ), + .sample (sample ), + .left_in (left_in ), + .right_in (right_in ), + .left_out (left_out ), + .right_out (right_out ), + .sample_out(sample_out), + .cnt (cnt ), + .coeff (coeff ) +); + + +always @(*) + case( cnt ) + 7'd0: coeff = -9'd1; + 7'd1: coeff = 9'd0; + 7'd2: coeff = 9'd1; + 7'd3: coeff = 9'd1; + 7'd4: coeff = 9'd2; + 7'd5: coeff = 9'd3; + 7'd6: coeff = 9'd4; + 7'd7: coeff = 9'd4; + 7'd8: coeff = 9'd5; + 7'd9: coeff = 9'd5; + 7'd10: coeff = 9'd5; + 7'd11: coeff = 9'd4; + 7'd12: coeff = 9'd3; + 7'd13: coeff = 9'd1; + 7'd14: coeff = -9'd2; + 7'd15: coeff = -9'd6; + 7'd16: coeff = -9'd11; + 7'd17: coeff = -9'd16; + 7'd18: coeff = -9'd21; + 7'd19: coeff = -9'd26; + 7'd20: coeff = -9'd30; + 7'd21: coeff = -9'd33; + 7'd22: coeff = -9'd34; + 7'd23: coeff = -9'd32; + 7'd24: coeff = -9'd28; + 7'd25: coeff = -9'd21; + 7'd26: coeff = -9'd10; + 7'd27: coeff = 9'd4; + 7'd28: coeff = 9'd22; + 7'd29: coeff = 9'd42; + 7'd30: coeff = 9'd65; + 7'd31: coeff = 9'd91; + 7'd32: coeff = 9'd117; + 7'd33: coeff = 9'd142; + 7'd34: coeff = 9'd168; + 7'd35: coeff = 9'd192; + 7'd36: coeff = 9'd213; + 7'd37: coeff = 9'd231; + 7'd38: coeff = 9'd244; + 7'd39: coeff = 9'd252; + 7'd40: coeff = 9'd255; + default: coeff = 9'd0; + endcase // cnt + +endmodule diff --git a/modules/sound-jt51/filter/jt51_fir_ram.v b/modules/sound-jt51/filter/jt51_fir_ram.v new file mode 100644 index 0000000..377321e --- /dev/null +++ b/modules/sound-jt51/filter/jt51_fir_ram.v @@ -0,0 +1,43 @@ +/* This file is part of jt51. + + jt51 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. + + jt51 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 jt51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 7th 2017 + */ + +`timescale 1ns / 1ps + +module jt51_fir_ram +#(parameter data_width=8, parameter addr_width=7) +( + input [(data_width-1):0] data, + input [(addr_width-1):0] addr, + input we, clk, + output [(data_width-1):0] q +); + +(* ramstyle = "no_rw_check" *) reg [data_width-1:0] ram[2**addr_width-1:0]; + + reg [addr_width-1:0] addr_reg; + + always @ (posedge clk) begin + if (we) + ram[addr] <= data; + addr_reg <= addr; + end + + assign q = ram[addr_reg]; +endmodule diff --git a/modules/sound-jt51/filter/jt51_interpol.v b/modules/sound-jt51/filter/jt51_interpol.v new file mode 100644 index 0000000..d9d2980 --- /dev/null +++ b/modules/sound-jt51/filter/jt51_interpol.v @@ -0,0 +1,130 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 7th 2017 + */ + +`timescale 1ns / 1ps + +module jt51_interpol( + input clk, // Use a clock at least 162*2 times faster than JT51 sampling rate + input rst, + input sample_in, + input signed [15:0] left_in, + input signed [15:0] right_in, + // mix in other sound sources, like ADPCM sound of arcade boards + // other sound sources should be at the same + // sampling frequency than the FM sound + // for best results + input signed [15:0] left_other, + input signed [15:0] right_other, + + output signed [15:0] out_l, + output signed [15:0] out_r, + output sample_out +); + +/* max_clk_count is chosen so as to divide the input clock to + obtain a 32xFs frequency. + Fs = JT51 sampling frequency, normally ~55kHz + 32xFs = 1.78MHz + If this module's clock is 50MHz then + max_clk_count = 50/1.78=28 + + The division must be exact, otherwise samples will get out of sync + eventually and sound will get distorted. + max_clk_count*32 is the number of clock ticks that the FIR module + has to process the two sound channels. Each channels needs at least + 162 clock ticks, so in total it needs just over 324 ticks. + (162 is the number of stages of the filter) + + Using 50MHz and max_clk_count=28 gives 896 clock ticks, which is + more than enough. + +*/ +parameter max_clk_count = 7'd111; + +reg [15:0] fir_left_in, fir_right_in, left_mux, right_mux; +reg fir_sample_in; +reg fir4_sample_in; + + +reg [2:0] state; +reg [6:0] cnt; + +always @(*) + case( state ) + 3'd0: { left_mux, right_mux } <= { left_in, right_in}; + 3'd3: { left_mux, right_mux } <= { left_other, right_other}; + default: { left_mux, right_mux } <= 32'd0; + endcase + +always @(posedge clk) +if( rst ) begin + state <= 2'b0; + fir_sample_in <= 1'b0; + cnt <= 6'd0; +end else begin + fir4_sample_in <= ( cnt==0 || cnt==28 || cnt==56 || cnt==84 ); + if( cnt==max_clk_count ) begin + cnt <= 6'd0; + state <= state+1'b1; + fir_sample_in <= 1'b1; + {fir_left_in,fir_right_in} <= { left_mux, right_mux }; + end + else begin + cnt <= cnt + 1'b1; + fir_sample_in <= 1'b0; + end +end + +localparam fir8_w=16; // at least 16 +localparam fir4_w=16; // at least 16 +wire [fir8_w-1:0] fir8_out_l, fir8_out_r; +wire [fir4_w-1:0] fir4_out_l, fir4_out_r; + +assign out_l = fir4_out_l[15:0]; +assign out_r = fir4_out_r[15:0]; +//assign out_l = fir8_out_l[15:0]; +//assign out_r = fir8_out_r[15:0]; + +//wire fir8_sample; + +jt51_fir8 #(.data_width(16), .output_width(fir8_w)) u_fir8 ( + .clk ( clk ), + .rst ( rst ), + .sample ( fir_sample_in ), + .left_in ( fir_left_in ), + .right_in ( fir_right_in ), + .left_out ( fir8_out_l ), + .right_out ( fir8_out_r ) + // .sample_out ( fir8_sample ) +); + +jt51_fir4 #(.data_width(16), .output_width(fir4_w)) u_fir4 ( + .clk ( clk ), + .rst ( rst ), + .sample ( fir4_sample_in), + .left_in ( fir8_out_l[fir8_w-1:fir8_w-16] ), + .right_in ( fir8_out_r[fir8_w-1:fir8_w-16] ), + .left_out ( fir4_out_l ), + .right_out ( fir4_out_r ), + .sample_out ( sample_out ) +); + + +endmodule diff --git a/modules/sound-jt51/filter/jt51_sincf.v b/modules/sound-jt51/filter/jt51_sincf.v new file mode 100644 index 0000000..f1fea5b --- /dev/null +++ b/modules/sound-jt51/filter/jt51_sincf.v @@ -0,0 +1,53 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 7th 2017 + */ + +`timescale 1ns / 1ps + +module jt51_sincf #(parameter win=1, wout=5) +( + input clk, + input [win-1:0] din, + output reg [wout-1:0] dout +); + +reg [win-1:0] mem[23:0]; + +genvar i; + + +generate +for (i=23; i>0; i=i-1) begin: meminput + always @(posedge clk) + mem[i] <= mem[i-1]; +end + +endgenerate + +always @(posedge clk) begin + mem[0] <= din; + dout <= mem[0] + mem[1] + mem[2] + mem[3] + + mem[4] + mem[5] + mem[6] + mem[7] + + mem[8] + mem[9] + mem[10] + mem[11] + + mem[12] + mem[13] + mem[14] + mem[15] + + mem[16] + mem[17] + mem[18] + mem[19] + + mem[20] + mem[21] + mem[22] + mem[23]; +end + +endmodule \ No newline at end of file diff --git a/modules/sound-jt51/index.qip b/modules/sound-jt51/index.qip new file mode 100644 index 0000000..babfcf9 --- /dev/null +++ b/modules/sound-jt51/index.qip @@ -0,0 +1,25 @@ +# ============================================================================== +# Quartus Prime QIP Index File +# ============================================================================== +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_acc.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_eg.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_exp2lin.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_exprom.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_kon.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_lfo.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_lin2exp.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_mmr.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_mod.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_noise_lfsr.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_noise.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_op.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_pg.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_phinc_rom.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_phrom.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_pm.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_reg.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_sh.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_timers.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_csr_ch.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_csr_op.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51.v] diff --git a/modules/sound-jt51/jt51.v b/modules/sound-jt51/jt51.v new file mode 100644 index 0000000..0c3ccb8 --- /dev/null +++ b/modules/sound-jt51/jt51.v @@ -0,0 +1,372 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51( + input rst, // reset + input clk, // main clock + (* direct_enable *) input cen, // clock enable + (* direct_enable *) input cen_p1, // clock enable at half the speed + input cs_n, // chip select + input wr_n, // write + input a0, + input [7:0] din, // data in + output [7:0] dout, // data out + // peripheral control + output ct1, + output ct2, + output irq_n, // I do not synchronize this signal + // Low resolution output (same as real chip) + output sample, // marks new output sample + output signed [15:0] left, + output signed [15:0] right, + // Full resolution output + output signed [15:0] xleft, + output signed [15:0] xright +); + +// Timers +wire [9:0] value_A; +wire [7:0] value_B; +wire load_A, load_B; +wire enable_irq_A, enable_irq_B; +wire clr_flag_A, clr_flag_B; +wire flag_A, flag_B, overflow_A; +wire zero, half; +wire [4:0] cycles; + +jt51_timers u_timers( + .clk ( clk ), + .cen ( cen_p1 ), + .rst ( rst ), + .zero ( zero ), + .value_A ( value_A ), + .value_B ( value_B ), + .load_A ( load_A ), + .load_B ( load_B ), + .enable_irq_A( enable_irq_A ), + .enable_irq_B( enable_irq_B ), + .clr_flag_A ( clr_flag_A ), + .clr_flag_B ( clr_flag_B ), + .flag_A ( flag_A ), + .flag_B ( flag_B ), + .overflow_A ( overflow_A ), + .irq_n ( irq_n ) +); + +/*verilator tracing_on*/ + +`ifndef JT51_ONLYTIMERS +`define YM_TIMER_CTRL 8'h14 + +wire [1:0] rl_I; +wire [2:0] fb_II; +wire [2:0] con_I; +wire [6:0] kc_I; +wire [5:0] kf_I; +wire [2:0] pms_I; +wire [1:0] ams_VII; +wire [2:0] dt1_II; +wire [3:0] mul_VI; +wire [6:0] tl_VII; +wire [1:0] ks_III; +wire [4:0] arate_II; +wire amsen_VII; +wire [4:0] rate1_II; +wire [1:0] dt2_I; +wire [4:0] rate2_II; +wire [3:0] d1l_I; +wire [3:0] rrate_II; + +wire [1:0] cur_op; +wire keyon_II; + +wire [7:0] lfo_freq; +wire [1:0] lfo_w; +wire lfo_up; +wire [7:0] am; +wire [7:0] pm; +wire [6:0] amd, pmd; +wire [7:0] test_mode; +wire noise; + +wire m1_enters, m2_enters, c1_enters, c2_enters; +wire use_prevprev1,use_internal_x,use_internal_y, use_prev2,use_prev1; + +assign sample = zero & cen_p1; // single strobe + +jt51_lfo u_lfo( + .rst ( rst ), + .clk ( clk ), + .cen ( cen_p1 ), + .cycles ( cycles ), + + // Configuration + .lfo_freq ( lfo_freq ), + .lfo_w ( lfo_w ), + .lfo_amd ( amd ), + .lfo_pmd ( pmd ), + .lfo_up ( lfo_up ), + .noise ( noise ), + + // Test + .test ( test_mode ), + .lfo_clk ( ), + + .am ( am ), + .pm ( pm ) +); + +wire [ 4:0] keycode_III; +wire [ 9:0] ph_X; +wire pg_rst_III; + +/*verilator tracing_on*/ + + +jt51_pg u_pg( + .rst ( rst ), + .clk ( clk ), // P1 + .cen ( cen_p1 ), + .zero ( zero ), + // Channel frequency + .kc_I ( kc_I ), + .kf_I ( kf_I ), + // Operator multiplying + .mul_VI ( mul_VI ), + // Operator detuning + .dt1_II ( dt1_II ), + .dt2_I ( dt2_I ), + // phase modulation from LFO + .pms_I ( pms_I ), + .pm ( pm ), + // phase operation + .pg_rst_III ( pg_rst_III ), + .keycode_III( keycode_III ), + .pg_phase_X ( ph_X ) +); + +`ifdef TEST_SUPPORT +wire test_eg, test_op0; +`endif +wire [9:0] eg_XI; + +jt51_eg u_eg( + `ifdef TEST_SUPPORT + .test_eg ( test_eg ), + `endif + .rst ( rst ), + .clk ( clk ), + .cen ( cen_p1 ), + .zero ( zero ), + // envelope configuration + .keycode_III(keycode_III), // used in stage III + .arate_II ( arate_II ), + .rate1_II ( rate1_II ), + .rate2_II ( rate2_II ), + .rrate_II ( rrate_II ), + .d1l_I ( d1l_I ), + .ks_III ( ks_III ), + // envelope operation + .keyon_II ( keyon_II ), + .pg_rst_III ( pg_rst_III), + // envelope number + .tl_VII ( tl_VII ), + .am ( am ), + .ams_VII ( ams_VII ), + .amsen_VII ( amsen_VII ), + .eg_XI ( eg_XI ) +); + +/*verilator tracing_off*/ +wire signed [13:0] op_out; + +jt51_op u_op( + `ifdef TEST_SUPPORT + .test_eg ( test_eg ), + .test_op0 ( test_op0 ), + `endif + .rst ( rst ), + .clk ( clk ), + .cen ( cen_p1 ), + .pg_phase_X ( ph_X ), + .con_I ( con_I ), + .fb_II ( fb_II ), + // volume + .eg_atten_XI ( eg_XI ), + // modulation + .m1_enters ( m1_enters ), + .c1_enters ( c1_enters ), + // Operator + .use_prevprev1 ( use_prevprev1 ), + .use_internal_x ( use_internal_x ), + .use_internal_y ( use_internal_y ), + .use_prev2 ( use_prev2 ), + .use_prev1 ( use_prev1 ), + .test_214 ( 1'b0 ), + `ifdef SIMULATION + .zero ( zero ), + `endif + // output data + .op_XVII ( op_out ) +); + +wire [ 4:0] nfrq; +wire [11:0] noise_mix; +wire ne, op31_acc, op31_no; + +jt51_noise u_noise( + .rst ( rst ), + .clk ( clk ), + .cen ( cen_p1 ), + .cycles ( cycles ), + .nfrq ( nfrq ), + .eg ( eg_XI ), + .op31_no( op31_no ), + .out ( noise ), + .mix ( noise_mix ) +); + +jt51_acc u_acc( + .rst ( rst ), + .clk ( clk ), + .cen ( cen_p1 ), + .m1_enters ( m1_enters ), + .m2_enters ( m2_enters ), + .c1_enters ( c1_enters ), + .c2_enters ( c2_enters ), + .op31_acc ( op31_acc ), + .rl_I ( rl_I ), + .con_I ( con_I ), + .op_out ( op_out ), + .ne ( ne ), + .noise_mix ( noise_mix ), + .left ( left ), + .right ( right ), + .xleft ( xleft ), + .xright ( xright ) +); +`else +assign left = 16'd0; +assign right = 16'd0; +assign xleft = 16'd0; +assign xright = 16'd0; +`endif + +wire busy; +wire write = !cs_n && !wr_n; + +assign dout = { busy, 5'h0, flag_B, flag_A }; + +/*verilator tracing_on*/ + +jt51_mmr u_mmr( + .rst ( rst ), + .clk ( clk ), + .cen ( cen_p1 ), + .a0 ( a0 ), + .write ( write ), + .din ( din ), + .busy ( busy ), + + .test_mode ( test_mode ), + // CT + .ct1 ( ct1 ), // the LFO clock can be outputted via CT1 -not implemented- + .ct2 ( ct2 ), + // LFO + .lfo_freq ( lfo_freq ), + .lfo_w ( lfo_w ), + .lfo_amd ( amd ), + .lfo_pmd ( pmd ), + .lfo_up ( lfo_up ), + + // Noise + .ne ( ne ), + .nfrq ( nfrq ), + + // Timers + .value_A ( value_A ), + .value_B ( value_B ), + .load_A ( load_A ), + .load_B ( load_B ), + .enable_irq_A( enable_irq_A ), + .enable_irq_B( enable_irq_B ), + .clr_flag_A ( clr_flag_A ), + .clr_flag_B ( clr_flag_B ), + .overflow_A ( overflow_A ), + `ifdef TEST_SUPPORT + // Test + .test_eg ( test_eg ), + .test_op0 ( test_op0 ), + `endif + // REG + .rl_I ( rl_I ), + .fb_II ( fb_II ), + .con_I ( con_I ), + .kc_I ( kc_I ), + .kf_I ( kf_I ), + .pms_I ( pms_I ), + .ams_VII ( ams_VII ), + .dt1_II ( dt1_II ), + .mul_VI ( mul_VI ), + .tl_VII ( tl_VII ), + .ks_III ( ks_III ), + .arate_II ( arate_II ), + .amsen_VII ( amsen_VII ), + .rate1_II ( rate1_II ), + .dt2_I ( dt2_I ), + .rate2_II ( rate2_II ), + .d1l_I ( d1l_I ), + .rrate_II ( rrate_II ), + .keyon_II ( keyon_II ), + + .cur_op ( cur_op ), + .op31_no ( op31_no ), + .op31_acc ( op31_acc ), + .zero ( zero ), + .half ( half ), + .cycles ( cycles ), + .m1_enters ( m1_enters ), + .m2_enters ( m2_enters ), + .c1_enters ( c1_enters ), + .c2_enters ( c2_enters ), + // Operator + .use_prevprev1 ( use_prevprev1 ), + .use_internal_x ( use_internal_x ), + .use_internal_y ( use_internal_y ), + .use_prev2 ( use_prev2 ), + .use_prev1 ( use_prev1 ) +); + +`ifdef SIMULATION +`ifndef VERILATOR +integer fsnd; +initial begin + fsnd=$fopen("jt51.raw","wb"); +end + +always @(posedge zero) begin + $fwrite(fsnd,"%u", {xleft, xright}); +end +`endif +`endif + +endmodule + diff --git a/modules/sound-jt51/jt51_acc.v b/modules/sound-jt51/jt51_acc.v new file mode 100644 index 0000000..3b601d4 --- /dev/null +++ b/modules/sound-jt51/jt51_acc.v @@ -0,0 +1,175 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.1 Date: 14- 4-2017 + Version: 1.0 Date: 27-10-2016 + */ + + +module jt51_acc( + input rst, + input clk, + input cen, + input m1_enters, + input m2_enters, + input c1_enters, + input c2_enters, + input op31_acc, + input [1:0] rl_I, + input [2:0] con_I, + input signed [13:0] op_out, + input ne, // noise enable + input signed [11:0] noise_mix, + output signed [15:0] left, + output signed [15:0] right, + output reg signed [15:0] xleft, // exact outputs + output reg signed [15:0] xright +); + +reg signed [13:0] op_val; + +always @(*) begin + if( ne && op31_acc ) // cambiar a OP 31 + op_val = { {2{noise_mix[11]}}, noise_mix }; + else + op_val = op_out; +end + +reg sum_en; + +always @(*) begin + case ( con_I ) + 3'd0,3'd1,3'd2,3'd3: sum_en = m2_enters; + 3'd4: sum_en = m1_enters | m2_enters; + 3'd5,3'd6: sum_en = ~c1_enters; + 3'd7: sum_en = 1'b1; + default: sum_en = 1'bx; + endcase +end + +wire ren = rl_I[1]; +wire len = rl_I[0]; +reg signed [16:0] pre_left, pre_right; +wire signed [15:0] total; +wire signed [16:0] total_ex = {total[15],total}; + +reg sum_all; + +wire rst_sum = c2_enters; +//wire rst_sum = c1_enters; +//wire rst_sum = m1_enters; +//wire rst_sum = m2_enters; + +function signed [15:0] lim16; + input signed [16:0] din; + lim16 = !din[16] && din[15] ? 16'h7fff : + ( din[16] && !din[15] ? 16'h8000 : din[15:0] ); +endfunction + + +always @(posedge clk) begin + if( rst ) begin + sum_all <= 1'b0; + end + else if(cen) begin + if( rst_sum ) begin + sum_all <= 1'b1; + if( !sum_all ) begin + pre_right <= ren ? total_ex : 17'd0; + pre_left <= len ? total_ex : 17'd0; + end + else begin + pre_right <= pre_right + (ren ? total_ex : 17'd0); + pre_left <= pre_left + (len ? total_ex : 17'd0); + end + end + if( c1_enters ) begin + sum_all <= 1'b0; + xleft <= lim16(pre_left); + xright <= lim16(pre_right); + end + end +end + +reg signed [15:0] opsum; +wire signed [16:0] opsum10 = {{3{op_val[13]}},op_val}+{total[15],total}; + +always @(*) begin + if( rst_sum ) + opsum = sum_en ? { {2{op_val[13]}}, op_val } : 16'd0; + else begin + if( sum_en ) + if( opsum10[16]==opsum10[15] ) + opsum = opsum10[15:0]; + else begin + opsum = opsum10[16] ? 16'h8000 : 16'h7fff; + end + else + opsum = total; + end +end + +jt51_sh #(.width(16),.stages(8)) u_acc( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( opsum ), + .drop ( total ) +); + + +wire signed [9:0] left_man, right_man; +wire [2:0] left_exp, right_exp; + +jt51_exp2lin left_reconstruct( + .lin( left ), + .man( left_man ), + .exp( left_exp ) +); + +jt51_exp2lin right_reconstruct( + .lin( right ), + .man( right_man ), + .exp( right_exp ) +); + +jt51_lin2exp left2exp( + .lin( xleft ), + .man( left_man ), + .exp( left_exp ) ); + +jt51_lin2exp right2exp( + .lin( xright ), + .man( right_man ), + .exp( right_exp ) ); + +`ifdef DUMPLEFT + +reg skip; + +wire signed [15:0] dump = left; + +initial skip=1; + +always @(posedge clk) + if( c1_enters && (!skip || dump) && cen) begin + $display("%d", dump ); + skip <= 0; + end + +`endif + +endmodule diff --git a/modules/sound-jt51/jt51_csr_ch.v b/modules/sound-jt51/jt51_csr_ch.v new file mode 100644 index 0000000..a4f3800 --- /dev/null +++ b/modules/sound-jt51/jt51_csr_ch.v @@ -0,0 +1,74 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 23-10-2019 + */ + +module jt51_csr_ch( + input rst, + input clk, + input cen, + input [ 7:0] din, + + input up_rl_ch, + input up_fb_ch, + input up_con_ch, + input up_kc_ch, + input up_kf_ch, + input up_ams_ch, + input up_pms_ch, + + output [1:0] rl, + output [2:0] fb, + output [2:0] con, + output [6:0] kc, + output [5:0] kf, + output [1:0] ams, + output [2:0] pms +); + +wire [1:0] rl_in = din[7:6]; +wire [2:0] fb_in = din[5:3]; +wire [2:0] con_in = din[2:0]; +wire [6:0] kc_in = din[6:0]; +wire [5:0] kf_in = din[7:2]; +wire [1:0] ams_in = din[1:0]; +wire [2:0] pms_in = din[6:4]; + +wire [25:0] reg_in = { + up_rl_ch ? rl_in : rl, + up_fb_ch ? fb_in : fb, + up_con_ch ? con_in : con, + up_kc_ch ? kc_in : kc, + up_kf_ch ? kf_in : kf, + up_ams_ch ? ams_in : ams, + up_pms_ch ? pms_in : pms }; + +wire [25:0] reg_out; + +assign { rl, fb, con, kc, kf, ams, pms } = reg_out; + +jt51_sh #( .width(26), .stages(8)) u_regop( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( reg_in ), + .drop ( reg_out ) +); + + +endmodule \ No newline at end of file diff --git a/modules/sound-jt51/jt51_csr_op.v b/modules/sound-jt51/jt51_csr_op.v new file mode 100644 index 0000000..0136812 --- /dev/null +++ b/modules/sound-jt51/jt51_csr_op.v @@ -0,0 +1,104 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 23-10-2019 + */ + +module jt51_csr_op( + input rst, + input clk, + input cen, + input [ 7:0] din, + input up_dt1_op, + input up_mul_op, + input up_tl_op, + input up_ks_op, + input up_amsen_op, + input up_dt2_op, + input up_d1l_op, + input up_ar_op, + input up_d1r_op, + input up_d2r_op, + input up_rr_op, + + output [2:0] dt1, + output [3:0] mul, + output [6:0] tl, + output [1:0] ks, + output amsen, + output [1:0] dt2, + output [3:0] d1l, + output [4:0] arate, + output [4:0] rate1, + output [4:0] rate2, + output [3:0] rrate +); + +wire [2:0] dt1_in = din[6:4]; +wire [3:0] mul_in = din[3:0]; +wire [6:0] tl_in = din[6:0]; +wire [1:0] ks_in = din[7:6]; +wire amsen_in= din[7]; +wire [1:0] dt2_in = din[7:6]; +wire [3:0] d1l_in = din[7:4]; +wire [4:0] ar_in = din[4:0]; +wire [4:0] d1r_in = din[4:0]; +wire [4:0] d2r_in = din[4:0]; +wire [3:0] rr_in = din[3:0]; + +wire [30:0] reg0_in = { + up_dt1_op ? dt1_in : dt1, // 3 + up_mul_op ? mul_in : mul, // 4 + up_ks_op ? ks_in : ks, // 2 + up_amsen_op ? amsen_in : amsen, // 1 + up_dt2_op ? dt2_in : dt2, // 2 + up_d1l_op ? d1l_in : d1l, // 4 + + up_ar_op ? ar_in : arate, // 5 + up_d1r_op ? d1r_in : rate1, // 5 + up_d2r_op ? d2r_in : rate2 }; // 5 + +wire [10:0] reg1_in = { + up_tl_op ? tl_in : tl, // 7 + up_rr_op ? rr_in : rrate }; // 4 + +wire [30:0] reg0_out; +wire [10:0] reg1_out; + +assign { dt1, mul, ks, amsen, dt2, d1l, arate, rate1, rate2, tl, rrate } + = {reg0_out, reg1_out}; + +// reset to zero +jt51_sh #( .width(31), .stages(32)) u_reg0op( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( reg0_in ), + .drop ( reg0_out ) +); + +// reset to one +jt51_sh #( .width(11), .stages(32), .rstval(1'b1)) u_reg1op( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( reg1_in ), + .drop ( reg1_out ) +); + + +endmodule \ No newline at end of file diff --git a/modules/sound-jt51/jt51_eg.v b/modules/sound-jt51/jt51_eg.v new file mode 100644 index 0000000..a77b9d8 --- /dev/null +++ b/modules/sound-jt51/jt51_eg.v @@ -0,0 +1,441 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_eg( + `ifdef TEST_SUPPORT + input test_eg, + `endif + input rst, + input clk, + input cen, + input zero, + // envelope configuration + input [4:0] keycode_III, + input [4:0] arate_II, + input [4:0] rate1_II, + input [4:0] rate2_II, + input [3:0] rrate_II, + input [3:0] d1l_I, + input [1:0] ks_III, + // envelope operation + input keyon_II, + output reg pg_rst_III, + // envelope number + input [6:0] tl_VII, + input [7:0] am, + input [1:0] ams_VII, + input amsen_VII, + output [9:0] eg_XI +); + + // eg[9:6] -> direct attenuation (divide by 2) + // eg[5:0] -> mantisa attenuation (uses LUT) + // 1 LSB of eg is -0.09257 dB + +localparam ATTACK=2'd0, + DECAY1=2'd1, + DECAY2=2'd2, + RELEASE=2'd3; + +reg [ 4:0] d1level_II; +reg [ 2:0] cnt_V; +reg [ 5:0] rate_IV; +wire [ 9:0] eg_VI; +reg [ 9:0] eg_VII, eg_VIII; +wire [ 9:0] eg_II; +reg [11:0] sum_eg_tl_VII; + +reg step_V, step_VI; +reg sum_up; +reg [5:0] rate_V; +reg [5:1] rate_VI; + +// remember: { log_msb, pow_addr } <= log_val[11:0] + { tl, 5'd0 } + { eg, 2'd0 }; + +reg [ 1:0] eg_cnt_base; +reg [14:0] eg_cnt /*verilator public*/; + +reg [ 9:0] am_final_VII; + +always @(posedge clk) begin : envelope_counter + if( rst ) begin + eg_cnt_base <= 2'd0; + eg_cnt <=15'd0; + end + else if(cen) begin + if( zero ) begin + // envelope counter increases every 3 output samples, + // there is one sample every 32 clock ticks + if( eg_cnt_base == 2'd2 ) begin + eg_cnt <= eg_cnt + 1'b1; + eg_cnt_base <= 2'd0; + end + else eg_cnt_base <= eg_cnt_base + 1'b1; + end + end +end + +wire cnt_out; // = all_cnt_last[3*31-1:3*30]; + +reg [6:0] pre_rate_III; +reg [4:0] kshift_III; +reg [4:0] cfg_III; + +always @(*) begin : pre_rate_calc + kshift_III = keycode_III >> ~ks_III; + pre_rate_III = { 1'b0, cfg_III, 1'b0 } + { 2'b0, kshift_III }; +end + + + +reg [7:0] step_idx; +reg [1:0] state_in_III, state_in_IV, state_in_V, state_in_VI; + +always @(*) begin : rate_step + if( rate_V[5:4]==2'b11 ) begin // 0 means 1x, 1 means 2x + if( rate_V[5:2]==4'hf && state_in_V == ATTACK) + step_idx = 8'b11111111; // Maximum attack speed, rates 60&61 + else + case( rate_V[1:0] ) + 2'd0: step_idx = 8'b00000000; + 2'd1: step_idx = 8'b10001000; // 2 + 2'd2: step_idx = 8'b10101010; // 4 + 2'd3: step_idx = 8'b11101110; // 6 + endcase + end + else begin + if( rate_V[5:2]==4'd0 && state_in_V != ATTACK) + step_idx = 8'b11111110; // limit slowest decay rate_IV + else + case( rate_V[1:0] ) + 2'd0: step_idx = 8'b10101010; // 4 + 2'd1: step_idx = 8'b11101010; // 5 + 2'd2: step_idx = 8'b11101110; // 6 + 2'd3: step_idx = 8'b11111110; // 7 + endcase + end + // a rate_IV of zero keeps the level still + step_V = rate_V[5:2]==4'd0 ? 1'b0 : step_idx[ cnt_V ]; +end + + + +wire ar_off_VI; + +always @(posedge clk) if(cen) begin + // I + if( d1l_I == 4'd15 ) + d1level_II <= 5'h10; // 48dB + else + d1level_II <= {1'b0,d1l_I}; +end + +// II +wire keyon_last_II; +wire keyon_now_II = !keyon_last_II && keyon_II; +wire keyoff_now_II = keyon_last_II && !keyon_II; +wire ar_off_II = keyon_now_II && (arate_II == 5'h1f); +wire [1:0] state_II; + +always @(posedge clk) if(cen) begin + pg_rst_III <= keyon_now_II; + // trigger release + if( keyoff_now_II ) begin + cfg_III <= { rrate_II, 1'b1 }; + state_in_III <= RELEASE; + end + else begin + // trigger 1st decay + if( keyon_now_II ) begin + cfg_III <= arate_II; + state_in_III <= ATTACK; + end + else begin : sel_rate + case ( state_II ) + ATTACK: begin + if( eg_II==10'd0 ) begin + state_in_III <= DECAY1; + cfg_III <= rate1_II; + end + else begin + state_in_III <= state_II; // attack + cfg_III <= arate_II; + end + end + DECAY1: begin + if( eg_II[9:5] >= d1level_II ) begin + cfg_III <= rate2_II; + state_in_III <= DECAY2; + end + else begin + cfg_III <= rate1_II; + state_in_III <= state_II; // decay1 + end + end + DECAY2: begin + cfg_III <= rate2_II; + state_in_III <= state_II; // decay2 + end + RELEASE: begin + cfg_III <= { rrate_II, 1'b1 }; + state_in_III <= state_II; // release + end + endcase + end + end +end + + // III +always @(posedge clk) if(cen) begin + state_in_IV <= state_in_III; + rate_IV <= pre_rate_III[6] ? 6'd63 : pre_rate_III[5:0]; +end + + // IV +always @(posedge clk) if(cen) begin + state_in_V <= state_in_IV; + rate_V <= rate_IV; + if( state_in_IV == ATTACK ) + case( rate_IV[5:2] ) + 4'h0: cnt_V <= eg_cnt[13:11]; + 4'h1: cnt_V <= eg_cnt[12:10]; + 4'h2: cnt_V <= eg_cnt[11: 9]; + 4'h3: cnt_V <= eg_cnt[10: 8]; + 4'h4: cnt_V <= eg_cnt[ 9: 7]; + 4'h5: cnt_V <= eg_cnt[ 8: 6]; + 4'h6: cnt_V <= eg_cnt[ 7: 5]; + 4'h7: cnt_V <= eg_cnt[ 6: 4]; + 4'h8: cnt_V <= eg_cnt[ 5: 3]; + 4'h9: cnt_V <= eg_cnt[ 4: 2]; + 4'ha: cnt_V <= eg_cnt[ 3: 1]; + default: cnt_V <= eg_cnt[ 2: 0]; + endcase + else + case( rate_IV[5:2] ) + 4'h0: cnt_V <= eg_cnt[14:12]; + 4'h1: cnt_V <= eg_cnt[13:11]; + 4'h2: cnt_V <= eg_cnt[12:10]; + 4'h3: cnt_V <= eg_cnt[11: 9]; + 4'h4: cnt_V <= eg_cnt[10: 8]; + 4'h5: cnt_V <= eg_cnt[ 9: 7]; + 4'h6: cnt_V <= eg_cnt[ 8: 6]; + 4'h7: cnt_V <= eg_cnt[ 7: 5]; + 4'h8: cnt_V <= eg_cnt[ 6: 4]; + 4'h9: cnt_V <= eg_cnt[ 5: 3]; + 4'ha: cnt_V <= eg_cnt[ 4: 2]; + 4'hb: cnt_V <= eg_cnt[ 3: 1]; + default: cnt_V <= eg_cnt[ 2: 0]; + endcase +end + + // V +always @(posedge clk) if(cen) begin + state_in_VI <= state_in_V; + rate_VI <= rate_V[5:1]; + sum_up <= cnt_V[0] != cnt_out; + step_VI <= step_V; +end + +/////////////////////////////////////// +// VI +reg [8:0] ar_sum0_VI; +reg [9:0] ar_result_VI, ar_sum_VI; + +always @(*) begin : ar_calculation + casez( rate_VI[5:2] ) + default: ar_sum0_VI = { 3'd0, eg_VI[9:4] } + 9'd1; + 4'b1100: ar_sum0_VI = { 3'd0, eg_VI[9:4] } + 9'd1; + 4'b1101: ar_sum0_VI = { 2'd0, eg_VI[9:3] } + 9'd1; + 4'b111?: ar_sum0_VI = { 1'd0, eg_VI[9:2] } + 9'd1; + endcase + if( rate_VI[5:4] == 2'b11 ) + ar_sum_VI = step_VI ? { ar_sum0_VI, 1'b0 } : { 1'b0, ar_sum0_VI }; + else + ar_sum_VI = step_VI ? { 1'b0, ar_sum0_VI } : 10'd0; + ar_result_VI = ar_sum_VI. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_exp2lin( + output reg signed [15:0] lin, + input signed [9:0] man, + input [2:0] exp +); + +always @(*) begin + case( exp ) + 3'd7: lin = { man, 6'b0 }; + 3'd6: lin = { {1{man[9]}}, man, 5'b0 }; + 3'd5: lin = { {2{man[9]}}, man, 4'b0 }; + 3'd4: lin = { {3{man[9]}}, man, 3'b0 }; + 3'd3: lin = { {4{man[9]}}, man, 2'b0 }; + 3'd2: lin = { {5{man[9]}}, man, 1'b0 }; + 3'd1: lin = { {6{man[9]}}, man }; + 3'd0: lin = 16'd0; + endcase +end + +endmodule diff --git a/modules/sound-jt51/jt51_exprom.v b/modules/sound-jt51/jt51_exprom.v new file mode 100644 index 0000000..1990339 --- /dev/null +++ b/modules/sound-jt51/jt51_exprom.v @@ -0,0 +1,77 @@ + + +/* This file is part of JT51. + + + JT51 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. + + JT51 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 JT51. If not, see . + + Based on hardware measurements and Sauraen VHDL version of OPN/OPN2, + which is based on die shots. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-4-2017 + +*/ + +module jt51_exprom +( + input [4:0] addr, + input clk, + input cen, + output reg [44:0] exp +); + + reg [44:0] explut[31:0]; + initial + begin + explut[0] = 45'b111110101011010110001011010000010010111011011; + explut[1] = 45'b111101010011010101000011001100101110110101011; + explut[2] = 45'b111011111011010011110111001000110010101110011; + explut[3] = 45'b111010100101010010101111000100110010101000011; + explut[4] = 45'b111001001101010001100111000000110010100001011; + explut[5] = 45'b110111111011010000011110111101010010011011011; + explut[6] = 45'b110110100011001111010110111001010010010100100; + explut[7] = 45'b110101001011001110001110110101110010001110011; + explut[8] = 45'b110011111011001101000110110001110010001000011; + explut[9] = 45'b110010100011001011111110101110010010000010011; + explut[10] = 45'b110001010011001010111010101010010001111011011; + explut[11] = 45'b101111111011001001110010100110110001110101011; + explut[12] = 45'b101110101011001000101010100011001101101111011; + explut[13] = 45'b101101010101000111100110011111010001101001011; + explut[14] = 45'b101100000011000110100010011011110001100011011; + explut[15] = 45'b101010110011000101011110011000010001011101011; + explut[16] = 45'b101001100011000100011010010100101101010111011; + explut[17] = 45'b101000010011000011010010010001001101010001011; + explut[18] = 45'b100111000011000010010010001101101101001011011; + explut[19] = 45'b100101110011000001001110001010001101000101011; + explut[20] = 45'b100100100011000000001010000110010000111111011; + explut[21] = 45'b100011010010111111001010000011001100111001011; + explut[22] = 45'b100010000010111110000101111111101100110011011; + explut[23] = 45'b100000110010111101000001111100001100101101011; + explut[24] = 45'b011111101010111100000001111000101100101000010; + explut[25] = 45'b011110011010111011000001110101001100100010011; + explut[26] = 45'b011101001010111010000001110001110000011100011; + explut[27] = 45'b011100000010111001000001101110010000010110011; + explut[28] = 45'b011010110010111000000001101011001100010001011; + explut[29] = 45'b011001101010110111000001100111101100001011011; + explut[30] = 45'b011000100000110110000001100100010000000110010; + explut[31] = 45'b010111010010110101000001100001001100000000011; + end + + always @ (posedge clk) if(cen) begin + exp <= explut[addr]; + end + +endmodule diff --git a/modules/sound-jt51/jt51_kon.v b/modules/sound-jt51/jt51_kon.v new file mode 100644 index 0000000..b9865d2 --- /dev/null +++ b/modules/sound-jt51/jt51_kon.v @@ -0,0 +1,68 @@ + + +/* This file is part of JT51. + + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + +*/ + +module jt51_kon( + input rst, + input clk, + input cen, + input [3:0] keyon_op, + input [2:0] keyon_ch, + input [1:0] cur_op, + input [2:0] cur_ch, + input up_keyon, + input csm, + input overflow_A, + + output reg keyon_II +); + +//reg csm_copy; + +reg din; +wire drop; + +reg [3:0] cur_op_hot; + +always @(posedge clk) if (cen) + keyon_II <= (csm&&overflow_A) || drop; + +always @(*) begin + case( cur_op ) + 2'd0: cur_op_hot = 4'b0001; // S1 / M1 + 2'd1: cur_op_hot = 4'b0100; // S3 / M2 + 2'd2: cur_op_hot = 4'b0010; // S2 / C1 + 2'd3: cur_op_hot = 4'b1000; // S4 / C2 + endcase + din = keyon_ch==cur_ch && up_keyon ? |(keyon_op&cur_op_hot) : drop; +end + +jt51_sh #(.width(1),.stages(32)) u_konch( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( din ), + .drop ( drop ) +); + +endmodule diff --git a/modules/sound-jt51/jt51_lfo.v b/modules/sound-jt51/jt51_lfo.v new file mode 100644 index 0000000..7fb8b1e --- /dev/null +++ b/modules/sound-jt51/jt51_lfo.v @@ -0,0 +1,234 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + +module jt51_lfo( + input rst, + input clk, + input cen, + input [4:0] cycles, + + // configuration + input [7:0] lfo_freq, + input [6:0] lfo_amd, + input [6:0] lfo_pmd, + input [1:0] lfo_w, + input lfo_up, + input noise, + + // test + input [7:0] test, + output reg lfo_clk, + + // data + output reg [7:0] am, + output reg [7:0] pm +); + +localparam [1:0] SAWTOOTH = 2'd0, + SQUARE = 2'd1, + TRIANG = 2'd2, + NOISE = 2'd3; + +reg [14:0] lfo_lut[0:15]; + +// counters +reg [ 3:0] cnt1, cnt3, bitcnt; +reg [14:0] cnt2; +reg [15:0] next_cnt2; +reg [ 1:0] cnt1_ov, cnt2_ov; + +// LFO state (value) +reg [15:0] val, // counts next integrator step + out2; // integrator for PM/AM +reg [ 6:0] out1; +wire pm_sign; +reg trig_sign, saw_sign; + +reg bitcnt_rst, cnt2_load, cnt3_step; +wire lfo_clk_next; +reg lfo_clk_latch; + +wire cyc_5 = cycles[3:0]==4'h5; +wire cyc_6 = cycles[3:0]==4'h6; +wire cyc_c = cycles[3:0]==4'hc; // 12 +wire cyc_d = cycles[3:0]==4'hd; // 13 +wire cyc_e = cycles[3:0]==4'he; // 14 +wire cyc_f = cycles[3:0]==4'hf; // 15 + +reg cnt3_clk; +wire ampm_sel = bitcnt[3]; +wire bit7 = &bitcnt[2:0]; + +reg lfo_up_latch; + +assign pm_sign = lfo_w==TRIANG ? trig_sign : saw_sign; +assign lfo_clk_next = test[2] | next_cnt2[15] | cnt3_step; + +always @(*) begin + if( cnt2_load ) begin + next_cnt2 = {1'b0, lfo_lut[ lfo_freq[7:4] ] }; + end else begin + next_cnt2 = {1'd0,cnt2 } + {15'd0,cnt1_ov[1]|test[3]}; + end +end + +always @(posedge clk) begin + if( lfo_up ) + lfo_up_latch <= 1; + else if( cen ) + lfo_up_latch <= 0; +end + +always @(posedge clk, posedge rst) begin + if( rst ) begin + cnt1 <= 4'd0; + cnt2 <= 15'd0; + cnt3 <= 4'd0; + cnt1_ov <= 2'd0; + cnt3_step <= 0; + bitcnt <= 4'h8; + end else if( cen ) begin + // counter 1 + if( cyc_c ) + { cnt1_ov[0], cnt1 } <= { 1'b0, cnt1 } + 1'd1; + else + cnt1_ov[0] <= 0; + cnt1_ov[1] <= cnt1_ov[0]; + bitcnt_rst <= cnt1==4'd2; + if( bitcnt_rst && !cyc_c ) + bitcnt <= 4'd0; + else if( cyc_e ) + bitcnt <= bitcnt + 1'd1; + // counter 2 + cnt2_load <= lfo_up_latch | next_cnt2[15]; + cnt2 <= next_cnt2[14:0]; + if( cyc_e ) begin + cnt2_ov[0] <= next_cnt2[15]; + lfo_clk_latch <= lfo_clk_next; + end + if( cyc_5 ) cnt2_ov[1] <= cnt2_ov[0]; + // counter 3 + cnt3_step <= 0; + if( cnt2_ov[1] & cyc_d ) begin + cnt3_clk <= 1; + // frequency LSB control + if( !cnt3[0] ) cnt3_step <= lfo_freq[3]; + else if( !cnt3[1] ) cnt3_step <= lfo_freq[2]; + else if( !cnt3[2] ) cnt3_step <= lfo_freq[1]; + else if( !cnt3[3] ) cnt3_step <= lfo_freq[0]; + end else begin + cnt3_clk <= 0; + end + if( cnt3_clk ) + cnt3 <= cnt3 + 1'd1; + // LFO clock + lfo_clk <= lfo_clk_next; + end +end + +// LFO value +reg [1:0] val_sum; +reg val_c, wcarry, val0_next; +reg w1, w2, w3, w4, w5, w6, w7, w8; + +reg [6:0] dmux; +reg integ_c, out1bit; +reg [1:0] out2sum; +wire [7:0] out2b; +reg [2:0] bitsel; + +assign out2b = out2[15:8]; + +always @(*) begin + w1 = !lfo_clk || lfo_w==NOISE || !cyc_f; + w4 = lfo_clk_latch && lfo_w==NOISE; + w3 = !w4 && val[15] && !test[1]; + w2 = !w1 && lfo_w==TRIANG; + wcarry = !w1 || ( !cyc_f && lfo_w!=NOISE && val_c); + val_sum = {1'b0, w2} + {1'b0, w3} + {1'b0, wcarry}; + val0_next = val_sum[0] || (lfo_w==NOISE && lfo_clk_latch && noise); + // LFO compound output, AM/PM base value one after the other + w5 = ampm_sel ? saw_sign : (!trig_sign || lfo_w!=TRIANG); + w6 = w5 ^ w3; + w7 = cycles[3:0]<4'd7 || cycles[3:0]==4'd15; + w8 = lfo_w == SQUARE ? (ampm_sel?cyc_6 : !saw_sign) : w6; + w8 = ~(w8 & w7); + + // Integrator + dmux = (ampm_sel ? lfo_pmd : lfo_amd) &~out1; + bitsel = ~(bitcnt[2:0]+3'd1); + out1bit = dmux[ bitsel ] & ~bit7; + out2sum = {1'b0, out1bit} + {1'b0, out2[0] && bitcnt[2:0]!=0} + {1'b0, integ_c & ~cyc_f }; +end + +always @(posedge clk, posedge rst) begin + if( rst ) begin + val <= 16'd0; + val_c <= 0; + trig_sign <= 0; + saw_sign <= 0; + out1 <= ~7'd0; + out2 <= 16'd0; + integ_c <= 0; + end else if( cen ) begin + val <= {val[14:0], val0_next }; + val_c <= val_sum[1]; + if( cyc_f ) begin + trig_sign <= val[7]; + saw_sign <= val[8]; + end + // current step + out1 <= {out1[5:0], w8}; + // integrator + integ_c <= out2sum[1]; + out2 <= { out2sum[0], out2[15:1] }; + // final output + if( bit7 & cyc_f ) begin + if( ampm_sel ) + pm <= lfo_pmd==7'd0 ? 8'd0 : { out2b[7]^pm_sign, out2b[6:0]}; + else + am <= out2b; + end + end +end + +initial begin + lfo_lut[0] = 15'h0000; + lfo_lut[1] = 15'h4000; + lfo_lut[2] = 15'h6000; + lfo_lut[3] = 15'h7000; + + lfo_lut[4] = 15'h7800; + lfo_lut[5] = 15'h7c00; + lfo_lut[6] = 15'h7e00; + lfo_lut[7] = 15'h7f00; + + lfo_lut[8] = 15'h7f80; + lfo_lut[9] = 15'h7fc0; + lfo_lut[10] = 15'h7fe0; + lfo_lut[11] = 15'h7ff0; + + lfo_lut[12] = 15'h7ff8; + lfo_lut[13] = 15'h7ffc; + lfo_lut[14] = 15'h7ffe; + lfo_lut[15] = 15'h7fff; +end + +endmodule diff --git a/modules/sound-jt51/jt51_lfo_lfsr.v b/modules/sound-jt51/jt51_lfo_lfsr.v new file mode 100644 index 0000000..a89e1a2 --- /dev/null +++ b/modules/sound-jt51/jt51_lfo_lfsr.v @@ -0,0 +1,50 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + +`timescale 1ns / 1ps + +module jt51_lfo_lfsr #(parameter init=220 )( + input rst, + input clk, + input cen, + input base, + output out +); + +reg [18:0] bb; +assign out = bb[18]; + +reg last_base; + +always @(posedge clk, posedge rst) begin : base_counter + if( rst ) begin + bb <= init[18:0]; + last_base <= 1'b0; + end + else if(cen) begin + last_base <= base; + if( last_base != base ) begin + bb[18:1] <= bb[17:0]; + bb[0] <= ^{bb[0],bb[1],bb[14],bb[15],bb[17],bb[18]}; + end + end +end + +endmodule diff --git a/modules/sound-jt51/jt51_lin2exp.v b/modules/sound-jt51/jt51_lin2exp.v new file mode 100644 index 0000000..75d408e --- /dev/null +++ b/modules/sound-jt51/jt51_lin2exp.v @@ -0,0 +1,96 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_lin2exp( + input [15:0] lin, + output reg [9:0] man, + output reg [2:0] exp +); + +always @(*) begin + casez( lin[15:9] ) + // negative numbers + 7'b10?????: begin + man = lin[15:6]; + exp = 3'd7; + end + 7'b110????: begin + man = lin[14:5]; + exp = 3'd6; + end + 7'b1110???: begin + man = lin[13:4]; + exp = 3'd5; + end + 7'b11110??: begin + man = lin[12:3]; + exp = 3'd4; + end + 7'b111110?: begin + man = lin[11:2]; + exp = 3'd3; + end + 7'b1111110: begin + man = lin[10:1]; + exp = 3'd2; + end + 7'b1111111: begin + man = lin[ 9:0]; + exp = 3'd1; + end + // positive numbers + 7'b01?????: begin + man = lin[15:6]; + exp = 3'd7; + end + 7'b001????: begin + man = lin[14:5]; + exp = 3'd6; + end + 7'b0001???: begin + man = lin[13:4]; + exp = 3'd5; + end + 7'b00001??: begin + man = lin[12:3]; + exp = 3'd4; + end + 7'b000001?: begin + man = lin[11:2]; + exp = 3'd3; + end + 7'b0000001: begin + man = lin[10:1]; + exp = 3'd2; + end + 7'b0000000: begin + man = lin[ 9:0]; + exp = 3'd1; + end + + default: begin + man = lin[9:0]; + exp = 3'd1; + end + endcase +end + +endmodule diff --git a/modules/sound-jt51/jt51_mmr.v b/modules/sound-jt51/jt51_mmr.v new file mode 100644 index 0000000..a16c02c --- /dev/null +++ b/modules/sound-jt51/jt51_mmr.v @@ -0,0 +1,386 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_mmr( + input rst, + input clk, + input cen, // P1 + input [7:0] din, + input write, + input a0, + output reg busy, + + // Original test bits + output reg [7:0] test_mode, + + // CT + output reg ct1, + output reg ct2, + + // Noise + output reg ne, + output reg [4:0] nfrq, + + // LFO + output reg [7:0] lfo_freq, + output reg [1:0] lfo_w, + output reg [6:0] lfo_amd, + output reg [6:0] lfo_pmd, + output reg lfo_up, + // Timers + output reg [9:0] value_A, + output reg [7:0] value_B, + output reg load_A, + output reg load_B, + output reg enable_irq_A, + output reg enable_irq_B, + output reg clr_flag_A, + output reg clr_flag_B, + input overflow_A, + + `ifdef TEST_SUPPORT + // Test + output reg test_eg, + output reg test_op0, + `endif + // REG + output [1:0] rl_I, + output [2:0] fb_II, + output [2:0] con_I, + output [6:0] kc_I, + output [5:0] kf_I, + output [2:0] pms_I, + output [1:0] ams_VII, + output [2:0] dt1_II, + output [3:0] mul_VI, + output [6:0] tl_VII, + output [1:0] ks_III, + output [4:0] arate_II, + output amsen_VII, + output [4:0] rate1_II, + output [1:0] dt2_I, + output [4:0] rate2_II, + output [3:0] d1l_I, + output [3:0] rrate_II, + output keyon_II, + + output [1:0] cur_op, + output op31_no, + output op31_acc, + + output zero, // high once per round + output half, // high twice per round + output [4:0] cycles, + output m1_enters, + output m2_enters, + output c1_enters, + output c2_enters, + // Operator + output use_prevprev1, + output use_internal_x, + output use_internal_y, + output use_prev2, + output use_prev1 +); + +reg [7:0] selected_register, din_copy ; + +reg up_rl, up_kc, up_kf, up_pms, + up_dt1, up_tl, up_ks, up_dt2, + up_d1l, up_keyon, up_amsen; +reg [1:0] up_op; +reg [2:0] up_ch; + +`ifdef SIMULATION +reg mmr_dump; +`endif + +parameter REG_TEST = 8'h01, + REG_TEST2 = 8'h02, + REG_KON = 8'h08, + REG_NOISE = 8'h0f, + REG_CLKA1 = 8'h10, + REG_CLKA2 = 8'h11, + REG_CLKB = 8'h12, + REG_TIMER = 8'h14, + REG_LFRQ = 8'h18, + REG_PMDAMD = 8'h19, + REG_CTW = 8'h1b, + REG_DUMP = 8'h1f; + +reg csm; + +always @(posedge clk, posedge rst) begin : memory_mapped_registers + if( rst ) begin + selected_register <= 8'h0; + { up_rl, up_kc, up_kf, up_pms, up_dt1, up_tl, + up_ks, up_amsen, up_dt2, up_d1l, up_keyon } <= 11'd0; + `ifdef TEST_SUPPORT + { test_eg, test_op0 } <= 2'd0; + `endif + // noise + nfrq <= 5'b0; + ne <= 1'b0; + // timers + { value_A, value_B } <= 18'd0; + { clr_flag_B, clr_flag_A, + enable_irq_B, enable_irq_A, load_B, load_A } <= 6'd0; + // LFO + { lfo_amd, lfo_pmd } <= 14'h0; + lfo_up <= 1'b0; + lfo_freq <= 8'd0; + lfo_w <= 2'd0; + { ct2, ct1 } <= 2'd0; + csm <= 1'b0; + din_copy <= 8'd0; + test_mode <= 8'd0; + `ifdef SIMULATION + mmr_dump <= 1'b0; + `endif + end else begin + // WRITE IN REGISTERS + if( write ) begin + if( !a0 ) + selected_register <= din; + else begin + din_copy <= din; + up_op <= selected_register[4:3]; // operator to update + up_ch <= selected_register[2:0]; // channel to update + up_rl <= 1'b0; + up_kc <= 1'b0; + up_kf <= 1'b0; + up_pms <= 1'b0; + up_dt1 <= 1'b0; + up_tl <= 1'b0; + up_ks <= 1'b0; + up_amsen <= 1'b0; + up_dt2 <= 1'b0; + up_d1l <= 1'b0; + up_keyon <= 1'b0; + // Global registers + if( selected_register < 8'h20 ) begin + case( selected_register) + // registros especiales + REG_TEST: test_mode <= din; // regardless of din + `ifdef TEST_SUPPORT + REG_TEST2: { test_op0, test_eg } <= din[1:0]; + `endif + REG_KON: up_keyon <= 1'b1; + REG_NOISE: { ne, nfrq } <= { din[7], din[4:0] }; + REG_CLKA1: value_A[9:2] <= din; + REG_CLKA2: value_A[1:0] <= din[1:0]; + REG_CLKB: value_B <= din; + REG_TIMER: begin + csm <= din[7]; + { clr_flag_B, clr_flag_A, + enable_irq_B, enable_irq_A, + load_B, load_A } <= din[5:0]; + end + REG_LFRQ: begin + lfo_freq <= din; + lfo_up <= 1; + end + REG_PMDAMD: begin + if( !din[7] ) + lfo_amd <= din[6:0]; + else + lfo_pmd <= din[6:0]; + end + REG_CTW: begin + { ct2, ct1 } <= din[7:6]; + lfo_w <= din[1:0]; + end + `ifdef SIMULATION + REG_DUMP: + mmr_dump <= 1'b1; + `endif + default:; + endcase + end else + // channel registers + if( selected_register < 8'h40 ) begin + case( selected_register[4:3] ) + 2'h0: up_rl <= 1'b1; + 2'h1: up_kc <= 1'b1; + 2'h2: up_kf <= 1'b1; + 2'h3: up_pms<= 1'b1; + endcase + end + else + // operator registers + begin + case( selected_register[7:5] ) + 3'h2: up_dt1 <= 1'b1; + 3'h3: up_tl <= 1'b1; + 3'h4: up_ks <= 1'b1; + 3'h5: up_amsen <= 1'b1; + 3'h6: up_dt2 <= 1'b1; + 3'h7: up_d1l <= 1'b1; + default:; + endcase + end + end + end + else begin /* clear once-only bits */ + `ifdef SIMULATION + mmr_dump <= 1'b0; + `endif + csm <= 0; + lfo_up <= 0; + { clr_flag_B, clr_flag_A } <= 2'd0; + end + end +end + +reg [4:0] busy_cnt; // busy lasts for 32 synth clock cycles +reg old_write; + +always @(posedge clk) + if( rst ) begin + busy <= 1'b0; + busy_cnt <= 5'd0; + end + else begin + old_write <= write; + if (!old_write && write && a0 ) begin // only set for data writes + busy <= 1'b1; + busy_cnt <= 5'd0; + end + else if(cen) begin + if( busy_cnt == 5'd31 ) busy <= 1'b0; + busy_cnt <= busy_cnt+5'd1; + end + end + +jt51_reg u_reg( + .rst ( rst ), + .clk ( clk ), // P1 + .cen ( cen ), // P1 + .din ( din_copy ), + + .up_rl ( up_rl ), + .up_kc ( up_kc ), + .up_kf ( up_kf ), + .up_pms ( up_pms ), + .up_dt1 ( up_dt1 ), + .up_tl ( up_tl ), + .up_ks ( up_ks ), + .up_amsen ( up_amsen ), + .up_dt2 ( up_dt2 ), + .up_d1l ( up_d1l ), + .up_keyon ( up_keyon ), + .op ( up_op ), // operator to update + .ch ( up_ch ), // channel to update + + .csm ( csm ), + .overflow_A ( overflow_A), + + .rl_I ( rl_I ), + .fb_II ( fb_II ), + .con_I ( con_I ), + + .kc_I ( kc_I ), + .kf_I ( kf_I ), + .pms_I ( pms_I ), + .ams_VII ( ams_VII ), + + .dt1_II ( dt1_II ), + .dt2_I ( dt2_I ), + .mul_VI ( mul_VI ), + .tl_VII ( tl_VII ), + .ks_III ( ks_III ), + + .arate_II ( arate_II ), + .amsen_VII ( amsen_VII ), + .rate1_II ( rate1_II ), + .rate2_II ( rate2_II ), + .rrate_II ( rrate_II ), + .d1l_I ( d1l_I ), + .keyon_II ( keyon_II ), + + .cur_op ( cur_op ), + .op31_no ( op31_no ), + .op31_acc ( op31_acc ), + .zero ( zero ), + .half ( half ), + .cycles ( cycles ), + .m1_enters ( m1_enters ), + .m2_enters ( m2_enters ), + .c1_enters ( c1_enters ), + .c2_enters ( c2_enters ), + // Operator + .use_prevprev1 ( use_prevprev1 ), + .use_internal_x ( use_internal_x ), + .use_internal_y ( use_internal_y ), + .use_prev2 ( use_prev2 ), + .use_prev1 ( use_prev1 ) +); + +`ifdef SIMULATION +`ifndef VERILATOR +integer fdump; +integer clk_count; +initial begin + clk_count=0; + fdump=$fopen("jt51_cmd.txt","w"); +end + +always @(posedge clk) clk_count <= clk_count+1; + +always @(posedge write) begin + $fdisplay(fdump,"%d,%d,%X",clk_count,a0,din); +end +`endif +`endif + + +`ifdef JT51_DEBUG +`ifdef SIMULATION +/* verilator lint_off PINMISSING */ +wire [4:0] cnt_aux; + +sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt_aux)); + +sep32 #(.width(2),.stg(1)) sep_rl (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( rl_I )); +sep32 #(.width(3),.stg(2)) sep_fb (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( fb_II )); +sep32 #(.width(3),.stg(1)) sep_con(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( con_I )); + +sep32 #(.width(7),.stg(1)) sep_kc (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( kc_I )); +sep32 #(.width(6),.stg(1)) sep_kf (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( kf_I )); +sep32 #(.width(3),.stg(1)) sep_pms(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( pms_I )); +sep32 #(.width(2),.stg(7)) sep_ams(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( ams_VII )); + +sep32 #(.width(3),.stg(2)) sep_dt1(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( dt1_II )); +sep32 #(.width(2),.stg(1)) sep_dt2(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( dt2_I )); +sep32 #(.width(4),.stg(6)) sep_mul(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( mul_VI )); +sep32 #(.width(7),.stg(7)) sep_tl (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( tl_VII )); +sep32 #(.width(2),.stg(3)) sep_ks (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( ks_III )); + +sep32 #(.width(5),.stg(2)) sep_ar (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( arate_II )); +sep32 #(.width(1),.stg(7)) sep_ame(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( amsen_VII)); +sep32 #(.width(5),.stg(2)) sep_dr1(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( rate1_II )); +sep32 #(.width(5),.stg(2)) sep_dr2(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( rate2_II )); +sep32 #(.width(4),.stg(2)) sep_rr (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( rrate_II )); +sep32 #(.width(4),.stg(1)) sep_d1l(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( d1l_I )); +`endif +`endif + +endmodule diff --git a/modules/sound-jt51/jt51_mod.v b/modules/sound-jt51/jt51_mod.v new file mode 100644 index 0000000..a7346ba --- /dev/null +++ b/modules/sound-jt51/jt51_mod.v @@ -0,0 +1,66 @@ + + +/* This file is part of JT51. + + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-4-2017 + +*/ + +module jt51_mod( + input m1_enters, + input m2_enters, + input c1_enters, + input c2_enters, + + input [2:0] alg_I, + + output reg use_prevprev1, + output reg use_internal_x, + output reg use_internal_y, + output reg use_prev2, + output reg use_prev1 +); + +reg [7:0] alg_hot; + +always @(*) begin + case( alg_I ) + 3'd0: alg_hot = 8'h1; // D0 + 3'd1: alg_hot = 8'h2; // D1 + 3'd2: alg_hot = 8'h4; // D2 + 3'd3: alg_hot = 8'h8; // D3 + 3'd4: alg_hot = 8'h10; // D4 + 3'd5: alg_hot = 8'h20; // D5 + 3'd6: alg_hot = 8'h40; // D6 + 3'd7: alg_hot = 8'h80; // D7 + default: alg_hot = 8'hx; + endcase +end + +always @(*) begin + use_prevprev1 = m1_enters | (m2_enters&alg_hot[5]); + use_prev2 = (m2_enters&(|alg_hot[2:0])) | (c2_enters&alg_hot[3]); + use_internal_x = c2_enters & alg_hot[2]; + use_internal_y = c2_enters & (|{alg_hot[4:3],alg_hot[1:0]}); + use_prev1 = m1_enters | (m2_enters&alg_hot[1]) | + (c1_enters&(|{alg_hot[6:3],alg_hot[0]}) )| + (c2_enters&(|{alg_hot[5],alg_hot[2]})); +end + +endmodule diff --git a/modules/sound-jt51/jt51_noise.v b/modules/sound-jt51/jt51_noise.v new file mode 100644 index 0000000..1f7d78f --- /dev/null +++ b/modules/sound-jt51/jt51_noise.v @@ -0,0 +1,109 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 6-2-2021 + */ + + +/* + + NFRQ formula in the App: + Output rate is 55kHz but for NFRQ=1 the formula states that + the noise is 111kHz, twice the output rate per channel. The + reason must be the inversion of the LFSR data + + That would suggest that the noise for LEFT and RIGHT are + different but the rest of the system suggest that LEFT and + RIGHT outputs are calculated at the same time, based on the + same OP output. + + I have not been able to measure noise in actual chip because + operator 31 does not produce any output on my two chips. This + module is based on NukeYKT's work + +*/ + +module jt51_noise( + input rst, + input clk, + input cen, // phi 1 + input [ 4:0] cycles, + + // Noise Frequency + input [ 4:0] nfrq, + + // Noise envelope + input [ 9:0] eg, // serial signal in the original design + input op31_no, + + output out, + output reg [11:0] mix +); + +reg update, nfrq_met; +reg [ 4:0] cnt; +reg [15:0] lfsr; +reg last_lfsr0; +wire all1, fb; +wire mix_sgn; + +assign out = lfsr[0]; + +// period counter + +always @(posedge clk, posedge rst) begin + if( rst ) begin + cnt <= 5'b0; + end else if(cen) begin + if( &cycles[3:0] ) begin + cnt <= update ? 5'd0 : (cnt+5'd1); + end + update <= nfrq_met; + nfrq_met <= ~nfrq == cnt; + end +end + +// LFSR + +assign fb = update ? ~((all1 & ~last_lfsr0) | (lfsr[2]^last_lfsr0)) + : ~lfsr[0]; +assign all1 = &lfsr; + +always @(posedge clk, posedge rst) begin + if( rst ) begin + lfsr <= 16'hffff; + last_lfsr0 <= 1'b0; + end else if(cen) begin + lfsr <= { fb, lfsr[15:1] }; + if(update) last_lfsr0 <= ~lfsr[0]; + end +end + + +// Noise mix + +assign mix_sgn = /*eg!=10'd0 ^*/ ~out; + +always @(posedge clk, posedge rst) begin + if( rst ) begin + mix <= 12'd0; + end else if( op31_no && cen ) begin + mix <= { mix_sgn, eg[9:2] ^ {8{out}}, {3{mix_sgn}} }; + end +end + +endmodule diff --git a/modules/sound-jt51/jt51_noise_lfsr.v b/modules/sound-jt51/jt51_noise_lfsr.v new file mode 100644 index 0000000..4b6a47f --- /dev/null +++ b/modules/sound-jt51/jt51_noise_lfsr.v @@ -0,0 +1,47 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +// See xapp052.pdf from Xilinx + +module jt51_noise_lfsr #(parameter init=14220 )( + input rst, + input clk, + input cen, + input base, + output out +); + +reg [16:0] bb; +assign out = bb[16]; + +always @(posedge clk, posedge rst) begin : base_counter + if( rst ) begin + bb <= init[16:0]; + end + else if(cen) begin + if( base ) begin + bb[16:1] <= bb[15:0]; + bb[0] <= ~(bb[16]^bb[13]); + end + end +end + +endmodule diff --git a/modules/sound-jt51/jt51_op.v b/modules/sound-jt51/jt51_op.v new file mode 100644 index 0000000..0058107 --- /dev/null +++ b/modules/sound-jt51/jt51_op.v @@ -0,0 +1,343 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +// Pipeline operator + +module jt51_op( + `ifdef TEST_SUPPORT + input test_eg, + input test_op0, + `endif + input rst, + input clk, + input cen, // P1 + input [9:0] pg_phase_X, + input [2:0] con_I, + input [2:0] fb_II, + // volume + input [9:0] eg_atten_XI, + // modulation + input use_prevprev1, + input use_internal_x, + input use_internal_y, + input use_prev2, + input use_prev1, + input test_214, + + input m1_enters, + input c1_enters, + `ifdef SIMULATION + input zero, + `endif + // output data + output signed [13:0] op_XVII +); + +/* enters exits + m1 c1 + m2 S4 + c1 m1 + S4 m2 +*/ + +wire signed [13:0] prev1, prevprev1, prev2; + +jt51_sh #( .width(14), .stages(8)) prev1_buffer( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( c1_enters ? op_XVII : prev1 ), + .drop ( prev1 ) +); + +jt51_sh #( .width(14), .stages(8)) prevprev1_buffer( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( c1_enters ? prev1 : prevprev1 ), + .drop ( prevprev1 ) +); + +jt51_sh #( .width(14), .stages(8)) prev2_buffer( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( m1_enters ? op_XVII : prev2 ), + .drop ( prev2 ) +); + +// REGISTER/CYCLE 1 +// Creation of phase modulation (FM) feedback signal, before shifting +reg [13:0] x, y; +reg [14:0] xs, ys, pm_preshift_II; +reg m1_II; + +always @(*) begin + x = ( {14{use_prevprev1}} & prevprev1 ) | + ( {14{use_internal_x}} & op_XVII ) | + ( {14{use_prev2}} & prev2 ); + y = ( {14{use_prev1}} & prev1 ) | + ( {14{use_internal_y}} & op_XVII ); + xs = { x[13], x }; // sign-extend + ys = { y[13], y }; // sign-extend +end + +always @(posedge clk) if(cen) begin + pm_preshift_II <= xs + ys; // carry is discarded + m1_II <= m1_enters; +end + +/* REGISTER/CYCLE 2-7 (also YM2612 extra cycles 1-6) + Shifting of FM feedback signal, adding phase from PG to FM phase + In YM2203, phasemod_II is not registered at all, it is latched on the first edge + in add_pg_phase and the second edge is the output of add_pg_phase. In the YM2612, there + are 6 cycles worth of registers between the generated (non-registered) phasemod_II signal + and the input to add_pg_phase. */ + +reg [9:0] phasemod_II; +wire [9:0] phasemod_X; + +always @(*) begin + // Shift FM feedback signal + if (!m1_II ) // Not m1 + phasemod_II = pm_preshift_II[10:1]; // Bit 0 of pm_preshift_II is never used + else // m1 + case( fb_II ) + 3'd0: phasemod_II = 10'd0; + 3'd1: phasemod_II = { {4{pm_preshift_II[14]}}, pm_preshift_II[14:9] }; + 3'd2: phasemod_II = { {3{pm_preshift_II[14]}}, pm_preshift_II[14:8] }; + 3'd3: phasemod_II = { {2{pm_preshift_II[14]}}, pm_preshift_II[14:7] }; + 3'd4: phasemod_II = { pm_preshift_II[14], pm_preshift_II[14:6] }; + 3'd5: phasemod_II = pm_preshift_II[14:5]; + 3'd6: phasemod_II = pm_preshift_II[13:4]; + 3'd7: phasemod_II = pm_preshift_II[12:3]; + default: phasemod_II = 10'dx; + endcase +end + +// REGISTER/CYCLE 2-9 +jt51_sh #( .width(10), .stages(8)) phasemod_sh( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( phasemod_II ), + .drop ( phasemod_X ) +); + + +// REGISTER/CYCLE 10 +reg [ 9:0] phase; +// Sets the maximum number of fanouts for a register or combinational +// cell. The Quartus II software will replicate the cell and split +// the fanouts among the duplicates until the fanout of each cell +// is below the maximum. + +reg [ 7:0] phaselo_XI, aux_X; +reg signbit_X; + +always @(*) begin + phase = phasemod_X + pg_phase_X; + aux_X = phase[7:0] ^ {8{~phase[8]}}; + signbit_X = phase[9]; +end + +always @(posedge clk) if(cen) begin + phaselo_XI <= aux_X; +end + +wire [45:0] sta_XI; + +jt51_phrom u_phrom( + .clk ( clk ), + .cen ( cen ), + .addr ( aux_X[5:1]), + .ph ( sta_XI ) +); + +// REGISTER/CYCLE 11 +// Sine table +// Main sine table body +reg [18:0] stb; +reg [10:0] stf, stg; +reg [11:0] logsin; +reg [10:0] subtresult; +reg [11:0] atten_internal_XI; + +always @(*) begin + //sta_XI = sinetable[ phaselo_XI[5:1] ]; + // 2-bit row chooser + case( phaselo_XI[7:6] ) + 2'b00: stb = { 10'b0, sta_XI[29], sta_XI[25], 2'b0, sta_XI[18], + sta_XI[14], 1'b0, sta_XI[7] , sta_XI[3] }; + 2'b01: stb = { 6'b0 , sta_XI[37], sta_XI[34], 2'b0, sta_XI[28], + sta_XI[24], 2'b0, sta_XI[17], sta_XI[13], sta_XI[10], sta_XI[6], sta_XI[2] }; + 2'b10: stb = { 2'b0, sta_XI[43], sta_XI[41], 2'b0, sta_XI[36], + sta_XI[33], 2'b0, sta_XI[27], sta_XI[23], 1'b0, sta_XI[20], + sta_XI[16], sta_XI[12], sta_XI[9], sta_XI[5], sta_XI[1] }; + 2'b11: stb = { + sta_XI[45], sta_XI[44], sta_XI[42], sta_XI[40] + , sta_XI[39], sta_XI[38], sta_XI[35], sta_XI[32] + , sta_XI[31], sta_XI[30], sta_XI[26], sta_XI[22] + , sta_XI[21], sta_XI[19], sta_XI[15], sta_XI[11] + , sta_XI[8], sta_XI[4], sta_XI[0] }; + default: stb = 19'dx; + endcase + // Fixed value to sum + stf = { stb[18:15], stb[12:11], stb[8:7], stb[4:3], stb[0] }; + // Gated value to sum; bit 14 is indeed used twice + if( phaselo_XI[0] ) + stg = { 2'b0, stb[14], stb[14:13], stb[10:9], stb[6:5], stb[2:1] }; + else + stg = 11'd0; + // Sum to produce final logsin value + logsin = stf + stg; // Carry-out of 11-bit addition becomes 12th bit + // Invert-subtract logsin value from EG attenuation value, with inverted carry + // In the actual chip, the output of the above logsin sum is already inverted. + // The two LSBs go through inverters (so they're non-inverted); the eg_atten_XI signal goes through inverters. + // The adder is normal except the carry-in is 1. It's a 10-bit adder. + // The outputs are inverted outputs, including the carry bit. + //subtresult = not (('0' & not eg_atten_XI) - ('1' & logsin([11:2]))); + // After a little pencil-and-paper, turns out this is equivalent to a regular adder! + subtresult = eg_atten_XI + logsin[11:2]; + // Place all but carry bit into result; also two LSBs of logsin + // If addition overflowed, make it the largest value (saturate) + atten_internal_XI = { subtresult[9:0], logsin[1:0] } | {12{subtresult[10]}}; +end + + +// Register cycle 12 +// Exponential table +wire [44:0] exp_XII; +reg [11:0] totalatten_XII; +reg [12:0] etb; +reg [ 9:0] etf; +reg [ 2:0] etg; + +jt51_exprom u_exprom( + .clk ( clk ), + .cen ( cen ), + .addr ( atten_internal_XI[5:1] ), + .exp ( exp_XII ) +); + +always @(posedge clk) if(cen) begin + totalatten_XII <= atten_internal_XI; +end + +//wire [1:0] et_sel = totalatten_XII[7:6]; +//wire [4:0] et_fine = totalatten_XII[5:1]; + +// Main sine table body +always @(*) begin + // 2-bit row chooser + case( totalatten_XII[7:6] ) + 2'b00: begin + etf = { 1'b1, exp_XII[44:36] }; + etg = { 1'b1, exp_XII[35:34] }; + end + 2'b01: begin + etf = exp_XII[33:24]; + etg = { 2'b10, exp_XII[23] }; + end + 2'b10: begin + etf = { 1'b0, exp_XII[22:14] }; + etg = exp_XII[13:11]; + end + 2'b11: begin + etf = { 2'b00, exp_XII[10:3] }; + etg = exp_XII[2:0]; + end + endcase +end + +reg [9:0] mantissa_XIII; +reg [3:0] exponent_XIII; + +always @(posedge clk) if(cen) begin + //RESULT + mantissa_XIII <= etf + { 7'd0, totalatten_XII[0] ? 3'd0 : etg }; //carry-out discarded + exponent_XIII <= totalatten_XII[11:8]; +end + +// REGISTER/CYCLE 13 +// Introduce test bit as MSB, 2's complement & Carry-out discarded +reg [12:0] shifter, shifter_2, shifter_3; + +always @(*) begin + // Floating-point to integer, and incorporating sign bit + // Two-stage shifting of mantissa_XIII by exponent_XIII + shifter = { 3'b001, mantissa_XIII }; + case( ~exponent_XIII[1:0] ) + 2'b00: shifter_2 = { 1'b0, shifter[12:1] }; // LSB discarded + 2'b01: shifter_2 = shifter; + 2'b10: shifter_2 = { shifter[11:0], 1'b0 }; + 2'b11: shifter_2 = { shifter[10:0], 2'b0 }; + endcase + case( ~exponent_XIII[3:2] ) + 2'b00: shifter_3 = {12'b0, shifter_2[12] }; + 2'b01: shifter_3 = { 8'b0, shifter_2[12:8] }; + 2'b10: shifter_3 = { 4'b0, shifter_2[12:4] }; + 2'b11: shifter_3 = shifter_2; + endcase +end + +reg signed [13:0] op_XIII; +wire signbit_XIII; + +always @(*) begin + op_XIII = ({ test_214, shifter_3 } ^ {14{signbit_XIII}}) + {13'd0, signbit_XIII}; +end + +jt51_sh #( .width(14), .stages(4)) out_padding( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( op_XIII ), // note op_XIII was not latched, is a comb output + .drop ( op_XVII ) +); + +jt51_sh #( .width(1), .stages(3)) shsignbit( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( signbit_X ), + .drop ( signbit_XIII ) +); + +/////////////////// Debug +`ifdef JT51_DEBUG +`ifdef SIMULATION +/* verilator lint_off PINMISSING */ +wire [4:0] cnt; + +sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt)); + +sep32 #(.width(14),.stg(17)) sep_op( + .clk ( clk ), + .cen ( cen ), + .mixed ( op_XVII ), + .cnt ( cnt ) + ); +/* verilator lint_on PINMISSING */ +`endif +`endif + +endmodule diff --git a/modules/sound-jt51/jt51_pg.v b/modules/sound-jt51/jt51_pg.v new file mode 100644 index 0000000..1593f00 --- /dev/null +++ b/modules/sound-jt51/jt51_pg.v @@ -0,0 +1,339 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_pg( + input rst, + input clk, + input cen /* direct_enable */, + input zero, + // Channel frequency + input [6:0] kc_I, + input [5:0] kf_I, + // Operator multiplying + input [3:0] mul_VI, + // Operator detuning + input [2:0] dt1_II, + input [1:0] dt2_I, + // phase modulation from LFO + input [7:0] pm, + input [2:0] pms_I, + // phase operation + input pg_rst_III, + output reg [ 4:0] keycode_III, + output [ 9:0] pg_phase_X + `ifdef JT51_PG_SIM + ,output [19:0] phase_step_VII_out + ,output [12:0] keycode_I_out + `endif +); + +wire [19:0] ph_VII; + +reg [19:0] phase_base_VI, phase_step_VII, ph_VIII; +reg [17:0] phase_base_IV, phase_base_V; +wire pg_rst_VII; + +wire [11:0] phinc_III; + +reg [ 9:0] phinc_addr_III; + +reg [13:0] keycode_II; +reg [5:0] dt1_kf_III; +reg [ 2:0] dt1_kf_IV; + +reg [4:0] pow2; +reg [4:0] dt1_offset_V; +reg [2:0] pow2ind_IV; + +reg [2:0] dt1_III, dt1_IV, dt1_V; + +`ifdef JT51_PG_SIM +assign phase_step_VII_out = phase_step_VII; +assign keycode_I_out = keycode_I; +`endif + +jt51_phinc_rom u_phinctable( + // .clk ( clk ), + .keycode( phinc_addr_III[9:0] ), + .phinc ( phinc_III ) +); + +always @(*) begin : calcpow2 + case( pow2ind_IV ) + 3'd0: pow2 = 5'd16; + 3'd1: pow2 = 5'd17; + 3'd2: pow2 = 5'd19; + 3'd3: pow2 = 5'd20; + 3'd4: pow2 = 5'd22; + 3'd5: pow2 = 5'd24; + 3'd6: pow2 = 5'd26; + 3'd7: pow2 = 5'd29; + endcase +end + +reg [5:0] dt1_limit, dt1_unlimited; +reg [4:0] dt1_limited_IV; + +always @(*) begin : dt1_limit_mux + case( dt1_IV[1:0] ) + default: dt1_limit = 6'd8; + 2'd1: dt1_limit = 6'd8; + 2'd2: dt1_limit = 6'd16; + 2'd3: dt1_limit = 6'd22; + endcase + case( dt1_kf_IV ) + 3'd0: dt1_unlimited = { 5'd0, pow2[4] }; // <2 + 3'd1: dt1_unlimited = { 4'd0, pow2[4:3] }; // <4 + 3'd2: dt1_unlimited = { 3'd0, pow2[4:2] }; // <8 + 3'd3: dt1_unlimited = { 2'd0, pow2[4:1] }; + 3'd4: dt1_unlimited = { 1'd0, pow2[4:0] }; + 3'd5: dt1_unlimited = { pow2[4:0], 1'd0 }; + default:dt1_unlimited = 6'd0; + endcase + dt1_limited_IV = dt1_unlimited > dt1_limit ? + dt1_limit[4:0] : dt1_unlimited[4:0]; +end + +reg signed [8:0] mod_I; + +always @(*) begin + case( pms_I ) // comprobar en silicio + 3'd0: mod_I = 9'd0; + 3'd1: mod_I = { 7'd0, pm[6:5] }; + 3'd2: mod_I = { 6'd0, pm[6:4] }; + 3'd3: mod_I = { 5'd0, pm[6:3] }; + 3'd4: mod_I = { 4'd0, pm[6:2] }; + 3'd5: mod_I = { 3'd0, pm[6:1] }; + 3'd6: mod_I = { 1'd0, pm[6:0], 1'b0 }; + 3'd7: mod_I = { pm[6:0], 2'b0 }; + endcase +end + + +reg [3:0] octave_III; + +wire [12:0] keycode_I; + +jt51_pm u_pm( + // Channel frequency + .kc_I ( kc_I ), + .kf_I ( kf_I ), + .add ( ~pm[7] ), + .mod_I ( mod_I ), + .kcex ( keycode_I ) +); + +// limit value at which we add +64 to the keycode +// I assume this is to avoid the note==3 violation somehow +parameter dt2_lim2 = 8'd11 + 8'd64; +parameter dt2_lim3 = 8'd31 + 8'd64; + + // I +always @(posedge clk) if(cen) begin : phase_calculation + case ( dt2_I ) + 2'd0: keycode_II <= { 1'b0, keycode_I } + + (keycode_I[7:6]==2'd3 ? 14'd64:14'd0); + 2'd1: keycode_II <= { 1'b0, keycode_I } + 14'd512 + + (keycode_I[7:6]==2'd3 ? 14'd64:14'd0); + 2'd2: keycode_II <= { 1'b0, keycode_I } + 14'd628 + + (keycode_I[7:0]>dt2_lim2 ? 14'd64:14'd0); + 2'd3: keycode_II <= { 1'b0, keycode_I } + 14'd800 + + (keycode_I[7:0]>dt2_lim3 ? 14'd64:14'd0); + endcase +end + + // II +always @(posedge clk) if(cen) begin + phinc_addr_III <= keycode_II[9:0]; + octave_III <= keycode_II[13:10]; + keycode_III <= keycode_II[12:8]; + // Using bits 13:9 fixes Double Dragon issue #14 + // but notes get too long in Jackal + case( dt1_II[1:0] ) + 2'd1: dt1_kf_III <= keycode_II[13:8] - (6'b1<<2); + 2'd2: dt1_kf_III <= keycode_II[13:8] + (6'b1<<2); + 2'd3: dt1_kf_III <= keycode_II[13:8] + (6'b1<<3); + default:dt1_kf_III <= keycode_II[13:8]; + endcase + dt1_III <= dt1_II; +end + + // III +always @(posedge clk) if(cen) begin + case( octave_III ) + 4'd0: phase_base_IV <= { 8'd0, phinc_III[11:2] }; + 4'd1: phase_base_IV <= { 7'd0, phinc_III[11:1] }; + 4'd2: phase_base_IV <= { 6'd0, phinc_III[11:0] }; + 4'd3: phase_base_IV <= { 5'd0, phinc_III[11:0], 1'b0 }; + 4'd4: phase_base_IV <= { 4'd0, phinc_III[11:0], 2'b0 }; + 4'd5: phase_base_IV <= { 3'd0, phinc_III[11:0], 3'b0 }; + 4'd6: phase_base_IV <= { 2'd0, phinc_III[11:0], 4'b0 }; + 4'd7: phase_base_IV <= { 1'd0, phinc_III[11:0], 5'b0 }; + 4'd8: phase_base_IV <= { phinc_III[11:0], 6'b0 }; + default:phase_base_IV <= 18'd0; + endcase + pow2ind_IV <= dt1_kf_III[2:0]; + dt1_IV <= dt1_III; + dt1_kf_IV <= dt1_kf_III[5:3]; +end + + // IV LIMIT_BASE +always @(posedge clk) if(cen) begin + if( phase_base_IV > 18'd82976 ) + phase_base_V <= 18'd82976; + else + phase_base_V <= phase_base_IV; + dt1_offset_V <= dt1_limited_IV; + dt1_V <= dt1_IV; +end + + // V APPLY_DT1 +always @(posedge clk) if(cen) begin + if( dt1_V[1:0]==2'd0 ) + phase_base_VI <= {2'b0, phase_base_V}; + else begin + if( !dt1_V[2] ) + phase_base_VI <= {2'b0, phase_base_V} + { 15'd0, dt1_offset_V }; + else + phase_base_VI <= {2'b0, phase_base_V} - { 15'd0, dt1_offset_V }; + end +end + + // VI APPLY_MUL +always @(posedge clk) if(cen) begin + if( mul_VI==4'd0 ) + phase_step_VII <= { 1'b0, phase_base_VI[19:1] }; + else + phase_step_VII <= phase_base_VI * mul_VI; +end + +// VII have same number of stages as jt51_envelope +always @(posedge clk, posedge rst) begin + if( rst ) + ph_VIII <= 20'd0; + else if(cen) begin + ph_VIII <= pg_rst_VII ? 20'd0 : ph_VII + phase_step_VII; + `ifdef DISPLAY_STEP + $display( "%d", phase_step_VII ); + `endif + end +end + +// VIII +reg [19:0] ph_IX; +always @(posedge clk, posedge rst) begin + if( rst ) + ph_IX <= 20'd0; + else if(cen) begin + ph_IX <= ph_VIII[19:0]; + end +end + +// IX +reg [19:0] ph_X; +assign pg_phase_X = ph_X[19:10]; +always @(posedge clk, posedge rst) begin + if( rst ) begin + ph_X <= 20'd0; + end else if(cen) begin + ph_X <= ph_IX; + end +end + +jt51_sh #( .width(20), .stages(32-3) ) u_phsh( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( ph_X ), + .drop ( ph_VII ) +); + +jt51_sh #( .width(1), .stages(4) ) u_pgrstsh( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( pg_rst_III), + .drop ( pg_rst_VII) +); + +`ifdef JT51_DEBUG +`ifdef SIMULATION +/* verilator lint_off PINMISSING */ + +wire [4:0] cnt; + +sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt)); + +sep32 #(.width(10),.stg(10)) sep_ph( + .clk ( clk ), + .cen ( cen ), + .mixed ( pg_phase_X ), + .cnt ( cnt ) +); + +sep32 #(.width(20),.stg(7)) sep_phstep( + .clk ( clk ), + .cen ( cen ), + .mixed ( phase_step_VII), + .cnt ( cnt ) +); + +sep32 #(.width(13),.stg(1)) sep_kc1( + .clk ( clk ), + .cen ( cen ), + .mixed ( keycode_I ), + .cnt ( cnt ) +); + +sep32 #(.width(14),.stg(2)) sep_kc2( + .clk ( clk ), + .cen ( cen ), + .mixed ( keycode_II ), + .cnt ( cnt ) +); + +sep32 #(.width(3),.stg(1)) sep_pms( + .clk ( clk ), + .cen ( cen ), + .mixed ( pms_I ), + .cnt ( cnt ) +); + +sep32 #(.width(18),.stg(4)) sep_base4( + .clk ( clk ), + .cen ( cen ), + .mixed ( phase_base_IV ), + .cnt ( cnt ) +); + +sep32 #(.width(18),.stg(5)) sep_base5( + .clk ( clk ), + .cen ( cen ), + .mixed ( phase_base_V ), + .cnt ( cnt ) +); + +/* verilator lint_on PINMISSING */ +`endif +`endif + +endmodule + diff --git a/modules/sound-jt51/jt51_phinc_rom.v b/modules/sound-jt51/jt51_phinc_rom.v new file mode 100644 index 0000000..d9ebc97 --- /dev/null +++ b/modules/sound-jt51/jt51_phinc_rom.v @@ -0,0 +1,1057 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_phinc_rom( + // input clk, + input [9:0] keycode, + output reg [11:0] phinc +); + +always @(*) begin : read_lut + case( keycode ) + 10'd0: phinc = { 12'd1299 }; // nota = 0, KF = 0 + 10'd1: phinc = { 12'd1300 }; // nota = 0, KF = 1 + 10'd2: phinc = { 12'd1301 }; // nota = 0, KF = 2 + 10'd3: phinc = { 12'd1302 }; // nota = 0, KF = 3 + 10'd4: phinc = { 12'd1303 }; // nota = 0, KF = 4 + 10'd5: phinc = { 12'd1304 }; // nota = 0, KF = 5 + 10'd6: phinc = { 12'd1305 }; // nota = 0, KF = 6 + 10'd7: phinc = { 12'd1306 }; // nota = 0, KF = 7 + 10'd8: phinc = { 12'd1308 }; // nota = 0, KF = 8 + 10'd9: phinc = { 12'd1309 }; // nota = 0, KF = 9 + 10'd10: phinc = { 12'd1310 }; // nota = 0, KF = 10 + 10'd11: phinc = { 12'd1311 }; // nota = 0, KF = 11 + 10'd12: phinc = { 12'd1313 }; // nota = 0, KF = 12 + 10'd13: phinc = { 12'd1314 }; // nota = 0, KF = 13 + 10'd14: phinc = { 12'd1315 }; // nota = 0, KF = 14 + 10'd15: phinc = { 12'd1316 }; // nota = 0, KF = 15 + 10'd16: phinc = { 12'd1318 }; // nota = 0, KF = 16 + 10'd17: phinc = { 12'd1319 }; // nota = 0, KF = 17 + 10'd18: phinc = { 12'd1320 }; // nota = 0, KF = 18 + 10'd19: phinc = { 12'd1321 }; // nota = 0, KF = 19 + 10'd20: phinc = { 12'd1322 }; // nota = 0, KF = 20 + 10'd21: phinc = { 12'd1323 }; // nota = 0, KF = 21 + 10'd22: phinc = { 12'd1324 }; // nota = 0, KF = 22 + 10'd23: phinc = { 12'd1325 }; // nota = 0, KF = 23 + 10'd24: phinc = { 12'd1327 }; // nota = 0, KF = 24 + 10'd25: phinc = { 12'd1328 }; // nota = 0, KF = 25 + 10'd26: phinc = { 12'd1329 }; // nota = 0, KF = 26 + 10'd27: phinc = { 12'd1330 }; // nota = 0, KF = 27 + 10'd28: phinc = { 12'd1332 }; // nota = 0, KF = 28 + 10'd29: phinc = { 12'd1333 }; // nota = 0, KF = 29 + 10'd30: phinc = { 12'd1334 }; // nota = 0, KF = 30 + 10'd31: phinc = { 12'd1335 }; // nota = 0, KF = 31 + 10'd32: phinc = { 12'd1337 }; // nota = 0, KF = 32 + 10'd33: phinc = { 12'd1338 }; // nota = 0, KF = 33 + 10'd34: phinc = { 12'd1339 }; // nota = 0, KF = 34 + 10'd35: phinc = { 12'd1340 }; // nota = 0, KF = 35 + 10'd36: phinc = { 12'd1341 }; // nota = 0, KF = 36 + 10'd37: phinc = { 12'd1342 }; // nota = 0, KF = 37 + 10'd38: phinc = { 12'd1343 }; // nota = 0, KF = 38 + 10'd39: phinc = { 12'd1344 }; // nota = 0, KF = 39 + 10'd40: phinc = { 12'd1346 }; // nota = 0, KF = 40 + 10'd41: phinc = { 12'd1347 }; // nota = 0, KF = 41 + 10'd42: phinc = { 12'd1348 }; // nota = 0, KF = 42 + 10'd43: phinc = { 12'd1349 }; // nota = 0, KF = 43 + 10'd44: phinc = { 12'd1351 }; // nota = 0, KF = 44 + 10'd45: phinc = { 12'd1352 }; // nota = 0, KF = 45 + 10'd46: phinc = { 12'd1353 }; // nota = 0, KF = 46 + 10'd47: phinc = { 12'd1354 }; // nota = 0, KF = 47 + 10'd48: phinc = { 12'd1356 }; // nota = 0, KF = 48 + 10'd49: phinc = { 12'd1357 }; // nota = 0, KF = 49 + 10'd50: phinc = { 12'd1358 }; // nota = 0, KF = 50 + 10'd51: phinc = { 12'd1359 }; // nota = 0, KF = 51 + 10'd52: phinc = { 12'd1361 }; // nota = 0, KF = 52 + 10'd53: phinc = { 12'd1362 }; // nota = 0, KF = 53 + 10'd54: phinc = { 12'd1363 }; // nota = 0, KF = 54 + 10'd55: phinc = { 12'd1364 }; // nota = 0, KF = 55 + 10'd56: phinc = { 12'd1366 }; // nota = 0, KF = 56 + 10'd57: phinc = { 12'd1367 }; // nota = 0, KF = 57 + 10'd58: phinc = { 12'd1368 }; // nota = 0, KF = 58 + 10'd59: phinc = { 12'd1369 }; // nota = 0, KF = 59 + 10'd60: phinc = { 12'd1371 }; // nota = 0, KF = 60 + 10'd61: phinc = { 12'd1372 }; // nota = 0, KF = 61 + 10'd62: phinc = { 12'd1373 }; // nota = 0, KF = 62 + 10'd63: phinc = { 12'd1374 }; // nota = 0, KF = 63 + 10'd64: phinc = { 12'd1376 }; // nota = 1, KF = 0 + 10'd65: phinc = { 12'd1377 }; // nota = 1, KF = 1 + 10'd66: phinc = { 12'd1378 }; // nota = 1, KF = 2 + 10'd67: phinc = { 12'd1379 }; // nota = 1, KF = 3 + 10'd68: phinc = { 12'd1381 }; // nota = 1, KF = 4 + 10'd69: phinc = { 12'd1382 }; // nota = 1, KF = 5 + 10'd70: phinc = { 12'd1383 }; // nota = 1, KF = 6 + 10'd71: phinc = { 12'd1384 }; // nota = 1, KF = 7 + 10'd72: phinc = { 12'd1386 }; // nota = 1, KF = 8 + 10'd73: phinc = { 12'd1387 }; // nota = 1, KF = 9 + 10'd74: phinc = { 12'd1388 }; // nota = 1, KF = 10 + 10'd75: phinc = { 12'd1389 }; // nota = 1, KF = 11 + 10'd76: phinc = { 12'd1391 }; // nota = 1, KF = 12 + 10'd77: phinc = { 12'd1392 }; // nota = 1, KF = 13 + 10'd78: phinc = { 12'd1393 }; // nota = 1, KF = 14 + 10'd79: phinc = { 12'd1394 }; // nota = 1, KF = 15 + 10'd80: phinc = { 12'd1396 }; // nota = 1, KF = 16 + 10'd81: phinc = { 12'd1397 }; // nota = 1, KF = 17 + 10'd82: phinc = { 12'd1398 }; // nota = 1, KF = 18 + 10'd83: phinc = { 12'd1399 }; // nota = 1, KF = 19 + 10'd84: phinc = { 12'd1401 }; // nota = 1, KF = 20 + 10'd85: phinc = { 12'd1402 }; // nota = 1, KF = 21 + 10'd86: phinc = { 12'd1403 }; // nota = 1, KF = 22 + 10'd87: phinc = { 12'd1404 }; // nota = 1, KF = 23 + 10'd88: phinc = { 12'd1406 }; // nota = 1, KF = 24 + 10'd89: phinc = { 12'd1407 }; // nota = 1, KF = 25 + 10'd90: phinc = { 12'd1408 }; // nota = 1, KF = 26 + 10'd91: phinc = { 12'd1409 }; // nota = 1, KF = 27 + 10'd92: phinc = { 12'd1411 }; // nota = 1, KF = 28 + 10'd93: phinc = { 12'd1412 }; // nota = 1, KF = 29 + 10'd94: phinc = { 12'd1413 }; // nota = 1, KF = 30 + 10'd95: phinc = { 12'd1414 }; // nota = 1, KF = 31 + 10'd96: phinc = { 12'd1416 }; // nota = 1, KF = 32 + 10'd97: phinc = { 12'd1417 }; // nota = 1, KF = 33 + 10'd98: phinc = { 12'd1418 }; // nota = 1, KF = 34 + 10'd99: phinc = { 12'd1419 }; // nota = 1, KF = 35 + 10'd100: phinc = { 12'd1421 }; // nota = 1, KF = 36 + 10'd101: phinc = { 12'd1422 }; // nota = 1, KF = 37 + 10'd102: phinc = { 12'd1423 }; // nota = 1, KF = 38 + 10'd103: phinc = { 12'd1424 }; // nota = 1, KF = 39 + 10'd104: phinc = { 12'd1426 }; // nota = 1, KF = 40 + 10'd105: phinc = { 12'd1427 }; // nota = 1, KF = 41 + 10'd106: phinc = { 12'd1429 }; // nota = 1, KF = 42 + 10'd107: phinc = { 12'd1430 }; // nota = 1, KF = 43 + 10'd108: phinc = { 12'd1431 }; // nota = 1, KF = 44 + 10'd109: phinc = { 12'd1432 }; // nota = 1, KF = 45 + 10'd110: phinc = { 12'd1434 }; // nota = 1, KF = 46 + 10'd111: phinc = { 12'd1435 }; // nota = 1, KF = 47 + 10'd112: phinc = { 12'd1437 }; // nota = 1, KF = 48 + 10'd113: phinc = { 12'd1438 }; // nota = 1, KF = 49 + 10'd114: phinc = { 12'd1439 }; // nota = 1, KF = 50 + 10'd115: phinc = { 12'd1440 }; // nota = 1, KF = 51 + 10'd116: phinc = { 12'd1442 }; // nota = 1, KF = 52 + 10'd117: phinc = { 12'd1443 }; // nota = 1, KF = 53 + 10'd118: phinc = { 12'd1444 }; // nota = 1, KF = 54 + 10'd119: phinc = { 12'd1445 }; // nota = 1, KF = 55 + 10'd120: phinc = { 12'd1447 }; // nota = 1, KF = 56 + 10'd121: phinc = { 12'd1448 }; // nota = 1, KF = 57 + 10'd122: phinc = { 12'd1449 }; // nota = 1, KF = 58 + 10'd123: phinc = { 12'd1450 }; // nota = 1, KF = 59 + 10'd124: phinc = { 12'd1452 }; // nota = 1, KF = 60 + 10'd125: phinc = { 12'd1453 }; // nota = 1, KF = 61 + 10'd126: phinc = { 12'd1454 }; // nota = 1, KF = 62 + 10'd127: phinc = { 12'd1455 }; // nota = 1, KF = 63 + 10'd128: phinc = { 12'd1458 }; // nota = 2, KF = 0 + 10'd129: phinc = { 12'd1459 }; // nota = 2, KF = 1 + 10'd130: phinc = { 12'd1460 }; // nota = 2, KF = 2 + 10'd131: phinc = { 12'd1461 }; // nota = 2, KF = 3 + 10'd132: phinc = { 12'd1463 }; // nota = 2, KF = 4 + 10'd133: phinc = { 12'd1464 }; // nota = 2, KF = 5 + 10'd134: phinc = { 12'd1465 }; // nota = 2, KF = 6 + 10'd135: phinc = { 12'd1466 }; // nota = 2, KF = 7 + 10'd136: phinc = { 12'd1468 }; // nota = 2, KF = 8 + 10'd137: phinc = { 12'd1469 }; // nota = 2, KF = 9 + 10'd138: phinc = { 12'd1471 }; // nota = 2, KF = 10 + 10'd139: phinc = { 12'd1472 }; // nota = 2, KF = 11 + 10'd140: phinc = { 12'd1473 }; // nota = 2, KF = 12 + 10'd141: phinc = { 12'd1474 }; // nota = 2, KF = 13 + 10'd142: phinc = { 12'd1476 }; // nota = 2, KF = 14 + 10'd143: phinc = { 12'd1477 }; // nota = 2, KF = 15 + 10'd144: phinc = { 12'd1479 }; // nota = 2, KF = 16 + 10'd145: phinc = { 12'd1480 }; // nota = 2, KF = 17 + 10'd146: phinc = { 12'd1481 }; // nota = 2, KF = 18 + 10'd147: phinc = { 12'd1482 }; // nota = 2, KF = 19 + 10'd148: phinc = { 12'd1484 }; // nota = 2, KF = 20 + 10'd149: phinc = { 12'd1485 }; // nota = 2, KF = 21 + 10'd150: phinc = { 12'd1486 }; // nota = 2, KF = 22 + 10'd151: phinc = { 12'd1487 }; // nota = 2, KF = 23 + 10'd152: phinc = { 12'd1489 }; // nota = 2, KF = 24 + 10'd153: phinc = { 12'd1490 }; // nota = 2, KF = 25 + 10'd154: phinc = { 12'd1492 }; // nota = 2, KF = 26 + 10'd155: phinc = { 12'd1493 }; // nota = 2, KF = 27 + 10'd156: phinc = { 12'd1494 }; // nota = 2, KF = 28 + 10'd157: phinc = { 12'd1495 }; // nota = 2, KF = 29 + 10'd158: phinc = { 12'd1497 }; // nota = 2, KF = 30 + 10'd159: phinc = { 12'd1498 }; // nota = 2, KF = 31 + 10'd160: phinc = { 12'd1501 }; // nota = 2, KF = 32 + 10'd161: phinc = { 12'd1502 }; // nota = 2, KF = 33 + 10'd162: phinc = { 12'd1503 }; // nota = 2, KF = 34 + 10'd163: phinc = { 12'd1504 }; // nota = 2, KF = 35 + 10'd164: phinc = { 12'd1506 }; // nota = 2, KF = 36 + 10'd165: phinc = { 12'd1507 }; // nota = 2, KF = 37 + 10'd166: phinc = { 12'd1509 }; // nota = 2, KF = 38 + 10'd167: phinc = { 12'd1510 }; // nota = 2, KF = 39 + 10'd168: phinc = { 12'd1512 }; // nota = 2, KF = 40 + 10'd169: phinc = { 12'd1513 }; // nota = 2, KF = 41 + 10'd170: phinc = { 12'd1514 }; // nota = 2, KF = 42 + 10'd171: phinc = { 12'd1515 }; // nota = 2, KF = 43 + 10'd172: phinc = { 12'd1517 }; // nota = 2, KF = 44 + 10'd173: phinc = { 12'd1518 }; // nota = 2, KF = 45 + 10'd174: phinc = { 12'd1520 }; // nota = 2, KF = 46 + 10'd175: phinc = { 12'd1521 }; // nota = 2, KF = 47 + 10'd176: phinc = { 12'd1523 }; // nota = 2, KF = 48 + 10'd177: phinc = { 12'd1524 }; // nota = 2, KF = 49 + 10'd178: phinc = { 12'd1525 }; // nota = 2, KF = 50 + 10'd179: phinc = { 12'd1526 }; // nota = 2, KF = 51 + 10'd180: phinc = { 12'd1528 }; // nota = 2, KF = 52 + 10'd181: phinc = { 12'd1529 }; // nota = 2, KF = 53 + 10'd182: phinc = { 12'd1531 }; // nota = 2, KF = 54 + 10'd183: phinc = { 12'd1532 }; // nota = 2, KF = 55 + 10'd184: phinc = { 12'd1534 }; // nota = 2, KF = 56 + 10'd185: phinc = { 12'd1535 }; // nota = 2, KF = 57 + 10'd186: phinc = { 12'd1536 }; // nota = 2, KF = 58 + 10'd187: phinc = { 12'd1537 }; // nota = 2, KF = 59 + 10'd188: phinc = { 12'd1539 }; // nota = 2, KF = 60 + 10'd189: phinc = { 12'd1540 }; // nota = 2, KF = 61 + 10'd190: phinc = { 12'd1542 }; // nota = 2, KF = 62 + 10'd191: phinc = { 12'd1543 }; // nota = 2, KF = 63 + 10'd192: phinc = { 12'd1458 }; // nota = 3, KF = 0 + 10'd193: phinc = { 12'd1459 }; // nota = 3, KF = 1 + 10'd194: phinc = { 12'd1460 }; // nota = 3, KF = 2 + 10'd195: phinc = { 12'd1461 }; // nota = 3, KF = 3 + 10'd196: phinc = { 12'd1463 }; // nota = 3, KF = 4 + 10'd197: phinc = { 12'd1464 }; // nota = 3, KF = 5 + 10'd198: phinc = { 12'd1465 }; // nota = 3, KF = 6 + 10'd199: phinc = { 12'd1466 }; // nota = 3, KF = 7 + 10'd200: phinc = { 12'd1468 }; // nota = 3, KF = 8 + 10'd201: phinc = { 12'd1469 }; // nota = 3, KF = 9 + 10'd202: phinc = { 12'd1471 }; // nota = 3, KF = 10 + 10'd203: phinc = { 12'd1472 }; // nota = 3, KF = 11 + 10'd204: phinc = { 12'd1473 }; // nota = 3, KF = 12 + 10'd205: phinc = { 12'd1474 }; // nota = 3, KF = 13 + 10'd206: phinc = { 12'd1476 }; // nota = 3, KF = 14 + 10'd207: phinc = { 12'd1477 }; // nota = 3, KF = 15 + 10'd208: phinc = { 12'd1479 }; // nota = 3, KF = 16 + 10'd209: phinc = { 12'd1480 }; // nota = 3, KF = 17 + 10'd210: phinc = { 12'd1481 }; // nota = 3, KF = 18 + 10'd211: phinc = { 12'd1482 }; // nota = 3, KF = 19 + 10'd212: phinc = { 12'd1484 }; // nota = 3, KF = 20 + 10'd213: phinc = { 12'd1485 }; // nota = 3, KF = 21 + 10'd214: phinc = { 12'd1486 }; // nota = 3, KF = 22 + 10'd215: phinc = { 12'd1487 }; // nota = 3, KF = 23 + 10'd216: phinc = { 12'd1489 }; // nota = 3, KF = 24 + 10'd217: phinc = { 12'd1490 }; // nota = 3, KF = 25 + 10'd218: phinc = { 12'd1492 }; // nota = 3, KF = 26 + 10'd219: phinc = { 12'd1493 }; // nota = 3, KF = 27 + 10'd220: phinc = { 12'd1494 }; // nota = 3, KF = 28 + 10'd221: phinc = { 12'd1495 }; // nota = 3, KF = 29 + 10'd222: phinc = { 12'd1497 }; // nota = 3, KF = 30 + 10'd223: phinc = { 12'd1498 }; // nota = 3, KF = 31 + 10'd224: phinc = { 12'd1501 }; // nota = 3, KF = 32 + 10'd225: phinc = { 12'd1502 }; // nota = 3, KF = 33 + 10'd226: phinc = { 12'd1503 }; // nota = 3, KF = 34 + 10'd227: phinc = { 12'd1504 }; // nota = 3, KF = 35 + 10'd228: phinc = { 12'd1506 }; // nota = 3, KF = 36 + 10'd229: phinc = { 12'd1507 }; // nota = 3, KF = 37 + 10'd230: phinc = { 12'd1509 }; // nota = 3, KF = 38 + 10'd231: phinc = { 12'd1510 }; // nota = 3, KF = 39 + 10'd232: phinc = { 12'd1512 }; // nota = 3, KF = 40 + 10'd233: phinc = { 12'd1513 }; // nota = 3, KF = 41 + 10'd234: phinc = { 12'd1514 }; // nota = 3, KF = 42 + 10'd235: phinc = { 12'd1515 }; // nota = 3, KF = 43 + 10'd236: phinc = { 12'd1517 }; // nota = 3, KF = 44 + 10'd237: phinc = { 12'd1518 }; // nota = 3, KF = 45 + 10'd238: phinc = { 12'd1520 }; // nota = 3, KF = 46 + 10'd239: phinc = { 12'd1521 }; // nota = 3, KF = 47 + 10'd240: phinc = { 12'd1523 }; // nota = 3, KF = 48 + 10'd241: phinc = { 12'd1524 }; // nota = 3, KF = 49 + 10'd242: phinc = { 12'd1525 }; // nota = 3, KF = 50 + 10'd243: phinc = { 12'd1526 }; // nota = 3, KF = 51 + 10'd244: phinc = { 12'd1528 }; // nota = 3, KF = 52 + 10'd245: phinc = { 12'd1529 }; // nota = 3, KF = 53 + 10'd246: phinc = { 12'd1531 }; // nota = 3, KF = 54 + 10'd247: phinc = { 12'd1532 }; // nota = 3, KF = 55 + 10'd248: phinc = { 12'd1534 }; // nota = 3, KF = 56 + 10'd249: phinc = { 12'd1535 }; // nota = 3, KF = 57 + 10'd250: phinc = { 12'd1536 }; // nota = 3, KF = 58 + 10'd251: phinc = { 12'd1537 }; // nota = 3, KF = 59 + 10'd252: phinc = { 12'd1539 }; // nota = 3, KF = 60 + 10'd253: phinc = { 12'd1540 }; // nota = 3, KF = 61 + 10'd254: phinc = { 12'd1542 }; // nota = 3, KF = 62 + 10'd255: phinc = { 12'd1543 }; // nota = 3, KF = 63 + 10'd256: phinc = { 12'd1545 }; // nota = 4, KF = 0 + 10'd257: phinc = { 12'd1546 }; // nota = 4, KF = 1 + 10'd258: phinc = { 12'd1547 }; // nota = 4, KF = 2 + 10'd259: phinc = { 12'd1548 }; // nota = 4, KF = 3 + 10'd260: phinc = { 12'd1550 }; // nota = 4, KF = 4 + 10'd261: phinc = { 12'd1551 }; // nota = 4, KF = 5 + 10'd262: phinc = { 12'd1553 }; // nota = 4, KF = 6 + 10'd263: phinc = { 12'd1554 }; // nota = 4, KF = 7 + 10'd264: phinc = { 12'd1556 }; // nota = 4, KF = 8 + 10'd265: phinc = { 12'd1557 }; // nota = 4, KF = 9 + 10'd266: phinc = { 12'd1558 }; // nota = 4, KF = 10 + 10'd267: phinc = { 12'd1559 }; // nota = 4, KF = 11 + 10'd268: phinc = { 12'd1561 }; // nota = 4, KF = 12 + 10'd269: phinc = { 12'd1562 }; // nota = 4, KF = 13 + 10'd270: phinc = { 12'd1564 }; // nota = 4, KF = 14 + 10'd271: phinc = { 12'd1565 }; // nota = 4, KF = 15 + 10'd272: phinc = { 12'd1567 }; // nota = 4, KF = 16 + 10'd273: phinc = { 12'd1568 }; // nota = 4, KF = 17 + 10'd274: phinc = { 12'd1569 }; // nota = 4, KF = 18 + 10'd275: phinc = { 12'd1570 }; // nota = 4, KF = 19 + 10'd276: phinc = { 12'd1572 }; // nota = 4, KF = 20 + 10'd277: phinc = { 12'd1573 }; // nota = 4, KF = 21 + 10'd278: phinc = { 12'd1575 }; // nota = 4, KF = 22 + 10'd279: phinc = { 12'd1576 }; // nota = 4, KF = 23 + 10'd280: phinc = { 12'd1578 }; // nota = 4, KF = 24 + 10'd281: phinc = { 12'd1579 }; // nota = 4, KF = 25 + 10'd282: phinc = { 12'd1580 }; // nota = 4, KF = 26 + 10'd283: phinc = { 12'd1581 }; // nota = 4, KF = 27 + 10'd284: phinc = { 12'd1583 }; // nota = 4, KF = 28 + 10'd285: phinc = { 12'd1584 }; // nota = 4, KF = 29 + 10'd286: phinc = { 12'd1586 }; // nota = 4, KF = 30 + 10'd287: phinc = { 12'd1587 }; // nota = 4, KF = 31 + 10'd288: phinc = { 12'd1590 }; // nota = 4, KF = 32 + 10'd289: phinc = { 12'd1591 }; // nota = 4, KF = 33 + 10'd290: phinc = { 12'd1592 }; // nota = 4, KF = 34 + 10'd291: phinc = { 12'd1593 }; // nota = 4, KF = 35 + 10'd292: phinc = { 12'd1595 }; // nota = 4, KF = 36 + 10'd293: phinc = { 12'd1596 }; // nota = 4, KF = 37 + 10'd294: phinc = { 12'd1598 }; // nota = 4, KF = 38 + 10'd295: phinc = { 12'd1599 }; // nota = 4, KF = 39 + 10'd296: phinc = { 12'd1601 }; // nota = 4, KF = 40 + 10'd297: phinc = { 12'd1602 }; // nota = 4, KF = 41 + 10'd298: phinc = { 12'd1604 }; // nota = 4, KF = 42 + 10'd299: phinc = { 12'd1605 }; // nota = 4, KF = 43 + 10'd300: phinc = { 12'd1607 }; // nota = 4, KF = 44 + 10'd301: phinc = { 12'd1608 }; // nota = 4, KF = 45 + 10'd302: phinc = { 12'd1609 }; // nota = 4, KF = 46 + 10'd303: phinc = { 12'd1610 }; // nota = 4, KF = 47 + 10'd304: phinc = { 12'd1613 }; // nota = 4, KF = 48 + 10'd305: phinc = { 12'd1614 }; // nota = 4, KF = 49 + 10'd306: phinc = { 12'd1615 }; // nota = 4, KF = 50 + 10'd307: phinc = { 12'd1616 }; // nota = 4, KF = 51 + 10'd308: phinc = { 12'd1618 }; // nota = 4, KF = 52 + 10'd309: phinc = { 12'd1619 }; // nota = 4, KF = 53 + 10'd310: phinc = { 12'd1621 }; // nota = 4, KF = 54 + 10'd311: phinc = { 12'd1622 }; // nota = 4, KF = 55 + 10'd312: phinc = { 12'd1624 }; // nota = 4, KF = 56 + 10'd313: phinc = { 12'd1625 }; // nota = 4, KF = 57 + 10'd314: phinc = { 12'd1627 }; // nota = 4, KF = 58 + 10'd315: phinc = { 12'd1628 }; // nota = 4, KF = 59 + 10'd316: phinc = { 12'd1630 }; // nota = 4, KF = 60 + 10'd317: phinc = { 12'd1631 }; // nota = 4, KF = 61 + 10'd318: phinc = { 12'd1632 }; // nota = 4, KF = 62 + 10'd319: phinc = { 12'd1633 }; // nota = 4, KF = 63 + 10'd320: phinc = { 12'd1637 }; // nota = 5, KF = 0 + 10'd321: phinc = { 12'd1638 }; // nota = 5, KF = 1 + 10'd322: phinc = { 12'd1639 }; // nota = 5, KF = 2 + 10'd323: phinc = { 12'd1640 }; // nota = 5, KF = 3 + 10'd324: phinc = { 12'd1642 }; // nota = 5, KF = 4 + 10'd325: phinc = { 12'd1643 }; // nota = 5, KF = 5 + 10'd326: phinc = { 12'd1645 }; // nota = 5, KF = 6 + 10'd327: phinc = { 12'd1646 }; // nota = 5, KF = 7 + 10'd328: phinc = { 12'd1648 }; // nota = 5, KF = 8 + 10'd329: phinc = { 12'd1649 }; // nota = 5, KF = 9 + 10'd330: phinc = { 12'd1651 }; // nota = 5, KF = 10 + 10'd331: phinc = { 12'd1652 }; // nota = 5, KF = 11 + 10'd332: phinc = { 12'd1654 }; // nota = 5, KF = 12 + 10'd333: phinc = { 12'd1655 }; // nota = 5, KF = 13 + 10'd334: phinc = { 12'd1656 }; // nota = 5, KF = 14 + 10'd335: phinc = { 12'd1657 }; // nota = 5, KF = 15 + 10'd336: phinc = { 12'd1660 }; // nota = 5, KF = 16 + 10'd337: phinc = { 12'd1661 }; // nota = 5, KF = 17 + 10'd338: phinc = { 12'd1663 }; // nota = 5, KF = 18 + 10'd339: phinc = { 12'd1664 }; // nota = 5, KF = 19 + 10'd340: phinc = { 12'd1666 }; // nota = 5, KF = 20 + 10'd341: phinc = { 12'd1667 }; // nota = 5, KF = 21 + 10'd342: phinc = { 12'd1669 }; // nota = 5, KF = 22 + 10'd343: phinc = { 12'd1670 }; // nota = 5, KF = 23 + 10'd344: phinc = { 12'd1672 }; // nota = 5, KF = 24 + 10'd345: phinc = { 12'd1673 }; // nota = 5, KF = 25 + 10'd346: phinc = { 12'd1675 }; // nota = 5, KF = 26 + 10'd347: phinc = { 12'd1676 }; // nota = 5, KF = 27 + 10'd348: phinc = { 12'd1678 }; // nota = 5, KF = 28 + 10'd349: phinc = { 12'd1679 }; // nota = 5, KF = 29 + 10'd350: phinc = { 12'd1681 }; // nota = 5, KF = 30 + 10'd351: phinc = { 12'd1682 }; // nota = 5, KF = 31 + 10'd352: phinc = { 12'd1685 }; // nota = 5, KF = 32 + 10'd353: phinc = { 12'd1686 }; // nota = 5, KF = 33 + 10'd354: phinc = { 12'd1688 }; // nota = 5, KF = 34 + 10'd355: phinc = { 12'd1689 }; // nota = 5, KF = 35 + 10'd356: phinc = { 12'd1691 }; // nota = 5, KF = 36 + 10'd357: phinc = { 12'd1692 }; // nota = 5, KF = 37 + 10'd358: phinc = { 12'd1694 }; // nota = 5, KF = 38 + 10'd359: phinc = { 12'd1695 }; // nota = 5, KF = 39 + 10'd360: phinc = { 12'd1697 }; // nota = 5, KF = 40 + 10'd361: phinc = { 12'd1698 }; // nota = 5, KF = 41 + 10'd362: phinc = { 12'd1700 }; // nota = 5, KF = 42 + 10'd363: phinc = { 12'd1701 }; // nota = 5, KF = 43 + 10'd364: phinc = { 12'd1703 }; // nota = 5, KF = 44 + 10'd365: phinc = { 12'd1704 }; // nota = 5, KF = 45 + 10'd366: phinc = { 12'd1706 }; // nota = 5, KF = 46 + 10'd367: phinc = { 12'd1707 }; // nota = 5, KF = 47 + 10'd368: phinc = { 12'd1709 }; // nota = 5, KF = 48 + 10'd369: phinc = { 12'd1710 }; // nota = 5, KF = 49 + 10'd370: phinc = { 12'd1712 }; // nota = 5, KF = 50 + 10'd371: phinc = { 12'd1713 }; // nota = 5, KF = 51 + 10'd372: phinc = { 12'd1715 }; // nota = 5, KF = 52 + 10'd373: phinc = { 12'd1716 }; // nota = 5, KF = 53 + 10'd374: phinc = { 12'd1718 }; // nota = 5, KF = 54 + 10'd375: phinc = { 12'd1719 }; // nota = 5, KF = 55 + 10'd376: phinc = { 12'd1721 }; // nota = 5, KF = 56 + 10'd377: phinc = { 12'd1722 }; // nota = 5, KF = 57 + 10'd378: phinc = { 12'd1724 }; // nota = 5, KF = 58 + 10'd379: phinc = { 12'd1725 }; // nota = 5, KF = 59 + 10'd380: phinc = { 12'd1727 }; // nota = 5, KF = 60 + 10'd381: phinc = { 12'd1728 }; // nota = 5, KF = 61 + 10'd382: phinc = { 12'd1730 }; // nota = 5, KF = 62 + 10'd383: phinc = { 12'd1731 }; // nota = 5, KF = 63 + 10'd384: phinc = { 12'd1734 }; // nota = 6, KF = 0 + 10'd385: phinc = { 12'd1735 }; // nota = 6, KF = 1 + 10'd386: phinc = { 12'd1737 }; // nota = 6, KF = 2 + 10'd387: phinc = { 12'd1738 }; // nota = 6, KF = 3 + 10'd388: phinc = { 12'd1740 }; // nota = 6, KF = 4 + 10'd389: phinc = { 12'd1741 }; // nota = 6, KF = 5 + 10'd390: phinc = { 12'd1743 }; // nota = 6, KF = 6 + 10'd391: phinc = { 12'd1744 }; // nota = 6, KF = 7 + 10'd392: phinc = { 12'd1746 }; // nota = 6, KF = 8 + 10'd393: phinc = { 12'd1748 }; // nota = 6, KF = 9 + 10'd394: phinc = { 12'd1749 }; // nota = 6, KF = 10 + 10'd395: phinc = { 12'd1751 }; // nota = 6, KF = 11 + 10'd396: phinc = { 12'd1752 }; // nota = 6, KF = 12 + 10'd397: phinc = { 12'd1754 }; // nota = 6, KF = 13 + 10'd398: phinc = { 12'd1755 }; // nota = 6, KF = 14 + 10'd399: phinc = { 12'd1757 }; // nota = 6, KF = 15 + 10'd400: phinc = { 12'd1759 }; // nota = 6, KF = 16 + 10'd401: phinc = { 12'd1760 }; // nota = 6, KF = 17 + 10'd402: phinc = { 12'd1762 }; // nota = 6, KF = 18 + 10'd403: phinc = { 12'd1763 }; // nota = 6, KF = 19 + 10'd404: phinc = { 12'd1765 }; // nota = 6, KF = 20 + 10'd405: phinc = { 12'd1766 }; // nota = 6, KF = 21 + 10'd406: phinc = { 12'd1768 }; // nota = 6, KF = 22 + 10'd407: phinc = { 12'd1769 }; // nota = 6, KF = 23 + 10'd408: phinc = { 12'd1771 }; // nota = 6, KF = 24 + 10'd409: phinc = { 12'd1773 }; // nota = 6, KF = 25 + 10'd410: phinc = { 12'd1774 }; // nota = 6, KF = 26 + 10'd411: phinc = { 12'd1776 }; // nota = 6, KF = 27 + 10'd412: phinc = { 12'd1777 }; // nota = 6, KF = 28 + 10'd413: phinc = { 12'd1779 }; // nota = 6, KF = 29 + 10'd414: phinc = { 12'd1780 }; // nota = 6, KF = 30 + 10'd415: phinc = { 12'd1782 }; // nota = 6, KF = 31 + 10'd416: phinc = { 12'd1785 }; // nota = 6, KF = 32 + 10'd417: phinc = { 12'd1786 }; // nota = 6, KF = 33 + 10'd418: phinc = { 12'd1788 }; // nota = 6, KF = 34 + 10'd419: phinc = { 12'd1789 }; // nota = 6, KF = 35 + 10'd420: phinc = { 12'd1791 }; // nota = 6, KF = 36 + 10'd421: phinc = { 12'd1793 }; // nota = 6, KF = 37 + 10'd422: phinc = { 12'd1794 }; // nota = 6, KF = 38 + 10'd423: phinc = { 12'd1796 }; // nota = 6, KF = 39 + 10'd424: phinc = { 12'd1798 }; // nota = 6, KF = 40 + 10'd425: phinc = { 12'd1799 }; // nota = 6, KF = 41 + 10'd426: phinc = { 12'd1801 }; // nota = 6, KF = 42 + 10'd427: phinc = { 12'd1802 }; // nota = 6, KF = 43 + 10'd428: phinc = { 12'd1804 }; // nota = 6, KF = 44 + 10'd429: phinc = { 12'd1806 }; // nota = 6, KF = 45 + 10'd430: phinc = { 12'd1807 }; // nota = 6, KF = 46 + 10'd431: phinc = { 12'd1809 }; // nota = 6, KF = 47 + 10'd432: phinc = { 12'd1811 }; // nota = 6, KF = 48 + 10'd433: phinc = { 12'd1812 }; // nota = 6, KF = 49 + 10'd434: phinc = { 12'd1814 }; // nota = 6, KF = 50 + 10'd435: phinc = { 12'd1815 }; // nota = 6, KF = 51 + 10'd436: phinc = { 12'd1817 }; // nota = 6, KF = 52 + 10'd437: phinc = { 12'd1819 }; // nota = 6, KF = 53 + 10'd438: phinc = { 12'd1820 }; // nota = 6, KF = 54 + 10'd439: phinc = { 12'd1822 }; // nota = 6, KF = 55 + 10'd440: phinc = { 12'd1824 }; // nota = 6, KF = 56 + 10'd441: phinc = { 12'd1825 }; // nota = 6, KF = 57 + 10'd442: phinc = { 12'd1827 }; // nota = 6, KF = 58 + 10'd443: phinc = { 12'd1828 }; // nota = 6, KF = 59 + 10'd444: phinc = { 12'd1830 }; // nota = 6, KF = 60 + 10'd445: phinc = { 12'd1832 }; // nota = 6, KF = 61 + 10'd446: phinc = { 12'd1833 }; // nota = 6, KF = 62 + 10'd447: phinc = { 12'd1835 }; // nota = 6, KF = 63 + 10'd448: phinc = { 12'd1734 }; // nota = 7, KF = 0 + 10'd449: phinc = { 12'd1735 }; // nota = 7, KF = 1 + 10'd450: phinc = { 12'd1737 }; // nota = 7, KF = 2 + 10'd451: phinc = { 12'd1738 }; // nota = 7, KF = 3 + 10'd452: phinc = { 12'd1740 }; // nota = 7, KF = 4 + 10'd453: phinc = { 12'd1741 }; // nota = 7, KF = 5 + 10'd454: phinc = { 12'd1743 }; // nota = 7, KF = 6 + 10'd455: phinc = { 12'd1744 }; // nota = 7, KF = 7 + 10'd456: phinc = { 12'd1746 }; // nota = 7, KF = 8 + 10'd457: phinc = { 12'd1748 }; // nota = 7, KF = 9 + 10'd458: phinc = { 12'd1749 }; // nota = 7, KF = 10 + 10'd459: phinc = { 12'd1751 }; // nota = 7, KF = 11 + 10'd460: phinc = { 12'd1752 }; // nota = 7, KF = 12 + 10'd461: phinc = { 12'd1754 }; // nota = 7, KF = 13 + 10'd462: phinc = { 12'd1755 }; // nota = 7, KF = 14 + 10'd463: phinc = { 12'd1757 }; // nota = 7, KF = 15 + 10'd464: phinc = { 12'd1759 }; // nota = 7, KF = 16 + 10'd465: phinc = { 12'd1760 }; // nota = 7, KF = 17 + 10'd466: phinc = { 12'd1762 }; // nota = 7, KF = 18 + 10'd467: phinc = { 12'd1763 }; // nota = 7, KF = 19 + 10'd468: phinc = { 12'd1765 }; // nota = 7, KF = 20 + 10'd469: phinc = { 12'd1766 }; // nota = 7, KF = 21 + 10'd470: phinc = { 12'd1768 }; // nota = 7, KF = 22 + 10'd471: phinc = { 12'd1769 }; // nota = 7, KF = 23 + 10'd472: phinc = { 12'd1771 }; // nota = 7, KF = 24 + 10'd473: phinc = { 12'd1773 }; // nota = 7, KF = 25 + 10'd474: phinc = { 12'd1774 }; // nota = 7, KF = 26 + 10'd475: phinc = { 12'd1776 }; // nota = 7, KF = 27 + 10'd476: phinc = { 12'd1777 }; // nota = 7, KF = 28 + 10'd477: phinc = { 12'd1779 }; // nota = 7, KF = 29 + 10'd478: phinc = { 12'd1780 }; // nota = 7, KF = 30 + 10'd479: phinc = { 12'd1782 }; // nota = 7, KF = 31 + 10'd480: phinc = { 12'd1785 }; // nota = 7, KF = 32 + 10'd481: phinc = { 12'd1786 }; // nota = 7, KF = 33 + 10'd482: phinc = { 12'd1788 }; // nota = 7, KF = 34 + 10'd483: phinc = { 12'd1789 }; // nota = 7, KF = 35 + 10'd484: phinc = { 12'd1791 }; // nota = 7, KF = 36 + 10'd485: phinc = { 12'd1793 }; // nota = 7, KF = 37 + 10'd486: phinc = { 12'd1794 }; // nota = 7, KF = 38 + 10'd487: phinc = { 12'd1796 }; // nota = 7, KF = 39 + 10'd488: phinc = { 12'd1798 }; // nota = 7, KF = 40 + 10'd489: phinc = { 12'd1799 }; // nota = 7, KF = 41 + 10'd490: phinc = { 12'd1801 }; // nota = 7, KF = 42 + 10'd491: phinc = { 12'd1802 }; // nota = 7, KF = 43 + 10'd492: phinc = { 12'd1804 }; // nota = 7, KF = 44 + 10'd493: phinc = { 12'd1806 }; // nota = 7, KF = 45 + 10'd494: phinc = { 12'd1807 }; // nota = 7, KF = 46 + 10'd495: phinc = { 12'd1809 }; // nota = 7, KF = 47 + 10'd496: phinc = { 12'd1811 }; // nota = 7, KF = 48 + 10'd497: phinc = { 12'd1812 }; // nota = 7, KF = 49 + 10'd498: phinc = { 12'd1814 }; // nota = 7, KF = 50 + 10'd499: phinc = { 12'd1815 }; // nota = 7, KF = 51 + 10'd500: phinc = { 12'd1817 }; // nota = 7, KF = 52 + 10'd501: phinc = { 12'd1819 }; // nota = 7, KF = 53 + 10'd502: phinc = { 12'd1820 }; // nota = 7, KF = 54 + 10'd503: phinc = { 12'd1822 }; // nota = 7, KF = 55 + 10'd504: phinc = { 12'd1824 }; // nota = 7, KF = 56 + 10'd505: phinc = { 12'd1825 }; // nota = 7, KF = 57 + 10'd506: phinc = { 12'd1827 }; // nota = 7, KF = 58 + 10'd507: phinc = { 12'd1828 }; // nota = 7, KF = 59 + 10'd508: phinc = { 12'd1830 }; // nota = 7, KF = 60 + 10'd509: phinc = { 12'd1832 }; // nota = 7, KF = 61 + 10'd510: phinc = { 12'd1833 }; // nota = 7, KF = 62 + 10'd511: phinc = { 12'd1835 }; // nota = 7, KF = 63 + 10'd512: phinc = { 12'd1837 }; // nota = 8, KF = 0 + 10'd513: phinc = { 12'd1838 }; // nota = 8, KF = 1 + 10'd514: phinc = { 12'd1840 }; // nota = 8, KF = 2 + 10'd515: phinc = { 12'd1841 }; // nota = 8, KF = 3 + 10'd516: phinc = { 12'd1843 }; // nota = 8, KF = 4 + 10'd517: phinc = { 12'd1845 }; // nota = 8, KF = 5 + 10'd518: phinc = { 12'd1846 }; // nota = 8, KF = 6 + 10'd519: phinc = { 12'd1848 }; // nota = 8, KF = 7 + 10'd520: phinc = { 12'd1850 }; // nota = 8, KF = 8 + 10'd521: phinc = { 12'd1851 }; // nota = 8, KF = 9 + 10'd522: phinc = { 12'd1853 }; // nota = 8, KF = 10 + 10'd523: phinc = { 12'd1854 }; // nota = 8, KF = 11 + 10'd524: phinc = { 12'd1856 }; // nota = 8, KF = 12 + 10'd525: phinc = { 12'd1858 }; // nota = 8, KF = 13 + 10'd526: phinc = { 12'd1859 }; // nota = 8, KF = 14 + 10'd527: phinc = { 12'd1861 }; // nota = 8, KF = 15 + 10'd528: phinc = { 12'd1864 }; // nota = 8, KF = 16 + 10'd529: phinc = { 12'd1865 }; // nota = 8, KF = 17 + 10'd530: phinc = { 12'd1867 }; // nota = 8, KF = 18 + 10'd531: phinc = { 12'd1868 }; // nota = 8, KF = 19 + 10'd532: phinc = { 12'd1870 }; // nota = 8, KF = 20 + 10'd533: phinc = { 12'd1872 }; // nota = 8, KF = 21 + 10'd534: phinc = { 12'd1873 }; // nota = 8, KF = 22 + 10'd535: phinc = { 12'd1875 }; // nota = 8, KF = 23 + 10'd536: phinc = { 12'd1877 }; // nota = 8, KF = 24 + 10'd537: phinc = { 12'd1879 }; // nota = 8, KF = 25 + 10'd538: phinc = { 12'd1880 }; // nota = 8, KF = 26 + 10'd539: phinc = { 12'd1882 }; // nota = 8, KF = 27 + 10'd540: phinc = { 12'd1884 }; // nota = 8, KF = 28 + 10'd541: phinc = { 12'd1885 }; // nota = 8, KF = 29 + 10'd542: phinc = { 12'd1887 }; // nota = 8, KF = 30 + 10'd543: phinc = { 12'd1888 }; // nota = 8, KF = 31 + 10'd544: phinc = { 12'd1891 }; // nota = 8, KF = 32 + 10'd545: phinc = { 12'd1892 }; // nota = 8, KF = 33 + 10'd546: phinc = { 12'd1894 }; // nota = 8, KF = 34 + 10'd547: phinc = { 12'd1895 }; // nota = 8, KF = 35 + 10'd548: phinc = { 12'd1897 }; // nota = 8, KF = 36 + 10'd549: phinc = { 12'd1899 }; // nota = 8, KF = 37 + 10'd550: phinc = { 12'd1900 }; // nota = 8, KF = 38 + 10'd551: phinc = { 12'd1902 }; // nota = 8, KF = 39 + 10'd552: phinc = { 12'd1904 }; // nota = 8, KF = 40 + 10'd553: phinc = { 12'd1906 }; // nota = 8, KF = 41 + 10'd554: phinc = { 12'd1907 }; // nota = 8, KF = 42 + 10'd555: phinc = { 12'd1909 }; // nota = 8, KF = 43 + 10'd556: phinc = { 12'd1911 }; // nota = 8, KF = 44 + 10'd557: phinc = { 12'd1912 }; // nota = 8, KF = 45 + 10'd558: phinc = { 12'd1914 }; // nota = 8, KF = 46 + 10'd559: phinc = { 12'd1915 }; // nota = 8, KF = 47 + 10'd560: phinc = { 12'd1918 }; // nota = 8, KF = 48 + 10'd561: phinc = { 12'd1919 }; // nota = 8, KF = 49 + 10'd562: phinc = { 12'd1921 }; // nota = 8, KF = 50 + 10'd563: phinc = { 12'd1923 }; // nota = 8, KF = 51 + 10'd564: phinc = { 12'd1925 }; // nota = 8, KF = 52 + 10'd565: phinc = { 12'd1926 }; // nota = 8, KF = 53 + 10'd566: phinc = { 12'd1928 }; // nota = 8, KF = 54 + 10'd567: phinc = { 12'd1930 }; // nota = 8, KF = 55 + 10'd568: phinc = { 12'd1932 }; // nota = 8, KF = 56 + 10'd569: phinc = { 12'd1933 }; // nota = 8, KF = 57 + 10'd570: phinc = { 12'd1935 }; // nota = 8, KF = 58 + 10'd571: phinc = { 12'd1937 }; // nota = 8, KF = 59 + 10'd572: phinc = { 12'd1939 }; // nota = 8, KF = 60 + 10'd573: phinc = { 12'd1940 }; // nota = 8, KF = 61 + 10'd574: phinc = { 12'd1942 }; // nota = 8, KF = 62 + 10'd575: phinc = { 12'd1944 }; // nota = 8, KF = 63 + 10'd576: phinc = { 12'd1946 }; // nota = 9, KF = 0 + 10'd577: phinc = { 12'd1947 }; // nota = 9, KF = 1 + 10'd578: phinc = { 12'd1949 }; // nota = 9, KF = 2 + 10'd579: phinc = { 12'd1951 }; // nota = 9, KF = 3 + 10'd580: phinc = { 12'd1953 }; // nota = 9, KF = 4 + 10'd581: phinc = { 12'd1954 }; // nota = 9, KF = 5 + 10'd582: phinc = { 12'd1956 }; // nota = 9, KF = 6 + 10'd583: phinc = { 12'd1958 }; // nota = 9, KF = 7 + 10'd584: phinc = { 12'd1960 }; // nota = 9, KF = 8 + 10'd585: phinc = { 12'd1961 }; // nota = 9, KF = 9 + 10'd586: phinc = { 12'd1963 }; // nota = 9, KF = 10 + 10'd587: phinc = { 12'd1965 }; // nota = 9, KF = 11 + 10'd588: phinc = { 12'd1967 }; // nota = 9, KF = 12 + 10'd589: phinc = { 12'd1968 }; // nota = 9, KF = 13 + 10'd590: phinc = { 12'd1970 }; // nota = 9, KF = 14 + 10'd591: phinc = { 12'd1972 }; // nota = 9, KF = 15 + 10'd592: phinc = { 12'd1975 }; // nota = 9, KF = 16 + 10'd593: phinc = { 12'd1976 }; // nota = 9, KF = 17 + 10'd594: phinc = { 12'd1978 }; // nota = 9, KF = 18 + 10'd595: phinc = { 12'd1980 }; // nota = 9, KF = 19 + 10'd596: phinc = { 12'd1982 }; // nota = 9, KF = 20 + 10'd597: phinc = { 12'd1983 }; // nota = 9, KF = 21 + 10'd598: phinc = { 12'd1985 }; // nota = 9, KF = 22 + 10'd599: phinc = { 12'd1987 }; // nota = 9, KF = 23 + 10'd600: phinc = { 12'd1989 }; // nota = 9, KF = 24 + 10'd601: phinc = { 12'd1990 }; // nota = 9, KF = 25 + 10'd602: phinc = { 12'd1992 }; // nota = 9, KF = 26 + 10'd603: phinc = { 12'd1994 }; // nota = 9, KF = 27 + 10'd604: phinc = { 12'd1996 }; // nota = 9, KF = 28 + 10'd605: phinc = { 12'd1997 }; // nota = 9, KF = 29 + 10'd606: phinc = { 12'd1999 }; // nota = 9, KF = 30 + 10'd607: phinc = { 12'd2001 }; // nota = 9, KF = 31 + 10'd608: phinc = { 12'd2003 }; // nota = 9, KF = 32 + 10'd609: phinc = { 12'd2004 }; // nota = 9, KF = 33 + 10'd610: phinc = { 12'd2006 }; // nota = 9, KF = 34 + 10'd611: phinc = { 12'd2008 }; // nota = 9, KF = 35 + 10'd612: phinc = { 12'd2010 }; // nota = 9, KF = 36 + 10'd613: phinc = { 12'd2011 }; // nota = 9, KF = 37 + 10'd614: phinc = { 12'd2013 }; // nota = 9, KF = 38 + 10'd615: phinc = { 12'd2015 }; // nota = 9, KF = 39 + 10'd616: phinc = { 12'd2017 }; // nota = 9, KF = 40 + 10'd617: phinc = { 12'd2019 }; // nota = 9, KF = 41 + 10'd618: phinc = { 12'd2021 }; // nota = 9, KF = 42 + 10'd619: phinc = { 12'd2022 }; // nota = 9, KF = 43 + 10'd620: phinc = { 12'd2024 }; // nota = 9, KF = 44 + 10'd621: phinc = { 12'd2026 }; // nota = 9, KF = 45 + 10'd622: phinc = { 12'd2028 }; // nota = 9, KF = 46 + 10'd623: phinc = { 12'd2029 }; // nota = 9, KF = 47 + 10'd624: phinc = { 12'd2032 }; // nota = 9, KF = 48 + 10'd625: phinc = { 12'd2033 }; // nota = 9, KF = 49 + 10'd626: phinc = { 12'd2035 }; // nota = 9, KF = 50 + 10'd627: phinc = { 12'd2037 }; // nota = 9, KF = 51 + 10'd628: phinc = { 12'd2039 }; // nota = 9, KF = 52 + 10'd629: phinc = { 12'd2041 }; // nota = 9, KF = 53 + 10'd630: phinc = { 12'd2043 }; // nota = 9, KF = 54 + 10'd631: phinc = { 12'd2044 }; // nota = 9, KF = 55 + 10'd632: phinc = { 12'd2047 }; // nota = 9, KF = 56 + 10'd633: phinc = { 12'd2048 }; // nota = 9, KF = 57 + 10'd634: phinc = { 12'd2050 }; // nota = 9, KF = 58 + 10'd635: phinc = { 12'd2052 }; // nota = 9, KF = 59 + 10'd636: phinc = { 12'd2054 }; // nota = 9, KF = 60 + 10'd637: phinc = { 12'd2056 }; // nota = 9, KF = 61 + 10'd638: phinc = { 12'd2058 }; // nota = 9, KF = 62 + 10'd639: phinc = { 12'd2059 }; // nota = 9, KF = 63 + 10'd640: phinc = { 12'd2062 }; // nota = 10, KF = 0 + 10'd641: phinc = { 12'd2063 }; // nota = 10, KF = 1 + 10'd642: phinc = { 12'd2065 }; // nota = 10, KF = 2 + 10'd643: phinc = { 12'd2067 }; // nota = 10, KF = 3 + 10'd644: phinc = { 12'd2069 }; // nota = 10, KF = 4 + 10'd645: phinc = { 12'd2071 }; // nota = 10, KF = 5 + 10'd646: phinc = { 12'd2073 }; // nota = 10, KF = 6 + 10'd647: phinc = { 12'd2074 }; // nota = 10, KF = 7 + 10'd648: phinc = { 12'd2077 }; // nota = 10, KF = 8 + 10'd649: phinc = { 12'd2078 }; // nota = 10, KF = 9 + 10'd650: phinc = { 12'd2080 }; // nota = 10, KF = 10 + 10'd651: phinc = { 12'd2082 }; // nota = 10, KF = 11 + 10'd652: phinc = { 12'd2084 }; // nota = 10, KF = 12 + 10'd653: phinc = { 12'd2086 }; // nota = 10, KF = 13 + 10'd654: phinc = { 12'd2088 }; // nota = 10, KF = 14 + 10'd655: phinc = { 12'd2089 }; // nota = 10, KF = 15 + 10'd656: phinc = { 12'd2092 }; // nota = 10, KF = 16 + 10'd657: phinc = { 12'd2093 }; // nota = 10, KF = 17 + 10'd658: phinc = { 12'd2095 }; // nota = 10, KF = 18 + 10'd659: phinc = { 12'd2097 }; // nota = 10, KF = 19 + 10'd660: phinc = { 12'd2099 }; // nota = 10, KF = 20 + 10'd661: phinc = { 12'd2101 }; // nota = 10, KF = 21 + 10'd662: phinc = { 12'd2103 }; // nota = 10, KF = 22 + 10'd663: phinc = { 12'd2104 }; // nota = 10, KF = 23 + 10'd664: phinc = { 12'd2107 }; // nota = 10, KF = 24 + 10'd665: phinc = { 12'd2108 }; // nota = 10, KF = 25 + 10'd666: phinc = { 12'd2110 }; // nota = 10, KF = 26 + 10'd667: phinc = { 12'd2112 }; // nota = 10, KF = 27 + 10'd668: phinc = { 12'd2114 }; // nota = 10, KF = 28 + 10'd669: phinc = { 12'd2116 }; // nota = 10, KF = 29 + 10'd670: phinc = { 12'd2118 }; // nota = 10, KF = 30 + 10'd671: phinc = { 12'd2119 }; // nota = 10, KF = 31 + 10'd672: phinc = { 12'd2122 }; // nota = 10, KF = 32 + 10'd673: phinc = { 12'd2123 }; // nota = 10, KF = 33 + 10'd674: phinc = { 12'd2125 }; // nota = 10, KF = 34 + 10'd675: phinc = { 12'd2127 }; // nota = 10, KF = 35 + 10'd676: phinc = { 12'd2129 }; // nota = 10, KF = 36 + 10'd677: phinc = { 12'd2131 }; // nota = 10, KF = 37 + 10'd678: phinc = { 12'd2133 }; // nota = 10, KF = 38 + 10'd679: phinc = { 12'd2134 }; // nota = 10, KF = 39 + 10'd680: phinc = { 12'd2137 }; // nota = 10, KF = 40 + 10'd681: phinc = { 12'd2139 }; // nota = 10, KF = 41 + 10'd682: phinc = { 12'd2141 }; // nota = 10, KF = 42 + 10'd683: phinc = { 12'd2142 }; // nota = 10, KF = 43 + 10'd684: phinc = { 12'd2145 }; // nota = 10, KF = 44 + 10'd685: phinc = { 12'd2146 }; // nota = 10, KF = 45 + 10'd686: phinc = { 12'd2148 }; // nota = 10, KF = 46 + 10'd687: phinc = { 12'd2150 }; // nota = 10, KF = 47 + 10'd688: phinc = { 12'd2153 }; // nota = 10, KF = 48 + 10'd689: phinc = { 12'd2154 }; // nota = 10, KF = 49 + 10'd690: phinc = { 12'd2156 }; // nota = 10, KF = 50 + 10'd691: phinc = { 12'd2158 }; // nota = 10, KF = 51 + 10'd692: phinc = { 12'd2160 }; // nota = 10, KF = 52 + 10'd693: phinc = { 12'd2162 }; // nota = 10, KF = 53 + 10'd694: phinc = { 12'd2164 }; // nota = 10, KF = 54 + 10'd695: phinc = { 12'd2165 }; // nota = 10, KF = 55 + 10'd696: phinc = { 12'd2168 }; // nota = 10, KF = 56 + 10'd697: phinc = { 12'd2170 }; // nota = 10, KF = 57 + 10'd698: phinc = { 12'd2172 }; // nota = 10, KF = 58 + 10'd699: phinc = { 12'd2173 }; // nota = 10, KF = 59 + 10'd700: phinc = { 12'd2176 }; // nota = 10, KF = 60 + 10'd701: phinc = { 12'd2177 }; // nota = 10, KF = 61 + 10'd702: phinc = { 12'd2179 }; // nota = 10, KF = 62 + 10'd703: phinc = { 12'd2181 }; // nota = 10, KF = 63 + 10'd704: phinc = { 12'd2062 }; // nota = 11, KF = 0 + 10'd705: phinc = { 12'd2063 }; // nota = 11, KF = 1 + 10'd706: phinc = { 12'd2065 }; // nota = 11, KF = 2 + 10'd707: phinc = { 12'd2067 }; // nota = 11, KF = 3 + 10'd708: phinc = { 12'd2069 }; // nota = 11, KF = 4 + 10'd709: phinc = { 12'd2071 }; // nota = 11, KF = 5 + 10'd710: phinc = { 12'd2073 }; // nota = 11, KF = 6 + 10'd711: phinc = { 12'd2074 }; // nota = 11, KF = 7 + 10'd712: phinc = { 12'd2077 }; // nota = 11, KF = 8 + 10'd713: phinc = { 12'd2078 }; // nota = 11, KF = 9 + 10'd714: phinc = { 12'd2080 }; // nota = 11, KF = 10 + 10'd715: phinc = { 12'd2082 }; // nota = 11, KF = 11 + 10'd716: phinc = { 12'd2084 }; // nota = 11, KF = 12 + 10'd717: phinc = { 12'd2086 }; // nota = 11, KF = 13 + 10'd718: phinc = { 12'd2088 }; // nota = 11, KF = 14 + 10'd719: phinc = { 12'd2089 }; // nota = 11, KF = 15 + 10'd720: phinc = { 12'd2092 }; // nota = 11, KF = 16 + 10'd721: phinc = { 12'd2093 }; // nota = 11, KF = 17 + 10'd722: phinc = { 12'd2095 }; // nota = 11, KF = 18 + 10'd723: phinc = { 12'd2097 }; // nota = 11, KF = 19 + 10'd724: phinc = { 12'd2099 }; // nota = 11, KF = 20 + 10'd725: phinc = { 12'd2101 }; // nota = 11, KF = 21 + 10'd726: phinc = { 12'd2103 }; // nota = 11, KF = 22 + 10'd727: phinc = { 12'd2104 }; // nota = 11, KF = 23 + 10'd728: phinc = { 12'd2107 }; // nota = 11, KF = 24 + 10'd729: phinc = { 12'd2108 }; // nota = 11, KF = 25 + 10'd730: phinc = { 12'd2110 }; // nota = 11, KF = 26 + 10'd731: phinc = { 12'd2112 }; // nota = 11, KF = 27 + 10'd732: phinc = { 12'd2114 }; // nota = 11, KF = 28 + 10'd733: phinc = { 12'd2116 }; // nota = 11, KF = 29 + 10'd734: phinc = { 12'd2118 }; // nota = 11, KF = 30 + 10'd735: phinc = { 12'd2119 }; // nota = 11, KF = 31 + 10'd736: phinc = { 12'd2122 }; // nota = 11, KF = 32 + 10'd737: phinc = { 12'd2123 }; // nota = 11, KF = 33 + 10'd738: phinc = { 12'd2125 }; // nota = 11, KF = 34 + 10'd739: phinc = { 12'd2127 }; // nota = 11, KF = 35 + 10'd740: phinc = { 12'd2129 }; // nota = 11, KF = 36 + 10'd741: phinc = { 12'd2131 }; // nota = 11, KF = 37 + 10'd742: phinc = { 12'd2133 }; // nota = 11, KF = 38 + 10'd743: phinc = { 12'd2134 }; // nota = 11, KF = 39 + 10'd744: phinc = { 12'd2137 }; // nota = 11, KF = 40 + 10'd745: phinc = { 12'd2139 }; // nota = 11, KF = 41 + 10'd746: phinc = { 12'd2141 }; // nota = 11, KF = 42 + 10'd747: phinc = { 12'd2142 }; // nota = 11, KF = 43 + 10'd748: phinc = { 12'd2145 }; // nota = 11, KF = 44 + 10'd749: phinc = { 12'd2146 }; // nota = 11, KF = 45 + 10'd750: phinc = { 12'd2148 }; // nota = 11, KF = 46 + 10'd751: phinc = { 12'd2150 }; // nota = 11, KF = 47 + 10'd752: phinc = { 12'd2153 }; // nota = 11, KF = 48 + 10'd753: phinc = { 12'd2154 }; // nota = 11, KF = 49 + 10'd754: phinc = { 12'd2156 }; // nota = 11, KF = 50 + 10'd755: phinc = { 12'd2158 }; // nota = 11, KF = 51 + 10'd756: phinc = { 12'd2160 }; // nota = 11, KF = 52 + 10'd757: phinc = { 12'd2162 }; // nota = 11, KF = 53 + 10'd758: phinc = { 12'd2164 }; // nota = 11, KF = 54 + 10'd759: phinc = { 12'd2165 }; // nota = 11, KF = 55 + 10'd760: phinc = { 12'd2168 }; // nota = 11, KF = 56 + 10'd761: phinc = { 12'd2170 }; // nota = 11, KF = 57 + 10'd762: phinc = { 12'd2172 }; // nota = 11, KF = 58 + 10'd763: phinc = { 12'd2173 }; // nota = 11, KF = 59 + 10'd764: phinc = { 12'd2176 }; // nota = 11, KF = 60 + 10'd765: phinc = { 12'd2177 }; // nota = 11, KF = 61 + 10'd766: phinc = { 12'd2179 }; // nota = 11, KF = 62 + 10'd767: phinc = { 12'd2181 }; // nota = 11, KF = 63 + 10'd768: phinc = { 12'd2185 }; // nota = 12, KF = 0 + 10'd769: phinc = { 12'd2186 }; // nota = 12, KF = 1 + 10'd770: phinc = { 12'd2188 }; // nota = 12, KF = 2 + 10'd771: phinc = { 12'd2190 }; // nota = 12, KF = 3 + 10'd772: phinc = { 12'd2192 }; // nota = 12, KF = 4 + 10'd773: phinc = { 12'd2194 }; // nota = 12, KF = 5 + 10'd774: phinc = { 12'd2196 }; // nota = 12, KF = 6 + 10'd775: phinc = { 12'd2197 }; // nota = 12, KF = 7 + 10'd776: phinc = { 12'd2200 }; // nota = 12, KF = 8 + 10'd777: phinc = { 12'd2202 }; // nota = 12, KF = 9 + 10'd778: phinc = { 12'd2204 }; // nota = 12, KF = 10 + 10'd779: phinc = { 12'd2205 }; // nota = 12, KF = 11 + 10'd780: phinc = { 12'd2208 }; // nota = 12, KF = 12 + 10'd781: phinc = { 12'd2209 }; // nota = 12, KF = 13 + 10'd782: phinc = { 12'd2211 }; // nota = 12, KF = 14 + 10'd783: phinc = { 12'd2213 }; // nota = 12, KF = 15 + 10'd784: phinc = { 12'd2216 }; // nota = 12, KF = 16 + 10'd785: phinc = { 12'd2218 }; // nota = 12, KF = 17 + 10'd786: phinc = { 12'd2220 }; // nota = 12, KF = 18 + 10'd787: phinc = { 12'd2222 }; // nota = 12, KF = 19 + 10'd788: phinc = { 12'd2223 }; // nota = 12, KF = 20 + 10'd789: phinc = { 12'd2226 }; // nota = 12, KF = 21 + 10'd790: phinc = { 12'd2227 }; // nota = 12, KF = 22 + 10'd791: phinc = { 12'd2230 }; // nota = 12, KF = 23 + 10'd792: phinc = { 12'd2232 }; // nota = 12, KF = 24 + 10'd793: phinc = { 12'd2234 }; // nota = 12, KF = 25 + 10'd794: phinc = { 12'd2236 }; // nota = 12, KF = 26 + 10'd795: phinc = { 12'd2238 }; // nota = 12, KF = 27 + 10'd796: phinc = { 12'd2239 }; // nota = 12, KF = 28 + 10'd797: phinc = { 12'd2242 }; // nota = 12, KF = 29 + 10'd798: phinc = { 12'd2243 }; // nota = 12, KF = 30 + 10'd799: phinc = { 12'd2246 }; // nota = 12, KF = 31 + 10'd800: phinc = { 12'd2249 }; // nota = 12, KF = 32 + 10'd801: phinc = { 12'd2251 }; // nota = 12, KF = 33 + 10'd802: phinc = { 12'd2253 }; // nota = 12, KF = 34 + 10'd803: phinc = { 12'd2255 }; // nota = 12, KF = 35 + 10'd804: phinc = { 12'd2256 }; // nota = 12, KF = 36 + 10'd805: phinc = { 12'd2259 }; // nota = 12, KF = 37 + 10'd806: phinc = { 12'd2260 }; // nota = 12, KF = 38 + 10'd807: phinc = { 12'd2263 }; // nota = 12, KF = 39 + 10'd808: phinc = { 12'd2265 }; // nota = 12, KF = 40 + 10'd809: phinc = { 12'd2267 }; // nota = 12, KF = 41 + 10'd810: phinc = { 12'd2269 }; // nota = 12, KF = 42 + 10'd811: phinc = { 12'd2271 }; // nota = 12, KF = 43 + 10'd812: phinc = { 12'd2272 }; // nota = 12, KF = 44 + 10'd813: phinc = { 12'd2275 }; // nota = 12, KF = 45 + 10'd814: phinc = { 12'd2276 }; // nota = 12, KF = 46 + 10'd815: phinc = { 12'd2279 }; // nota = 12, KF = 47 + 10'd816: phinc = { 12'd2281 }; // nota = 12, KF = 48 + 10'd817: phinc = { 12'd2283 }; // nota = 12, KF = 49 + 10'd818: phinc = { 12'd2285 }; // nota = 12, KF = 50 + 10'd819: phinc = { 12'd2287 }; // nota = 12, KF = 51 + 10'd820: phinc = { 12'd2288 }; // nota = 12, KF = 52 + 10'd821: phinc = { 12'd2291 }; // nota = 12, KF = 53 + 10'd822: phinc = { 12'd2292 }; // nota = 12, KF = 54 + 10'd823: phinc = { 12'd2295 }; // nota = 12, KF = 55 + 10'd824: phinc = { 12'd2297 }; // nota = 12, KF = 56 + 10'd825: phinc = { 12'd2299 }; // nota = 12, KF = 57 + 10'd826: phinc = { 12'd2301 }; // nota = 12, KF = 58 + 10'd827: phinc = { 12'd2303 }; // nota = 12, KF = 59 + 10'd828: phinc = { 12'd2304 }; // nota = 12, KF = 60 + 10'd829: phinc = { 12'd2307 }; // nota = 12, KF = 61 + 10'd830: phinc = { 12'd2308 }; // nota = 12, KF = 62 + 10'd831: phinc = { 12'd2311 }; // nota = 12, KF = 63 + 10'd832: phinc = { 12'd2315 }; // nota = 13, KF = 0 + 10'd833: phinc = { 12'd2317 }; // nota = 13, KF = 1 + 10'd834: phinc = { 12'd2319 }; // nota = 13, KF = 2 + 10'd835: phinc = { 12'd2321 }; // nota = 13, KF = 3 + 10'd836: phinc = { 12'd2322 }; // nota = 13, KF = 4 + 10'd837: phinc = { 12'd2325 }; // nota = 13, KF = 5 + 10'd838: phinc = { 12'd2326 }; // nota = 13, KF = 6 + 10'd839: phinc = { 12'd2329 }; // nota = 13, KF = 7 + 10'd840: phinc = { 12'd2331 }; // nota = 13, KF = 8 + 10'd841: phinc = { 12'd2333 }; // nota = 13, KF = 9 + 10'd842: phinc = { 12'd2335 }; // nota = 13, KF = 10 + 10'd843: phinc = { 12'd2337 }; // nota = 13, KF = 11 + 10'd844: phinc = { 12'd2338 }; // nota = 13, KF = 12 + 10'd845: phinc = { 12'd2341 }; // nota = 13, KF = 13 + 10'd846: phinc = { 12'd2342 }; // nota = 13, KF = 14 + 10'd847: phinc = { 12'd2345 }; // nota = 13, KF = 15 + 10'd848: phinc = { 12'd2348 }; // nota = 13, KF = 16 + 10'd849: phinc = { 12'd2350 }; // nota = 13, KF = 17 + 10'd850: phinc = { 12'd2352 }; // nota = 13, KF = 18 + 10'd851: phinc = { 12'd2354 }; // nota = 13, KF = 19 + 10'd852: phinc = { 12'd2355 }; // nota = 13, KF = 20 + 10'd853: phinc = { 12'd2358 }; // nota = 13, KF = 21 + 10'd854: phinc = { 12'd2359 }; // nota = 13, KF = 22 + 10'd855: phinc = { 12'd2362 }; // nota = 13, KF = 23 + 10'd856: phinc = { 12'd2364 }; // nota = 13, KF = 24 + 10'd857: phinc = { 12'd2366 }; // nota = 13, KF = 25 + 10'd858: phinc = { 12'd2368 }; // nota = 13, KF = 26 + 10'd859: phinc = { 12'd2370 }; // nota = 13, KF = 27 + 10'd860: phinc = { 12'd2371 }; // nota = 13, KF = 28 + 10'd861: phinc = { 12'd2374 }; // nota = 13, KF = 29 + 10'd862: phinc = { 12'd2375 }; // nota = 13, KF = 30 + 10'd863: phinc = { 12'd2378 }; // nota = 13, KF = 31 + 10'd864: phinc = { 12'd2382 }; // nota = 13, KF = 32 + 10'd865: phinc = { 12'd2384 }; // nota = 13, KF = 33 + 10'd866: phinc = { 12'd2386 }; // nota = 13, KF = 34 + 10'd867: phinc = { 12'd2388 }; // nota = 13, KF = 35 + 10'd868: phinc = { 12'd2389 }; // nota = 13, KF = 36 + 10'd869: phinc = { 12'd2392 }; // nota = 13, KF = 37 + 10'd870: phinc = { 12'd2393 }; // nota = 13, KF = 38 + 10'd871: phinc = { 12'd2396 }; // nota = 13, KF = 39 + 10'd872: phinc = { 12'd2398 }; // nota = 13, KF = 40 + 10'd873: phinc = { 12'd2400 }; // nota = 13, KF = 41 + 10'd874: phinc = { 12'd2402 }; // nota = 13, KF = 42 + 10'd875: phinc = { 12'd2404 }; // nota = 13, KF = 43 + 10'd876: phinc = { 12'd2407 }; // nota = 13, KF = 44 + 10'd877: phinc = { 12'd2410 }; // nota = 13, KF = 45 + 10'd878: phinc = { 12'd2411 }; // nota = 13, KF = 46 + 10'd879: phinc = { 12'd2414 }; // nota = 13, KF = 47 + 10'd880: phinc = { 12'd2417 }; // nota = 13, KF = 48 + 10'd881: phinc = { 12'd2419 }; // nota = 13, KF = 49 + 10'd882: phinc = { 12'd2421 }; // nota = 13, KF = 50 + 10'd883: phinc = { 12'd2423 }; // nota = 13, KF = 51 + 10'd884: phinc = { 12'd2424 }; // nota = 13, KF = 52 + 10'd885: phinc = { 12'd2427 }; // nota = 13, KF = 53 + 10'd886: phinc = { 12'd2428 }; // nota = 13, KF = 54 + 10'd887: phinc = { 12'd2431 }; // nota = 13, KF = 55 + 10'd888: phinc = { 12'd2433 }; // nota = 13, KF = 56 + 10'd889: phinc = { 12'd2435 }; // nota = 13, KF = 57 + 10'd890: phinc = { 12'd2437 }; // nota = 13, KF = 58 + 10'd891: phinc = { 12'd2439 }; // nota = 13, KF = 59 + 10'd892: phinc = { 12'd2442 }; // nota = 13, KF = 60 + 10'd893: phinc = { 12'd2445 }; // nota = 13, KF = 61 + 10'd894: phinc = { 12'd2446 }; // nota = 13, KF = 62 + 10'd895: phinc = { 12'd2449 }; // nota = 13, KF = 63 + 10'd896: phinc = { 12'd2452 }; // nota = 14, KF = 0 + 10'd897: phinc = { 12'd2454 }; // nota = 14, KF = 1 + 10'd898: phinc = { 12'd2456 }; // nota = 14, KF = 2 + 10'd899: phinc = { 12'd2458 }; // nota = 14, KF = 3 + 10'd900: phinc = { 12'd2459 }; // nota = 14, KF = 4 + 10'd901: phinc = { 12'd2462 }; // nota = 14, KF = 5 + 10'd902: phinc = { 12'd2463 }; // nota = 14, KF = 6 + 10'd903: phinc = { 12'd2466 }; // nota = 14, KF = 7 + 10'd904: phinc = { 12'd2468 }; // nota = 14, KF = 8 + 10'd905: phinc = { 12'd2470 }; // nota = 14, KF = 9 + 10'd906: phinc = { 12'd2472 }; // nota = 14, KF = 10 + 10'd907: phinc = { 12'd2474 }; // nota = 14, KF = 11 + 10'd908: phinc = { 12'd2477 }; // nota = 14, KF = 12 + 10'd909: phinc = { 12'd2480 }; // nota = 14, KF = 13 + 10'd910: phinc = { 12'd2481 }; // nota = 14, KF = 14 + 10'd911: phinc = { 12'd2484 }; // nota = 14, KF = 15 + 10'd912: phinc = { 12'd2488 }; // nota = 14, KF = 16 + 10'd913: phinc = { 12'd2490 }; // nota = 14, KF = 17 + 10'd914: phinc = { 12'd2492 }; // nota = 14, KF = 18 + 10'd915: phinc = { 12'd2494 }; // nota = 14, KF = 19 + 10'd916: phinc = { 12'd2495 }; // nota = 14, KF = 20 + 10'd917: phinc = { 12'd2498 }; // nota = 14, KF = 21 + 10'd918: phinc = { 12'd2499 }; // nota = 14, KF = 22 + 10'd919: phinc = { 12'd2502 }; // nota = 14, KF = 23 + 10'd920: phinc = { 12'd2504 }; // nota = 14, KF = 24 + 10'd921: phinc = { 12'd2506 }; // nota = 14, KF = 25 + 10'd922: phinc = { 12'd2508 }; // nota = 14, KF = 26 + 10'd923: phinc = { 12'd2510 }; // nota = 14, KF = 27 + 10'd924: phinc = { 12'd2513 }; // nota = 14, KF = 28 + 10'd925: phinc = { 12'd2516 }; // nota = 14, KF = 29 + 10'd926: phinc = { 12'd2517 }; // nota = 14, KF = 30 + 10'd927: phinc = { 12'd2520 }; // nota = 14, KF = 31 + 10'd928: phinc = { 12'd2524 }; // nota = 14, KF = 32 + 10'd929: phinc = { 12'd2526 }; // nota = 14, KF = 33 + 10'd930: phinc = { 12'd2528 }; // nota = 14, KF = 34 + 10'd931: phinc = { 12'd2530 }; // nota = 14, KF = 35 + 10'd932: phinc = { 12'd2531 }; // nota = 14, KF = 36 + 10'd933: phinc = { 12'd2534 }; // nota = 14, KF = 37 + 10'd934: phinc = { 12'd2535 }; // nota = 14, KF = 38 + 10'd935: phinc = { 12'd2538 }; // nota = 14, KF = 39 + 10'd936: phinc = { 12'd2540 }; // nota = 14, KF = 40 + 10'd937: phinc = { 12'd2542 }; // nota = 14, KF = 41 + 10'd938: phinc = { 12'd2544 }; // nota = 14, KF = 42 + 10'd939: phinc = { 12'd2546 }; // nota = 14, KF = 43 + 10'd940: phinc = { 12'd2549 }; // nota = 14, KF = 44 + 10'd941: phinc = { 12'd2552 }; // nota = 14, KF = 45 + 10'd942: phinc = { 12'd2553 }; // nota = 14, KF = 46 + 10'd943: phinc = { 12'd2556 }; // nota = 14, KF = 47 + 10'd944: phinc = { 12'd2561 }; // nota = 14, KF = 48 + 10'd945: phinc = { 12'd2563 }; // nota = 14, KF = 49 + 10'd946: phinc = { 12'd2565 }; // nota = 14, KF = 50 + 10'd947: phinc = { 12'd2567 }; // nota = 14, KF = 51 + 10'd948: phinc = { 12'd2568 }; // nota = 14, KF = 52 + 10'd949: phinc = { 12'd2571 }; // nota = 14, KF = 53 + 10'd950: phinc = { 12'd2572 }; // nota = 14, KF = 54 + 10'd951: phinc = { 12'd2575 }; // nota = 14, KF = 55 + 10'd952: phinc = { 12'd2577 }; // nota = 14, KF = 56 + 10'd953: phinc = { 12'd2579 }; // nota = 14, KF = 57 + 10'd954: phinc = { 12'd2581 }; // nota = 14, KF = 58 + 10'd955: phinc = { 12'd2583 }; // nota = 14, KF = 59 + 10'd956: phinc = { 12'd2586 }; // nota = 14, KF = 60 + 10'd957: phinc = { 12'd2589 }; // nota = 14, KF = 61 + 10'd958: phinc = { 12'd2590 }; // nota = 14, KF = 62 + 10'd959: phinc = { 12'd2593 }; // nota = 14, KF = 63 + 10'd960: phinc = { 12'd2452 }; // nota = 15, KF = 0 + 10'd961: phinc = { 12'd2454 }; // nota = 15, KF = 1 + 10'd962: phinc = { 12'd2456 }; // nota = 15, KF = 2 + 10'd963: phinc = { 12'd2458 }; // nota = 15, KF = 3 + 10'd964: phinc = { 12'd2459 }; // nota = 15, KF = 4 + 10'd965: phinc = { 12'd2462 }; // nota = 15, KF = 5 + 10'd966: phinc = { 12'd2463 }; // nota = 15, KF = 6 + 10'd967: phinc = { 12'd2466 }; // nota = 15, KF = 7 + 10'd968: phinc = { 12'd2468 }; // nota = 15, KF = 8 + 10'd969: phinc = { 12'd2470 }; // nota = 15, KF = 9 + 10'd970: phinc = { 12'd2472 }; // nota = 15, KF = 10 + 10'd971: phinc = { 12'd2474 }; // nota = 15, KF = 11 + 10'd972: phinc = { 12'd2477 }; // nota = 15, KF = 12 + 10'd973: phinc = { 12'd2480 }; // nota = 15, KF = 13 + 10'd974: phinc = { 12'd2481 }; // nota = 15, KF = 14 + 10'd975: phinc = { 12'd2484 }; // nota = 15, KF = 15 + 10'd976: phinc = { 12'd2488 }; // nota = 15, KF = 16 + 10'd977: phinc = { 12'd2490 }; // nota = 15, KF = 17 + 10'd978: phinc = { 12'd2492 }; // nota = 15, KF = 18 + 10'd979: phinc = { 12'd2494 }; // nota = 15, KF = 19 + 10'd980: phinc = { 12'd2495 }; // nota = 15, KF = 20 + 10'd981: phinc = { 12'd2498 }; // nota = 15, KF = 21 + 10'd982: phinc = { 12'd2499 }; // nota = 15, KF = 22 + 10'd983: phinc = { 12'd2502 }; // nota = 15, KF = 23 + 10'd984: phinc = { 12'd2504 }; // nota = 15, KF = 24 + 10'd985: phinc = { 12'd2506 }; // nota = 15, KF = 25 + 10'd986: phinc = { 12'd2508 }; // nota = 15, KF = 26 + 10'd987: phinc = { 12'd2510 }; // nota = 15, KF = 27 + 10'd988: phinc = { 12'd2513 }; // nota = 15, KF = 28 + 10'd989: phinc = { 12'd2516 }; // nota = 15, KF = 29 + 10'd990: phinc = { 12'd2517 }; // nota = 15, KF = 30 + 10'd991: phinc = { 12'd2520 }; // nota = 15, KF = 31 + 10'd992: phinc = { 12'd2524 }; // nota = 15, KF = 32 + 10'd993: phinc = { 12'd2526 }; // nota = 15, KF = 33 + 10'd994: phinc = { 12'd2528 }; // nota = 15, KF = 34 + 10'd995: phinc = { 12'd2530 }; // nota = 15, KF = 35 + 10'd996: phinc = { 12'd2531 }; // nota = 15, KF = 36 + 10'd997: phinc = { 12'd2534 }; // nota = 15, KF = 37 + 10'd998: phinc = { 12'd2535 }; // nota = 15, KF = 38 + 10'd999: phinc = { 12'd2538 }; // nota = 15, KF = 39 + 10'd1000: phinc = { 12'd2540 }; // nota = 15, KF = 40 + 10'd1001: phinc = { 12'd2542 }; // nota = 15, KF = 41 + 10'd1002: phinc = { 12'd2544 }; // nota = 15, KF = 42 + 10'd1003: phinc = { 12'd2546 }; // nota = 15, KF = 43 + 10'd1004: phinc = { 12'd2549 }; // nota = 15, KF = 44 + 10'd1005: phinc = { 12'd2552 }; // nota = 15, KF = 45 + 10'd1006: phinc = { 12'd2553 }; // nota = 15, KF = 46 + 10'd1007: phinc = { 12'd2556 }; // nota = 15, KF = 47 + 10'd1008: phinc = { 12'd2561 }; // nota = 15, KF = 48 + 10'd1009: phinc = { 12'd2563 }; // nota = 15, KF = 49 + 10'd1010: phinc = { 12'd2565 }; // nota = 15, KF = 50 + 10'd1011: phinc = { 12'd2567 }; // nota = 15, KF = 51 + 10'd1012: phinc = { 12'd2568 }; // nota = 15, KF = 52 + 10'd1013: phinc = { 12'd2571 }; // nota = 15, KF = 53 + 10'd1014: phinc = { 12'd2572 }; // nota = 15, KF = 54 + 10'd1015: phinc = { 12'd2575 }; // nota = 15, KF = 55 + 10'd1016: phinc = { 12'd2577 }; // nota = 15, KF = 56 + 10'd1017: phinc = { 12'd2579 }; // nota = 15, KF = 57 + 10'd1018: phinc = { 12'd2581 }; // nota = 15, KF = 58 + 10'd1019: phinc = { 12'd2583 }; // nota = 15, KF = 59 + 10'd1020: phinc = { 12'd2586 }; // nota = 15, KF = 60 + 10'd1021: phinc = { 12'd2589 }; // nota = 15, KF = 61 + 10'd1022: phinc = { 12'd2590 }; // nota = 15, KF = 62 + 10'd1023: phinc = { 12'd2593 }; // nota = 15, KF = 63 + endcase +end + +endmodule diff --git a/modules/sound-jt51/jt51_phrom.v b/modules/sound-jt51/jt51_phrom.v new file mode 100644 index 0000000..7bf496f --- /dev/null +++ b/modules/sound-jt51/jt51_phrom.v @@ -0,0 +1,76 @@ + + +/* This file is part of JT51. + + + JT51 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. + + JT51 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 JT51. If not, see . + + Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-4-2017 + +*/ + +module jt51_phrom +( + input [4:0] addr, + input clk, + input cen, + output reg [45:0] ph +); + + reg [45:0] sinetable[31:0]; + initial + begin + sinetable[5'd0 ] = 46'b0001100000100100010001000010101010101001010010; + sinetable[5'd1 ] = 46'b0001100000110100000100000010010001001101000001; + sinetable[5'd2 ] = 46'b0001100000110100000100110010001011001101100000; + sinetable[5'd3 ] = 46'b0001110000010000000000110010110001001101110010; + sinetable[5'd4 ] = 46'b0001110000010000001100000010111010001101101001; + sinetable[5'd5 ] = 46'b0001110000010100001001100010000000101101111010; + sinetable[5'd6 ] = 46'b0001110000010100001101100010010011001101011010; + sinetable[5'd7 ] = 46'b0001110000011100000101010010111000101111111100; + sinetable[5'd8 ] = 46'b0001110000111000000001110010101110001101110111; + sinetable[5'd9 ] = 46'b0001110000111000010100111000011101011010100110; + sinetable[5'd10] = 46'b0001110000111100011000011000111100001001111010; + sinetable[5'd11] = 46'b0001110000111100011100111001101011001001110111; + sinetable[5'd12] = 46'b0100100001010000010001011001001000111010110111; + sinetable[5'd13] = 46'b0100100001010100010001001001110001111100101010; + sinetable[5'd14] = 46'b0100100001010100010101101101111110100101000110; + sinetable[5'd15] = 46'b0100100011100000001000011001010110101101111001; + sinetable[5'd16] = 46'b0100100011100100001000101011100101001011101111; + sinetable[5'd17] = 46'b0100100011101100000111011010000001011010110001; + sinetable[5'd18] = 46'b0100110011001000000111101010000010111010111111; + sinetable[5'd19] = 46'b0100110011001100001011011110101110110110000001; + sinetable[5'd20] = 46'b0100110011101000011010111011001010001101110001; + sinetable[5'd21] = 46'b0100110011101101011010110101111001010100001111; + sinetable[5'd22] = 46'b0111000010000001010111000101010101010110010111; + sinetable[5'd23] = 46'b0111000010000101010111110111110101010010111011; + sinetable[5'd24] = 46'b0111000010110101101000101100001000010000011001; + sinetable[5'd25] = 46'b0111010010011001100100011110100100010010010010; + sinetable[5'd26] = 46'b0111010010111010100101100101000000110100100011; + sinetable[5'd27] = 46'b1010000010011010101101011101100001110010011010; + sinetable[5'd28] = 46'b1010000010111111111100100111010100010000111001; + sinetable[5'd29] = 46'b1010010111110100110010001100111001010110100000; + sinetable[5'd30] = 46'b1011010111010011111011011110000100110010100001; + sinetable[5'd31] = 46'b1110011011110001111011100111100001110110100111; + + end + + always @ (posedge clk) if(cen) + ph <= sinetable[addr]; + +endmodule diff --git a/modules/sound-jt51/jt51_pm.v b/modules/sound-jt51/jt51_pm.v new file mode 100644 index 0000000..3a82ab3 --- /dev/null +++ b/modules/sound-jt51/jt51_pm.v @@ -0,0 +1,94 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_pm( + input [ 6:0] kc_I, + input [ 5:0] kf_I, + input [ 8:0] mod_I, + input add, + output reg [12:0] kcex +); + +reg [ 9:0] lim; +reg [13:0] kcex0, kcex1; +reg [ 1:0] extra; + +reg [ 6:0] kcin; +reg carry; + +always @(*) begin: kc_input_cleaner + { carry, kcin } = kc_I[1:0]==2'd3 ? { 1'b0, kc_I } + 8'd1 : {1'b0,kc_I}; +end + +always @(*) begin : addition + lim = { 1'd0, mod_I } + { 4'd0, kf_I }; + case( kcin[3:0] ) + default: + if( lim>=10'd448 ) extra = 2'd2; + else if( lim>=10'd256 ) extra = 2'd1; + else extra = 2'd0; + 4'd1,4'd5,4'd9,4'd13: + if( lim>=10'd384 ) extra = 2'd2; + else if( lim>=10'd192 ) extra = 2'd1; + else extra = 2'd0; + 4'd2,4'd6,4'd10,4'd14: + if( lim>=10'd512 ) extra = 2'd3; + else if( lim>=10'd320 ) extra = 2'd2; + else if( lim>=10'd128 ) extra = 2'd1; + else extra = 2'd0; + endcase + kcex0 = {1'b0,kcin,kf_I} + { 6'd0, extra, 6'd0 } + { 5'd0, mod_I }; + kcex1 = kcex0[7:6]==2'd3 ? kcex0 + 14'd64 : kcex0; +end + +reg signed [ 9:0] slim; +reg [ 1:0] sextra; +reg [13:0] skcex0, skcex1; + +always @(*) begin : subtraction + slim = { 1'd0, mod_I } - { 4'd0, kf_I }; + case( kcin[3:0] ) + default: + if( slim>=10'sd449 ) sextra = 2'd3; + else if( slim>=10'sd257 ) sextra = 2'd2; + else if( slim>=10'sd65 ) sextra = 2'd1; + else sextra = 2'd0; + 4'd1,4'd5,4'd9,4'd13: + if( slim>=10'sd321 ) sextra = 2'd2; + else if( slim>=10'sd129 ) sextra = 2'd1; + else sextra = 2'd0; + 4'd2,4'd6,4'd10,4'd14: + if( slim>=10'sd385 ) sextra = 2'd2; + else if( slim>=10'sd193 ) sextra = 2'd1; + else sextra = 2'd0; + endcase + skcex0 = {1'b0,kcin,kf_I} - { 6'd0, sextra, 6'd0 } - { 5'd0, mod_I }; + skcex1 = skcex0[7:6]==2'd3 ? skcex0 - 14'd64 : skcex0; +end + +always @(*) begin : mux + if ( add ) + kcex = kcex1[13] | carry ? {3'd7, 4'd14, 6'd63} : kcex1[12:0]; + else + kcex = carry ? {3'd7, 4'd14, 6'd63} : (skcex1[13] ? 13'd0 : skcex1[12:0]); +end + +endmodule diff --git a/modules/sound-jt51/jt51_reg.v b/modules/sound-jt51/jt51_reg.v new file mode 100644 index 0000000..abafe73 --- /dev/null +++ b/modules/sound-jt51/jt51_reg.v @@ -0,0 +1,306 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_reg( + input rst, + input clk, + input cen, // P1 + input [7:0] din, + + input up_rl, + input up_kc, + input up_kf, + input up_pms, + input up_dt1, + input up_tl, + input up_ks, + input up_amsen, + input up_dt2, + input up_d1l, + input up_keyon, + input [1:0] op, // operator to update + input [2:0] ch, // channel to update + + input csm, + input overflow_A, + + output [1:0] rl_I, + output [2:0] fb_II, + output [2:0] con_I, + output [6:0] kc_I, + output [5:0] kf_I, + output [2:0] pms_I, + output [1:0] ams_VII, + output [2:0] dt1_II, + output [3:0] mul_VI, + output [6:0] tl_VII, + output [1:0] ks_III, + output amsen_VII, + + output [4:0] arate_II, + output [4:0] rate1_II, + output [4:0] rate2_II, + output [3:0] rrate_II, + + output [1:0] dt2_I, + output [3:0] d1l_I, + output keyon_II, + + // Pipeline order + output reg zero, + output reg half, + output [4:0] cycles, + output reg m1_enters, + output reg m2_enters, + output reg c1_enters, + output reg c2_enters, + // Operator + output use_prevprev1, + output use_internal_x, + output use_internal_y, + output use_prev2, + output use_prev1, + + output [1:0] cur_op, + output reg op31_no, + output reg op31_acc +); + +reg kon, koff; +reg [1:0] csm_state; +reg [4:0] csm_cnt; + +// wire csm_kon = csm_state[0]; +// wire csm_koff = csm_state[1]; + +always @(*) begin + m1_enters = cur_op == 2'b00; + m2_enters = cur_op == 2'b01; + c1_enters = cur_op == 2'b10; + c2_enters = cur_op == 2'b11; +end + +`ifdef SIMULATION +wire up = up_rl | up_kc | up_kf | up_pms | up_dt1 | up_tl | + up_ks | up_amsen | up_dt2 | up_d1l | up_keyon; +`endif + +reg [4:0] cur; + +always @(posedge clk) if(cen) begin + op31_no <= cur == 5'o10; + op31_acc <= cur == 5'o16; +end + +assign cur_op = cur[4:3]; +assign cycles = cur; + +wire [4:0] req_I = { op, ch }; +wire [4:0] req_II = req_I + 5'd1; +wire [4:0] req_III = req_II + 5'd1; +wire [4:0] req_IV = req_III + 5'd1; +wire [4:0] req_V = req_IV + 5'd1; +wire [4:0] req_VI = req_V + 5'd1; +wire [4:0] req_VII = req_VI + 5'd1; + + +wire update_op_I = cur == req_I; +wire update_op_II = cur == req_II; +wire update_op_III = cur == req_III; +// wire update_op_IV = cur == req_IV; +// wire update_op_V = cur == req_V; +wire update_op_VI = cur == req_VI; +wire update_op_VII = cur == req_VII; + +wire up_rl_ch = up_rl & update_op_I; +wire up_fb_ch = up_rl & update_op_II; +wire up_con_ch = up_rl & update_op_I; + +wire up_kc_ch = up_kc & update_op_I; +wire up_kf_ch = up_kf & update_op_I; +wire up_pms_ch = up_pms & update_op_I; +wire up_ams_ch = up_pms & update_op_VII; + +wire up_dt1_op = up_dt1 & update_op_II; // DT1, MUL +wire up_mul_op = up_dt1 & update_op_VI; // DT1, MUL +wire up_tl_op = up_tl & update_op_VII; +wire up_ks_op = up_ks & update_op_III; // KS, AR +wire up_amsen_op= up_amsen & update_op_VII; // AMS-EN, D1R +wire up_dt2_op = up_dt2 & update_op_I; // DT2, D2R +wire up_d1l_op = up_d1l & update_op_I; // D1L, RR + +wire up_ar_op = up_ks & update_op_II; // KS, AR +wire up_d1r_op = up_amsen & update_op_II; // AMS-EN, D1R +wire up_d2r_op = up_dt2 & update_op_II; // DT2, D2R +wire up_rr_op = up_d1l & update_op_II; // D1L, RR + +wire [4:0] next = cur+5'd1; + +always @(posedge clk, posedge rst) begin : up_counter + if( rst ) begin + cur <= 5'h0; + zero <= 1'b0; + half <= 1'b0; + end + else if(cen) begin + cur <= next; + zero <= next== 5'd0; + half <= next[3:0] == 4'd0; + end +end + +wire [2:0] cur_ch = cur[2:0]; +wire [3:0] keyon_op = din[6:3]; +wire [2:0] keyon_ch = din[2:0]; + +jt51_kon u_kon ( + .rst (rst ), + .clk (clk ), + .cen (cen ), + .keyon_op (keyon_op ), + .keyon_ch (keyon_ch ), + .cur_op (cur_op ), + .cur_ch (cur_ch ), + .up_keyon (up_keyon ), + .csm (csm ), + .overflow_A(overflow_A), + .keyon_II (keyon_II ) +); + + +jt51_mod u_mod( + .alg_I ( con_I ), + .m1_enters ( m1_enters ), + .m2_enters ( m2_enters ), + .c1_enters ( c1_enters ), + .c2_enters ( c2_enters ), + + .use_prevprev1 ( use_prevprev1 ), + .use_internal_x( use_internal_x ), + .use_internal_y( use_internal_y ), + .use_prev2 ( use_prev2 ), + .use_prev1 ( use_prev1 ) +); + +jt51_csr_op u_csr_op( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), // P1 + .din ( din ), + + .up_dt1_op ( up_dt1_op ), + .up_mul_op ( up_mul_op ), + .up_tl_op ( up_tl_op ), + .up_ks_op ( up_ks_op ), + .up_amsen_op ( up_amsen_op ), + .up_dt2_op ( up_dt2_op ), + .up_d1l_op ( up_d1l_op ), + .up_ar_op ( up_ar_op ), + .up_d1r_op ( up_d1r_op ), + .up_d2r_op ( up_d2r_op ), + .up_rr_op ( up_rr_op ), + + .dt1 ( dt1_II ), + .mul ( mul_VI ), + .tl ( tl_VII ), + .ks ( ks_III ), + .amsen ( amsen_VII ), + .dt2 ( dt2_I ), + .d1l ( d1l_I ), + .arate ( arate_II ), + .rate1 ( rate1_II ), + .rate2 ( rate2_II ), + .rrate ( rrate_II ) +); + +jt51_csr_ch u_csr_ch( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .din ( din ), + + .up_rl_ch ( up_rl_ch ), + .up_fb_ch ( up_fb_ch ), + .up_con_ch ( up_con_ch ), + .up_kc_ch ( up_kc_ch ), + .up_kf_ch ( up_kf_ch ), + .up_ams_ch ( up_ams_ch ), + .up_pms_ch ( up_pms_ch ), + + .rl ( rl_I ), + .fb ( fb_II ), + .con ( con_I ), + .kc ( kc_I ), + .kf ( kf_I ), + .ams ( ams_VII ), + .pms ( pms_I ) +); + +//////////////////// Debug +`ifdef JT51_DEBUG +`ifdef SIMULATION +/* verilator lint_off PINMISSING */ +wire [4:0] cnt_aux; + +sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt_aux)); + +sep32 #(.width(7),.stg(1)) sep_tl( + .clk ( clk ), + .cen ( cen ), + .mixed ( tl_VII ), + .cnt ( cnt_aux ) + ); + +sep32 #(.width(5),.stg(1)) sep_ar( + .clk ( clk ), + .cen ( cen ), + .mixed ( arate_II ), + .cnt ( cnt_aux ) + ); + + +sep32 #(.width(4),.stg(1)) sep_d1l( + .clk ( clk ), + .cen ( cen ), + .mixed ( d1l_I ), + .cnt ( cnt_aux ) + ); + + +sep32 #(.width(4),.stg(1)) sep_rr( + .clk ( clk ), + .cen ( cen ), + .mixed ( rrate_II ), + .cnt ( cnt_aux ) + ); + +sep32 #(.width(1),.stg(1)) sep_amsen( + .clk ( clk ), + .cen ( cen ), + .mixed ( amsen_VII ), + .cnt ( cnt_aux ) + ); + +/* verilator lint_on PINMISSING */ +`endif +`endif + +endmodule diff --git a/modules/sound-jt51/jt51_sh.v b/modules/sound-jt51/jt51_sh.v new file mode 100644 index 0000000..8b2335a --- /dev/null +++ b/modules/sound-jt51/jt51_sh.v @@ -0,0 +1,45 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + + +module jt51_sh #(parameter width=5, stages=32, rstval=1'b0 ) ( + input rst, + input clk, + input cen, + input [width-1:0] din, + output [width-1:0] drop +); + +reg [stages-1:0] bits[width-1:0]; + +genvar i; +generate + for (i=0; i < width; i=i+1) begin: bit_shifter + always @(posedge clk, posedge rst) begin + if(rst) + bits[i] <= {stages{rstval}}; + else if(cen) + bits[i] <= {bits[i][stages-2:0], din[i]}; + end + assign drop[i] = bits[i][stages-1]; + end +endgenerate + +endmodule diff --git a/modules/sound-jt51/jt51_timers.v b/modules/sound-jt51/jt51_timers.v new file mode 100644 index 0000000..7bcab5c --- /dev/null +++ b/modules/sound-jt51/jt51_timers.v @@ -0,0 +1,121 @@ +/* This file is part of JT51. + + JT51 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. + + JT51 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 JT51. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-10-2016 + */ + +module jt51_timers( + input rst, + input clk, + input cen, + input zero, + input [9:0] value_A, + input [7:0] value_B, + input load_A, + input load_B, + input clr_flag_A, + input clr_flag_B, + input enable_irq_A, + input enable_irq_B, + output flag_A, + output flag_B, + output overflow_A, + output irq_n +); + +assign irq_n = ~( (flag_A&enable_irq_A) | (flag_B&enable_irq_B) ); + +jt51_timer #(.CW(10)) timer_A( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .zero ( zero ), + .start_value( value_A ), + .load ( load_A ), + .clr_flag ( clr_flag_A), + .flag ( flag_A ), + .overflow ( overflow_A) +); + +jt51_timer #(.CW(8),.FREE_EN(1)) timer_B( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .zero ( zero ), + .start_value( value_B ), + .load ( load_B ), + .clr_flag ( clr_flag_B ), + .flag ( flag_B ), + .overflow ( ) +); + +endmodule + +module jt51_timer #(parameter + CW = 8, // counter bit width. This is the counter that can be loaded + FREE_EN = 0 // enables a 4-bit free enable count +) ( + input rst, + input clk, + input cen, + input zero, + input [CW-1:0] start_value, + input load, + input clr_flag, + output reg flag, + output reg overflow +); + +reg last_load; +reg [CW-1:0] cnt, next; +reg [ 3:0] free_cnt, free_next; +reg free_ov; + +always@(posedge clk, posedge rst) + if( rst ) + flag <= 1'b0; + else /*if(cen)*/ begin + if( clr_flag ) + flag <= 1'b0; + else if(overflow) flag<=1'b1; + end + +always @(*) begin + {free_ov, free_next} = { 1'b0, free_cnt} + 1'b1; + /* verilator lint_off WIDTH */ + {overflow, next } = { 1'b0, cnt } + (FREE_EN ? free_ov : 1'b1); + /* verilator lint_on WIDTH */ +end + +always @(posedge clk) if(cen && zero) begin : counter + last_load <= load; + if( (load && !last_load) || overflow ) begin + cnt <= start_value; + end + else if( last_load ) cnt <= next; +end + +// Free running counter +always @(posedge clk) begin + if( rst ) begin + free_cnt <= 4'd0; + end else if( cen&&zero ) begin + free_cnt <= free_next; + end +end + +endmodule diff --git a/pkg/meta/Blade Master (World).mra b/pkg/meta/Blade Master (World).mra new file mode 100644 index 0000000..ac043eb --- /dev/null +++ b/pkg/meta/Blade Master (World).mra @@ -0,0 +1,104 @@ + + Blade Master (World) + 0245 + bmaster + 1991 + Irem + Brawler + IremM92 + horizontal + + 8-way + 2 + + + + + + + + + + + + + + + + + 00 + + + 00 0a 00 00 + + + + + + + + + + + 01 10 00 00 + + + + + + + + + 02 20 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 90 90 79 90 9d 48 90 90 90 90 2e 90 90 a5 72 90 + 46 5b b1 3a c3 90 35 90 90 23 90 99 90 05 90 3c + 3b 76 11 90 90 4b 90 92 90 32 5d 90 f7 5a 9c 90 + 26 40 89 90 90 90 90 57 90 90 90 90 90 ba 53 bb + 42 59 2f 90 77 90 90 4f bf 4a cb 86 62 7d 90 b8 + 90 34 90 5f 90 7f f8 80 a0 84 12 52 90 90 90 47 + 90 2b 88 f9 90 a3 83 90 75 87 90 ab eb 90 fe 90 + 90 af d0 2c d1 e6 90 43 a2 e7 85 e2 49 22 29 90 + 7c 90 90 9a 90 90 b9 90 14 cf 33 02 90 90 90 73 + 90 c5 90 90 90 f3 f6 24 90 56 d3 90 09 01 90 90 + 03 2d 1b 90 f5 be 90 90 fb 8e 21 8d 0b 90 90 b2 + fc fa c6 90 e8 d2 90 08 0a a8 78 ff 90 b5 90 90 + c7 06 18 90 90 1e 7e b0 0e 0f 90 90 0c aa 55 90 + 90 74 3d 90 90 38 27 50 90 b6 5e 8b 07 e5 39 ea + bd 90 81 b7 90 8a 0d 90 58 a1 a9 36 90 c4 90 8f + 8c 1f 51 04 f2 90 b3 b4 e9 2a 90 90 90 25 90 bc + + + + 05 08 00 00 + + + + + + + 00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 75 0e 00 80 d3 00 + + + + \ No newline at end of file diff --git a/pkg/meta/Dream Soccer '94 (Japan, M92 hardware).mra b/pkg/meta/Dream Soccer '94 (Japan, M92 hardware).mra new file mode 100644 index 0000000..71f7a35 --- /dev/null +++ b/pkg/meta/Dream Soccer '94 (Japan, M92 hardware).mra @@ -0,0 +1,106 @@ + + Dream Soccer '94 (Japan, M92 hardware) + 0245 + dsoccr94 + dsoccr94j + 1994 + Irem + Sport + IremM92 + horizontal + + 8-way + 2 + + + + + + + + + + + + + + + + + + 86 + + + 00 10 00 00 + + + + + + + + + + + 01 40 00 00 + + + + + + + + + 06 40 00 00 + + + + + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 90 d1 90 90 90 79 2e 90 90 90 5a 0f 90 90 43 90 + 90 90 e8 50 90 90 90 a0 5d 22 90 90 b2 3a 90 90 + f6 8a 41 90 90 81 90 90 90 90 2b 58 90 90 90 c6 + 90 90 b9 90 90 2a 90 3c 90 80 26 90 b0 90 47 90 + 90 90 0a 55 90 90 90 88 90 90 87 90 90 b4 0c 90 + 73 53 90 90 3b 1f 90 90 90 90 90 90 90 90 90 90 + f7 90 90 90 90 1e 90 90 c3 90 a3 74 90 32 42 75 + fc 90 b8 90 33 90 5e 90 90 aa 90 90 04 90 9c ba + 90 90 24 89 90 90 ea 90 23 90 90 90 bb 90 90 c7 + 90 8e 90 52 90 18 90 72 90 90 90 90 b6 90 90 90 + fa 90 90 90 90 90 90 90 b1 90 90 90 90 57 78 a2 + 90 3d 51 90 90 bf 46 2c 90 90 fb 90 90 90 90 38 + 56 90 cf 90 08 90 90 90 5b 07 90 90 90 20 9d 90 + 03 90 90 90 90 90 bc 86 59 90 02 90 ff d2 8b 90 + 90 d0 90 90 90 90 90 e9 06 90 5f f3 90 b5 90 90 + eb 90 90 90 90 90 83 90 36 90 90 90 90 bd fe 90 + + + + 05 10 00 00 + + + + + + 00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e ad 6d 00 80 10 04 + + + + \ No newline at end of file diff --git a/pkg/meta/Gun Force II (US).mra b/pkg/meta/Gun Force II (US).mra new file mode 100644 index 0000000..f66fb62 --- /dev/null +++ b/pkg/meta/Gun Force II (US).mra @@ -0,0 +1,99 @@ + + Gun Force II (US) + 0245 + gunforc2 + 1994 + Irem + Shooter + IremM92 + horizontal + + 8-way + 2 + + + + + + + + + + + + + + + + 06 + + + 00 10 00 00 + + + + + + + + + + + 01 20 00 00 + + + + + + + + + 02 40 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 7f 26 5d 90 ba 90 1e 5e b8 49 bc e8 01 90 4a 25 + 90 bd 90 22 10 90 02 57 70 90 7c 90 e7 52 90 a9 + 90 90 c6 06 a0 fe cf 8e 43 8f 2d 8c d4 85 75 a2 + 3d 90 90 38 7e 89 d1 80 3b 72 07 90 42 37 0a 18 + 88 b4 98 8b b9 9c ad 0e 2b 90 bf 90 55 90 56 b0 + 93 91 90 eb 90 50 41 29 47 90 90 60 90 ab 90 90 + c3 e2 d0 b2 11 79 90 08 82 fb 90 2c 23 90 28 0d + 90 90 90 83 3c 90 1b 34 5b 90 40 90 90 04 fc cd + b1 f3 8a 90 90 87 90 90 90 90 90 90 be 84 1f e6 + ff 90 12 90 b5 36 90 b3 90 90 90 d2 4e 90 90 90 + a5 90 90 c7 90 27 0b 90 20 90 90 90 90 90 61 7d + 63 90 86 0f 90 b7 90 4f 13 90 c0 fd 90 39 90 77 + 05 3a 90 48 92 71 3e 03 90 f8 90 59 a8 5f f9 bb + 81 fa 9d e9 2e a1 c1 33 90 78 90 0c 90 24 aa ac + 90 b6 90 ea 90 73 e5 58 00 f7 90 74 90 76 90 a3 + 90 5a f6 32 46 2a 90 90 53 4b 90 35 51 68 99 13 + + + + 05 10 00 00 + + + + + + 00 00 00 0A 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e a5 ae 00 4b 00 a6 + + + + \ No newline at end of file diff --git a/pkg/meta/Gunforce - Battle Fire Engulfed Terror Island (World).mra b/pkg/meta/Gunforce - Battle Fire Engulfed Terror Island (World).mra new file mode 100644 index 0000000..6a33985 --- /dev/null +++ b/pkg/meta/Gunforce - Battle Fire Engulfed Terror Island (World).mra @@ -0,0 +1,101 @@ + + Gunforce - Battle Fire Engulfed Terror Island (World) + 0245 + gunforce + 1991 + Irem + Shooter + IremM92 + horizontal + + 2 + 8-way + 2 + + + + + + + + + + + + + + + + + 00 + + + 00 08 00 00 + + + + + + + + + + + 01 10 00 00 + + + + + + + + + 02 10 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + ff 90 90 2c 90 90 43 88 90 13 0a bd ba 60 ea 90 + 90 90 f2 29 b3 22 90 0c a9 5f 9d 07 90 90 0b bb + 8a 90 90 90 3a 3c 5a 38 99 90 f8 89 90 91 90 55 + ac 40 73 90 59 90 fc 90 50 fa 90 25 90 34 47 b7 + 90 90 90 49 90 0f 8b 05 c3 a5 bf 83 86 c5 90 90 + 08 77 24 b4 90 92 90 3b 5e b6 80 0d 2e ab e7 90 + 48 90 ad c0 90 1b c6 a3 04 90 90 90 16 b0 7d 98 + 87 46 8c 90 90 fe 90 cf 90 68 84 90 d2 90 18 51 + 76 a4 36 52 fb 90 b9 90 90 b1 1c 21 e6 b5 17 27 + 3d 45 be ae 90 4a 0e e5 90 58 1f 61 f3 02 90 e8 + 90 90 90 f7 56 96 aa bc 4f 90 90 79 d0 90 2a 12 + 4e b8 90 41 90 90 d3 90 2d 33 f6 90 90 14 90 32 + 5d a8 53 26 2b 20 81 75 7f 3e 90 90 00 93 90 b2 + 57 90 a0 90 39 90 90 72 90 01 42 74 9c 1e 90 5b + 90 f9 90 2f 85 90 eb a2 90 e2 11 90 4b 7e 90 78 + 90 90 09 a1 03 90 23 c1 8e e9 d1 7c 90 90 c7 06 + + + + 05 02 00 00 + + + + + + 00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 66 33 00 40 44 20 + + + + \ No newline at end of file diff --git a/pkg/meta/Hook (World).mra b/pkg/meta/Hook (World).mra new file mode 100644 index 0000000..4121ae9 --- /dev/null +++ b/pkg/meta/Hook (World).mra @@ -0,0 +1,102 @@ + + Hook (World) + 0245 + hook + 1992 + Irem + Brawler + IremM92 + horizontal + + 8-way + 2 + + + + + + + + + + + + + + + + + + + 00 + + + 00 0c 00 00 + + + + + + + + + + + 01 10 00 00 + + + + + + + + + 02 40 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + b6 20 22 90 0f 57 59 c6 eb 90 b0 bb 3b 90 90 90 + 36 90 90 90 90 90 90 90 90 fe 90 90 90 90 90 a0 + 2e 90 0b 90 90 58 90 90 90 90 90 90 90 80 90 90 + 33 90 90 bf 55 90 90 90 53 90 90 90 90 90 90 90 + 47 74 90 b1 b4 90 90 88 90 90 38 cf 90 8e 90 90 + 90 c7 90 32 90 52 3c 90 90 90 90 90 90 90 83 72 + 90 73 90 5a 90 43 90 90 90 90 41 e9 bd 90 b2 d2 + 90 aa a2 90 90 90 90 90 90 90 90 26 90 90 8a 90 + 90 90 90 90 90 90 90 18 90 9d 90 90 90 5d 90 46 + 90 90 90 f6 c3 a3 1e 07 5f 81 90 0c 90 b8 90 75 + 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 79 + 90 5e 90 90 06 90 ff 90 5b 24 90 2b 90 90 90 02 + 86 90 90 fb 90 90 50 fc 08 90 90 90 03 90 b9 90 + 90 bc e8 1f fa 42 90 90 89 90 23 87 90 2a 90 90 + 8b 90 f3 ea 04 2c b5 90 0a 90 51 90 90 3a 90 9c + 90 90 78 90 ba 90 90 90 90 90 90 90 d0 56 90 90 + + + + 05 08 00 00 + + + + + + 00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e a6 ad 00 ec 00 4f + + + + \ No newline at end of file diff --git a/pkg/meta/In The Hunt (World).mra b/pkg/meta/In The Hunt (World).mra new file mode 100644 index 0000000..0595586 --- /dev/null +++ b/pkg/meta/In The Hunt (World).mra @@ -0,0 +1,102 @@ + + In The Hunt (World) + 0245 + inthunt + 1993 + Irem + Shooter + IremM92 + horizontal + + 2 + 8-way + 2 + + + + + + + + + + + + + + + + + 00 + + + 00 0c 00 00 + + + + + + + + + + + 01 20 00 00 + + + + + + + + + 02 40 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 1f 90 bb 50 90 58 42 57 90 90 e9 90 90 90 90 0b + 90 90 9d 9c 90 90 1e 90 90 b4 5b 90 90 90 90 90 + 90 90 78 c7 90 90 83 90 90 0c b0 04 90 90 90 90 + 90 90 90 90 3b c3 b5 47 90 90 90 90 59 90 90 90 + 90 90 90 38 90 90 90 90 5f a3 fa 90 e8 36 75 90 + 88 33 90 90 90 90 43 90 90 87 90 90 90 90 90 90 + 90 90 90 90 8e f3 56 90 90 90 90 26 ff 90 90 90 + 90 90 90 2a 90 8a 90 18 90 90 03 89 24 90 90 90 + 0a 90 eb 90 86 90 90 90 79 3a 90 90 90 90 a0 90 + ea 90 90 90 90 90 2c 90 c6 90 90 46 90 aa b6 5e + 90 90 90 90 8b 90 90 90 90 90 ba 90 b9 53 a2 90 + 90 07 90 90 90 3c 32 90 2b 90 b8 90 90 90 90 90 + bd 90 90 90 90 81 90 d0 08 90 55 06 cf 90 90 fc + 90 90 90 b1 bf 90 90 51 52 90 5d 90 5a 90 b2 90 + fe 90 90 22 20 72 f6 80 02 2e 90 74 0f 90 90 90 + 90 90 90 90 bc 41 90 fb 73 90 90 90 23 d2 90 90 + + + + 05 08 00 00 + + + + + + 00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 01 80 00 d8 00 02 + + + + + \ No newline at end of file diff --git a/pkg/meta/Lethal Thunder (World).mra b/pkg/meta/Lethal Thunder (World).mra new file mode 100644 index 0000000..3b0ce21 --- /dev/null +++ b/pkg/meta/Lethal Thunder (World).mra @@ -0,0 +1,103 @@ + + Lethal Thunder (World) + 0245 + lethalth + 1992 + Irem + Shooter + IremM92 + vertical + + 8-way + 2 + + + + + + + + + + + + + + + + 01 + + + + 10 + + + 00 08 00 00 + + + + + + + + + + + 01 10 00 00 + + + + + + + + + 02 10 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 7f 26 5d 90 ba 90 1e 5e b8 49 bc e8 01 90 4a 25 + 90 bd 90 22 10 90 02 57 70 90 7c 90 e7 52 90 a9 + 90 90 c6 06 a0 fe cf 8e 43 8f 2d 8c d4 85 75 a2 + 3d 90 90 38 7e 89 d1 80 3b 72 07 90 42 37 0a 18 + 88 b4 98 8b b9 9c ad 0e 2b 90 bf 90 55 90 56 b0 + 93 91 90 eb 90 50 41 29 47 90 90 60 90 ab 90 90 + c3 e2 d0 b2 11 79 90 08 82 fb 90 2c 23 90 28 0d + 90 90 90 83 3c 90 1b 34 5b 90 40 90 90 04 fc cd + b1 f3 8a 90 90 87 90 90 90 90 90 90 be 84 1f e6 + ff 90 12 90 b5 36 90 b3 90 90 90 d2 4e 90 90 90 + a5 90 90 c7 90 27 0b 90 20 90 90 90 90 90 61 7d + 63 90 86 0f 90 b7 90 4f 13 90 c0 fd 90 39 90 77 + 05 3a 90 48 92 71 3e 03 90 f8 90 59 a8 5f f9 bb + 81 fa 9d e9 2e a1 c1 33 90 78 90 0c 90 24 aa ac + 90 b6 90 ea 90 73 e5 58 00 f7 90 74 90 76 90 a3 + 90 5a f6 32 46 2a 90 90 53 4b 90 35 51 68 99 13 + + + + 05 04 00 00 + + + + + + 00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 00 86 00 b7 00 08 + + + + \ No newline at end of file diff --git a/pkg/meta/Major Title 2 (World, set 1).mra b/pkg/meta/Major Title 2 (World, set 1).mra new file mode 100644 index 0000000..4aa7418 --- /dev/null +++ b/pkg/meta/Major Title 2 (World, set 1).mra @@ -0,0 +1,101 @@ + + Major Title 2 (World, set 1) + 0245 + majtitl2 + 1992 + Irem + Sports + IremM92 + horizontal + + 4 + 8-way + 2 + + + + + + + + + + + + + + + + + + + 06 + + + 00 10 00 00 + + + + + + + + + + + 01 10 00 00 + + + + + + + + + 02 40 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 87 90 78 aa 90 90 90 2c 32 0a 0f 90 5e 90 c6 8a + 33 90 90 90 90 ea 90 72 90 90 90 90 90 90 24 55 + 90 90 90 89 fb 90 59 02 90 90 5d 90 90 90 36 90 + 90 06 79 90 90 1e 07 90 90 90 83 90 90 90 90 90 + 9d 90 90 74 90 90 90 0c 58 90 90 90 90 90 90 90 + 3c 90 03 90 90 fa 43 90 bf 90 90 75 90 88 90 80 + 90 a3 90 fe 90 90 90 90 90 90 90 90 3a 90 90 90 + 2b 90 90 90 90 e9 5f 90 46 90 41 90 18 b8 90 90 + b4 5a b1 90 90 50 e8 20 90 b2 90 90 90 90 90 51 + 90 90 90 56 90 90 90 90 90 cf 90 90 90 c3 90 90 + 90 90 90 90 0b 90 90 b5 57 90 90 c7 3b 90 90 90 + 90 90 90 90 b6 90 eb 90 38 90 a0 08 90 86 b0 90 + 42 1f 73 90 f6 90 90 90 53 90 52 90 04 bd 90 90 + 26 ff 2e 90 81 90 47 90 90 90 90 d0 22 90 90 b9 + 23 90 f3 90 90 90 90 90 90 d2 8b ba 90 90 90 5b + 90 90 9c 90 90 90 90 fc bc a2 2a 90 90 8e bb 90 + + + + 05 08 00 00 + + + + 07 00 20 00 + + + + + \ No newline at end of file diff --git a/pkg/meta/Mystic Riders (World).mra b/pkg/meta/Mystic Riders (World).mra new file mode 100644 index 0000000..2727cfc --- /dev/null +++ b/pkg/meta/Mystic Riders (World).mra @@ -0,0 +1,101 @@ + + Mystic Riders (World) + 0245 + mysticri + 1992 + Irem + Shooter + IremM92 + horizontal + + 8-way + 2 + + + + + + + + + + + + + + + + + 00 + + + 00 0a 00 00 + + + + + + + + + + + 01 10 00 00 + + + + + + + + + 02 20 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 90 57 90 90 90 90 90 90 bf 43 90 90 b3 90 fc 90 + 90 90 90 90 90 52 a3 26 90 c7 90 0f 90 0c 90 90 + 90 90 ff 90 90 02 90 90 2e 90 5f 90 90 90 73 50 + b2 3a 90 90 bb 90 90 90 90 90 90 90 90 90 90 90 + 90 90 8e 3c 42 90 90 b9 90 90 2a 90 47 a0 2b 03 + b5 1f 90 aa 90 fb 90 90 90 90 90 90 38 90 90 90 + 2c 90 90 c6 90 90 b1 90 90 90 90 90 90 90 a2 90 + e9 e8 90 90 86 90 8b 90 90 90 90 90 5b 72 90 90 + 90 90 5d 0a 90 90 89 90 b0 88 90 b7 90 87 75 bd + 90 51 90 90 90 90 90 be 90 90 90 5a 58 90 90 56 + 90 8a 90 55 90 90 90 b4 08 90 f6 90 90 9d 90 bc + 0b 00 90 5e 90 90 90 22 36 4b 1e 90 b6 ba 23 90 + 20 90 90 90 59 53 90 04 81 90 90 f3 90 90 3b 06 + e2 79 83 9c 90 18 80 90 c3 90 90 90 32 90 cf 90 + eb 90 90 33 90 fa 90 90 d2 90 24 90 74 41 b8 90 + 34 90 d0 07 f8 90 90 90 90 46 90 ea fe 78 90 90 + + + + 05 04 00 00 + + + + + + 00 00 00 0F 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 8a f8 00 38 00 4d + 00 0e 8b 30 00 94 2e 00 + + + + \ No newline at end of file diff --git a/pkg/meta/Ninja Baseball Bat Man (World).mra b/pkg/meta/Ninja Baseball Bat Man (World).mra new file mode 100644 index 0000000..8ed7548 --- /dev/null +++ b/pkg/meta/Ninja Baseball Bat Man (World).mra @@ -0,0 +1,103 @@ + + Ninja Baseball Bat Man (World) + 0245 + nbbatman + 1993 + Irem + Fighter + IremM92 + horizontal + + 4 + 8-way + 2 + + + + + + + + + + + + + + + + + + + 06 + + + 00 10 00 00 + + + + + + + + + + + 01 20 00 00 + + + + + + + + + 02 40 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 90 90 90 55 bb 90 23 79 90 90 90 90 90 90 38 90 + f7 90 90 90 90 90 90 90 3d 90 90 90 ba 90 1e 90 + 2c 46 90 b5 90 4b 90 fe 90 90 fb 2e 90 90 36 04 + cf 90 f3 5a 8a 0c 9c 90 90 90 b2 50 90 90 90 5f + 90 90 24 90 90 41 2b 90 e9 90 08 3b 90 90 90 90 + 90 d2 51 90 90 90 22 90 eb 3a 5b a2 b1 80 90 90 + 90 90 90 90 59 b4 88 90 90 bf d1 90 b9 57 90 90 + 72 90 73 90 90 90 90 0f 90 90 90 90 56 90 90 c6 + 90 90 90 90 90 2a 8e 90 81 a3 58 90 aa 78 89 90 + 90 90 90 90 90 90 bd 90 90 90 ff 90 90 90 07 53 + a0 90 90 5e b0 90 83 f6 90 26 32 90 90 90 74 0a + 18 90 90 90 75 03 90 90 b6 02 90 90 43 90 b8 90 + e8 90 fc 90 20 c3 90 06 90 1f 86 00 90 90 90 d0 + 47 90 87 90 90 9d 3c c7 90 90 90 90 90 90 90 90 + 90 90 90 8b 90 90 33 90 90 90 90 90 fa 42 90 90 + 90 90 90 ea 90 52 90 5d 90 90 90 90 bc 90 90 90 + + + + 05 08 00 00 + + + + + + 00 00 00 0F 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 25 d4 00 4f 00 03 + + + + \ No newline at end of file diff --git a/pkg/meta/R-Type Leo (World).mra b/pkg/meta/R-Type Leo (World).mra new file mode 100644 index 0000000..f23fc71 --- /dev/null +++ b/pkg/meta/R-Type Leo (World).mra @@ -0,0 +1,101 @@ + + R-Type Leo (World) + 0245 + rtypeleo + 1992 + Irem + Shooter + IremM92 + horizontal + + 2 + 8-way + 2 + + + + + + + + + + + + + + + + 00 + + + 00 0c 00 00 + + + + + + + + + + + 01 20 00 00 + + + + + + + + + 02 40 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 5d 90 c6 90 90 90 2a 3a 90 90 90 86 90 22 90 f3 + 90 90 90 90 90 38 f7 42 04 90 90 1f 4b 90 90 58 + 57 2e 90 90 53 90 b9 90 90 90 90 90 20 55 90 3d + a0 90 90 0c 03 90 83 90 90 90 8a 00 90 aa 90 90 + 90 90 90 90 90 90 90 90 90 41 0a 26 8b 56 5e 90 + 90 74 90 90 90 90 06 90 90 89 5b c7 43 90 90 90 + 90 b6 90 3b 90 90 90 90 90 36 ea 80 90 90 90 5f + 90 0f 90 90 90 46 90 90 3c 8e 90 a3 87 90 90 90 + 2b fb 47 0b 90 fc 02 90 90 90 90 90 90 90 72 2c + 33 90 90 90 90 90 9d bd 90 b2 90 78 75 b8 90 90 + 90 90 90 90 cf 5a 88 90 90 90 c3 90 eb fa 90 32 + 90 90 90 52 b4 90 90 90 90 bc 90 90 90 b1 59 50 + 90 90 b5 90 08 a2 bf bb 1e 9c 90 73 90 d0 90 90 + 90 90 90 90 81 90 79 90 90 24 23 90 90 b0 07 ff + 90 ba f6 51 90 90 90 fe 90 92 90 90 90 90 e9 90 + 90 90 90 90 90 90 e8 d2 90 18 90 90 90 d1 90 90 + + + + 05 08 00 00 + + + + + + 00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 22 1e 00 38 40 20 + 00 0e 22 56 00 03 40 01 + + + + \ No newline at end of file diff --git a/pkg/meta/Superior Soldiers (US).mra b/pkg/meta/Superior Soldiers (US).mra new file mode 100644 index 0000000..6dec834 --- /dev/null +++ b/pkg/meta/Superior Soldiers (US).mra @@ -0,0 +1,101 @@ + + Superior Soldiers (US) + 0245 + ssoldier + 1993 + Irem + Fighter + IremM92 + horizontal + + 8-way + 6 + + + + + + + + + + + + + + 40 + + + 00 0c 00 00 + + + + + + + + + + + 01 10 00 00 + + + + + + + + + 06 80 00 00 + + + + + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 90 90 90 8a 90 aa 90 90 90 20 23 55 90 b5 0a 90 + 90 46 90 b6 90 74 8b 90 90 ba f7 90 90 5a 86 fb + b2 90 b0 90 42 06 1e 08 22 9d 90 90 90 90 90 73 + 90 90 5f 90 90 d0 90 ff 90 90 bd 90 03 90 b9 90 + 90 90 90 51 5e 24 90 90 90 90 90 58 59 90 90 90 + 52 90 90 90 a0 90 90 02 d2 90 79 26 3a 0f cf b4 + f3 90 90 50 90 75 b1 90 d1 47 90 90 90 90 90 90 + c6 90 90 90 90 90 bc 90 90 90 90 90 53 41 90 90 + 90 90 90 90 90 90 04 90 90 90 90 2c 90 bf 90 90 + 90 90 e8 90 90 78 90 bb 90 90 1f 2b 87 90 4b 56 + 36 33 90 90 90 9c c3 90 90 81 90 e9 90 fa 90 90 + 90 72 90 a2 90 90 c7 90 90 92 90 90 88 90 90 90 + 3b 90 0c 90 80 90 90 90 90 2e 90 90 90 57 90 8e + 07 90 a3 90 90 90 3d 90 fe 90 90 fc ea 90 38 90 + 3c f6 90 90 90 18 90 90 b8 90 90 90 2a 5d 5b 90 + 90 43 32 90 90 90 eb 90 90 90 90 90 83 89 90 90 + + + + 05 08 00 00 + + + + + + 00 00 0F 00 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 1b 0f 00 31 10 31 + + + + \ No newline at end of file diff --git a/pkg/meta/Undercover Cops (World).mra b/pkg/meta/Undercover Cops (World).mra new file mode 100644 index 0000000..8ca9378 --- /dev/null +++ b/pkg/meta/Undercover Cops (World).mra @@ -0,0 +1,103 @@ + + Undercover Cops (World) + 0245 + uccops + 1992 + Irem + Fighter + IremM92 + horizontal + + 3 + 8-way + 2 + + + + + + + + + + + + + + + + + + + 00 + + + 00 0c 00 00 + + + + + + + + + + + 01 20 00 00 + + + + + + + + + 02 40 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 1f 51 84 90 3d 09 0d 90 90 57 90 90 90 32 11 90 + 90 9c 90 90 4b 90 90 03 90 90 90 89 b0 90 90 90 + 90 bb 18 be 53 21 55 7c 90 90 47 58 f6 90 90 b2 + 06 90 2b 90 2f 0b fc 91 90 90 fa 81 83 40 38 90 + 90 90 49 85 d1 f5 07 e2 5e 1e 90 04 90 90 90 b1 + c7 90 96 f2 b6 d2 c3 90 87 ba cb 88 90 b9 d0 b5 + 9a 80 a2 72 90 b4 90 aa 26 7d 52 33 2e bc 08 79 + 48 90 76 36 02 90 5b 12 8b e7 90 90 90 ab 90 4f + 90 90 a8 e5 39 0e a9 90 90 14 90 ff 7f 90 90 27 + 90 01 90 90 e6 8a d3 90 90 8e 56 a5 92 90 90 f9 + 22 90 5f 90 90 a1 90 74 b8 90 46 05 eb cf bf 5d + 24 90 9d 90 90 90 90 90 59 8d 3c f8 c5 90 f3 4e + 90 90 50 c6 e9 fe 0a 90 99 86 90 90 af 8c 42 f7 + 90 41 90 a3 90 3a 2a 43 90 b3 e8 90 c4 35 78 25 + 75 90 b7 90 23 90 90 8f 90 90 2c 90 77 7e 90 0f + 0c a0 bd 90 90 2d 29 ea 90 3b 73 90 fb 20 90 5a + + + + 05 08 00 00 + + + + + + 00 00 00 0F 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 3e 9a 00 49 30 01 + + + + \ No newline at end of file diff --git a/pkg/meta/Undercover Cops - Alpha Renewal Version (World).mra b/pkg/meta/Undercover Cops - Alpha Renewal Version (World).mra new file mode 100644 index 0000000..c5e66ef --- /dev/null +++ b/pkg/meta/Undercover Cops - Alpha Renewal Version (World).mra @@ -0,0 +1,104 @@ + + Undercover Cops - Alpha Renewal Version (World) + 0245 + uccopsar + uccops + 1992 + Irem + Fighter + IremM92 + horizontal + + 3 + 8-way + 2 + + + + + + + + + + + + + + + + + + + 00 + + + 00 0c 00 00 + + + + + + + + + + + 01 20 00 00 + + + + + + + + + 02 40 00 00 + + + + + + + + + 03 02 00 00 + + + + + + + 04 00 01 00 + + 1f 51 84 90 3d 09 0d 90 90 57 90 90 90 32 11 90 + 90 9c 90 90 4b 90 90 03 90 90 90 89 b0 90 90 90 + 90 bb 18 be 53 21 55 7c 90 90 47 58 f6 90 90 b2 + 06 90 2b 90 2f 0b fc 91 90 90 fa 81 83 40 38 90 + 90 90 49 85 d1 f5 07 e2 5e 1e 90 04 90 90 90 b1 + c7 90 96 f2 b6 d2 c3 90 87 ba cb 88 90 b9 d0 b5 + 9a 80 a2 72 90 b4 90 aa 26 7d 52 33 2e bc 08 79 + 48 90 76 36 02 90 5b 12 8b e7 90 90 90 ab 90 4f + 90 90 a8 e5 39 0e a9 90 90 14 90 ff 7f 90 90 27 + 90 01 90 90 e6 8a d3 90 90 8e 56 a5 92 90 90 f9 + 22 90 5f 90 90 a1 90 74 b8 90 46 05 eb cf bf 5d + 24 90 9d 90 90 90 90 90 59 8d 3c f8 c5 90 f3 4e + 90 90 50 c6 e9 fe 0a 90 99 86 90 90 af 8c 42 f7 + 90 41 90 a3 90 3a 2a 43 90 b3 e8 90 c4 35 78 25 + 75 90 b7 90 23 90 90 8f 90 90 2c 90 77 7e 90 0f + 0c a0 bd 90 90 2d 29 ea 90 3b 73 90 fb 20 90 5a + + + + 05 08 00 00 + + + + + + 00 00 00 0F 05 FF 00 01 00 0F 00 01 00 01 02 00 + 00 0e 3e 7c 00 49 30 01 + + + + \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/common/.gitkeep b/pkg/pocket/Assets/irem_m92/common/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/pkg/pocket/Assets/irem_m92/common/bmaster.dat b/pkg/pocket/Assets/irem_m92/common/bmaster.dat new file mode 100644 index 0000000..3c3b5f3 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/bmaster.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/dsocc94j.dat b/pkg/pocket/Assets/irem_m92/common/dsocc94j.dat new file mode 100644 index 0000000..b01a2ac Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/dsocc94j.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/gunforc2.dat b/pkg/pocket/Assets/irem_m92/common/gunforc2.dat new file mode 100644 index 0000000..d47f308 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/gunforc2.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/gunforce.dat b/pkg/pocket/Assets/irem_m92/common/gunforce.dat new file mode 100644 index 0000000..2936539 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/gunforce.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/hook.dat b/pkg/pocket/Assets/irem_m92/common/hook.dat new file mode 100644 index 0000000..df26ad7 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/hook.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/inthunt.dat b/pkg/pocket/Assets/irem_m92/common/inthunt.dat new file mode 100644 index 0000000..7074b26 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/inthunt.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/lethalth.dat b/pkg/pocket/Assets/irem_m92/common/lethalth.dat new file mode 100644 index 0000000..8696d84 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/lethalth.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/mysticri.dat b/pkg/pocket/Assets/irem_m92/common/mysticri.dat new file mode 100644 index 0000000..4b8e0b0 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/mysticri.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/nbbatman.dat b/pkg/pocket/Assets/irem_m92/common/nbbatman.dat new file mode 100644 index 0000000..1294328 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/nbbatman.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/rtypeleo.dat b/pkg/pocket/Assets/irem_m92/common/rtypeleo.dat new file mode 100644 index 0000000..634bfdc Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/rtypeleo.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/ssoldier.dat b/pkg/pocket/Assets/irem_m92/common/ssoldier.dat new file mode 100644 index 0000000..1f5dfe6 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/ssoldier.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/uccops.dat b/pkg/pocket/Assets/irem_m92/common/uccops.dat new file mode 100644 index 0000000..ac70198 Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/uccops.dat differ diff --git a/pkg/pocket/Assets/irem_m92/common/uccopsar.dat b/pkg/pocket/Assets/irem_m92/common/uccopsar.dat new file mode 100644 index 0000000..4be99be Binary files /dev/null and b/pkg/pocket/Assets/irem_m92/common/uccopsar.dat differ diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Blade Master (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Blade Master (World).json new file mode 100644 index 0000000..05fe475 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Blade Master (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "bmaster.rom", + "md5": "3d990e8a82b4b4f3453db6c7e6b6fa28" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 128 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json new file mode 100644 index 0000000..4905e45 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "dsocc94j.rom", + "md5": "02104821048467efb72618d3d25f025a" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 128 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Gun Force II (US).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Gun Force II (US).json new file mode 100644 index 0000000..c0ae9d4 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Gun Force II (US).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "gunforc2.rom", + "md5": "3aec0fc380c8d3a752395308c1a0e190" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 75 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json new file mode 100644 index 0000000..18e866c --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "gunforce.rom", + "md5": "8e6d7cf6b725502bb2a523a870eb4492" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 64 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Hook (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Hook (World).json new file mode 100644 index 0000000..6d3a7f8 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Hook (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "hook.rom", + "md5": "b36fe68ea8f68f6a65d139688b338106" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 236 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/In The Hunt (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/In The Hunt (World).json new file mode 100644 index 0000000..fbba242 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/In The Hunt (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "inthunt.rom", + "md5": "e43a428daf2fc8294721fd49ab58beec" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 216 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json new file mode 100644 index 0000000..9872369 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "lethalth.rom", + "md5": "7950cdb14c48c4f3d2f846524ae3c15b" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x01" + }, + { + "address": "0xF5000000", + "data": 183 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json new file mode 100644 index 0000000..23d3848 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json @@ -0,0 +1,26 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "majtitl2.rom", + "md5": "3d05124b8a4bb4e4b3ab386b82bced4e" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Mystic Riders (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Mystic Riders (World).json new file mode 100644 index 0000000..22adcda --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Mystic Riders (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "mysticri.rom", + "md5": "355094b8c099ed8605e4d69d91b15010" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 204 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json new file mode 100644 index 0000000..ab2c05a --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "nbbatman.rom", + "md5": "d520a1e042076300efb0b2c8764332a0" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 79 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/R-Type Leo (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/R-Type Leo (World).json new file mode 100644 index 0000000..bdb314b --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/R-Type Leo (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "rtypeleo.rom", + "md5": "ee396c8392b84ed8192428a2125933c2" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 59 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json new file mode 100644 index 0000000..16ad857 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "ssoldier.rom", + "md5": "45e5f8de4840617ddcac19263722c43c" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 49 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Undercover Cops (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Undercover Cops (World).json new file mode 100644 index 0000000..27bbbe4 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Undercover Cops (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "uccops.rom", + "md5": "e4b04f7cf5def3afbe4bd96584660431" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 73 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json new file mode 100644 index 0000000..ac88682 --- /dev/null +++ b/pkg/pocket/Assets/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json @@ -0,0 +1,30 @@ +{ + "instance": { + "magic": "APF_VER_1", + "variant_select": { + "id": 777, + "select": false + }, + "data_slots": [ + { + "id": 1, + "filename": "uccopsar.rom", + "md5": "3be9f2193a00951864d9517804f34a37" + } + ], + "memory_writes": [ + { + "address": "0xF1000000", + "data": "0x00000000" + }, + { + "address": "0xF2000000", + "data": "0x00" + }, + { + "address": "0xF5000000", + "data": 73 + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Cores/opengateware.irem_m92/audio.json b/pkg/pocket/Cores/opengateware.irem_m92/audio.json new file mode 100644 index 0000000..ea8e2f4 --- /dev/null +++ b/pkg/pocket/Cores/opengateware.irem_m92/audio.json @@ -0,0 +1,5 @@ +{ + "audio": { + "magic": "APF_VER_1" + } +} \ No newline at end of file diff --git a/pkg/pocket/Cores/opengateware.irem_m92/core.json b/pkg/pocket/Cores/opengateware.irem_m92/core.json new file mode 100644 index 0000000..d1c1c66 --- /dev/null +++ b/pkg/pocket/Cores/opengateware.irem_m92/core.json @@ -0,0 +1,36 @@ +{ + "core": { + "magic": "APF_VER_1", + "metadata": { + "platform_ids": [ + "irem_m92" + ], + "shortname": "irem_m92", + "description": "Irem M-92 Arcade Compatible Gateware IP Core", + "author": "opengateware", + "url": "https://github.com/opengateware/arcade-irem_m92", + "version": "0.1.0", + "date_release": "2024-04-18" + }, + "framework": { + "target_product": "Analogue Pocket", + "version_required": "1.1", + "sleep_supported": false, + "dock": { + "supported": true, + "analog_output": false + }, + "hardware": { + "link_port": false, + "cartridge_adapter": -1 + } + }, + "cores": [ + { + "name": "default", + "id": 0, + "filename": "bitstream.rbf_r" + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Cores/opengateware.irem_m92/data.json b/pkg/pocket/Cores/opengateware.irem_m92/data.json new file mode 100644 index 0000000..d170e92 --- /dev/null +++ b/pkg/pocket/Cores/opengateware.irem_m92/data.json @@ -0,0 +1,26 @@ +{ + "data": { + "magic": "APF_VER_1", + "data_slots": [ + { + "name": "Arcade Game", + "id": 0, + "required": true, + "parameters": "0x113", + "extensions": [ + "json" + ] + }, + { + "name": "ROM", + "id": 1, + "required": true, + "parameters": "0x0", + "extensions": [ + "rom" + ], + "address": "0x00000000" + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Cores/opengateware.irem_m92/icon.bin b/pkg/pocket/Cores/opengateware.irem_m92/icon.bin new file mode 100644 index 0000000..cb4e46d Binary files /dev/null and b/pkg/pocket/Cores/opengateware.irem_m92/icon.bin differ diff --git a/pkg/pocket/Cores/opengateware.irem_m92/icon.png b/pkg/pocket/Cores/opengateware.irem_m92/icon.png new file mode 100644 index 0000000..255e6ec Binary files /dev/null and b/pkg/pocket/Cores/opengateware.irem_m92/icon.png differ diff --git a/pkg/pocket/Cores/opengateware.irem_m92/info.txt b/pkg/pocket/Cores/opengateware.irem_m92/info.txt new file mode 100644 index 0000000..6555a71 --- /dev/null +++ b/pkg/pocket/Cores/opengateware.irem_m92/info.txt @@ -0,0 +1,3 @@ +Launched by Irem in 1991, the M92 was an advanced arcade system that offered robust graphics and sound capabilities. + +The M92 system was known for its cutting-edge graphical and sound technologies that enhanced the arcade gaming experience, paving the way for future innovations in the industry. The diverse array of games it supported showcased the hardware's capabilities, making it a popular choice for arcade operators and a fond memory for gamers. \ No newline at end of file diff --git a/pkg/pocket/Cores/opengateware.irem_m92/input.json b/pkg/pocket/Cores/opengateware.irem_m92/input.json new file mode 100644 index 0000000..e17d441 --- /dev/null +++ b/pkg/pocket/Cores/opengateware.irem_m92/input.json @@ -0,0 +1,5 @@ +{ + "input": { + "magic": "APF_VER_1" + } +} \ No newline at end of file diff --git a/pkg/pocket/Cores/opengateware.irem_m92/interact.json b/pkg/pocket/Cores/opengateware.irem_m92/interact.json new file mode 100644 index 0000000..f061588 --- /dev/null +++ b/pkg/pocket/Cores/opengateware.irem_m92/interact.json @@ -0,0 +1,7 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Cores/opengateware.irem_m92/variants.json b/pkg/pocket/Cores/opengateware.irem_m92/variants.json new file mode 100644 index 0000000..c2dbd41 --- /dev/null +++ b/pkg/pocket/Cores/opengateware.irem_m92/variants.json @@ -0,0 +1,6 @@ +{ + "variants": { + "magic": "APF_VER_1", + "variant_list": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Cores/opengateware.irem_m92/video.json b/pkg/pocket/Cores/opengateware.irem_m92/video.json new file mode 100644 index 0000000..94b8bdd --- /dev/null +++ b/pkg/pocket/Cores/opengateware.irem_m92/video.json @@ -0,0 +1,39 @@ +{ + "video": { + "magic": "APF_VER_1", + "scaler_modes": [ + { + "width": 320, + "height": 240, + "aspect_w": 4, + "aspect_h": 3, + "rotation": 0, + "mirror": 0 + }, + { + "width": 320, + "height": 240, + "aspect_w": 4, + "aspect_h": 3, + "rotation": 270, + "mirror": 0 + } + ], + "display_modes": [ + { "id": "0x10" }, + { "id": "0x20" }, + { "id": "0x21" }, + { "id": "0x22" }, + { "id": "0x23" }, + { "id": "0x30" }, + { "id": "0x31" }, + { "id": "0x32" }, + { "id": "0x40" }, + { "id": "0x41" }, + { "id": "0x42" }, + { "id": "0xe0" }, + { "id": "0x52" }, + { "id": "0x51" } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Platforms/_images/irem_m92.bin b/pkg/pocket/Platforms/_images/irem_m92.bin new file mode 100644 index 0000000..e608e0c Binary files /dev/null and b/pkg/pocket/Platforms/_images/irem_m92.bin differ diff --git a/pkg/pocket/Platforms/_images/irem_m92.png b/pkg/pocket/Platforms/_images/irem_m92.png new file mode 100644 index 0000000..65a084d Binary files /dev/null and b/pkg/pocket/Platforms/_images/irem_m92.png differ diff --git a/pkg/pocket/Platforms/irem_m92.json b/pkg/pocket/Platforms/irem_m92.json new file mode 100644 index 0000000..27da8fc --- /dev/null +++ b/pkg/pocket/Platforms/irem_m92.json @@ -0,0 +1,8 @@ +{ + "platform": { + "category": "Arcade", + "name": "Irem M92", + "manufacturer": "Irem", + "year": 1991 + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Blade Master (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Blade Master (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Blade Master (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Gun Force II (US).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Gun Force II (US).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Gun Force II (US).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Hook (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Hook (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Hook (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/In The Hunt (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/In The Hunt (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/In The Hunt (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Mystic Riders (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Mystic Riders (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Mystic Riders (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/R-Type Leo (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/R-Type Leo (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/R-Type Leo (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json new file mode 100644 index 0000000..0de17d0 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json @@ -0,0 +1,54 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 6, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 2, + "name": "Button 3", + "key": "pad_btn_y" + }, + { + "id": 3, + "name": "Button 4", + "key": "pad_btn_x" + }, + { + "id": 4, + "name": "Button 5", + "key": "pad_trig_l" + }, + { + "id": 5, + "name": "Button 6", + "key": "pad_trig_r" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Undercover Cops (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Undercover Cops (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Undercover Cops (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json new file mode 100644 index 0000000..42b40a6 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Input/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json @@ -0,0 +1,34 @@ +{ + "input": { + "magic": "APF_VER_1", + "controllers": [ + { + "type": "default", + "buttons": 2, + "ways": 8, + "mappings": [ + { + "id": 0, + "name": "Button 1", + "key": "pad_btn_a" + }, + { + "id": 1, + "name": "Button 2", + "key": "pad_btn_b" + }, + { + "id": 20, + "name": "Start", + "key": "pad_btn_start" + }, + { + "id": 21, + "name": "Coin", + "key": "pad_btn_select" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Blade Master (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Blade Master (World).json new file mode 100644 index 0000000..a5f8ba1 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Blade Master (World).json @@ -0,0 +1,256 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "2", + "value": "0x00000000" + }, + { + "name": "3", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "1", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Bonus Life", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFEF", + "options": [ + { + "name": "300k", + "value": "0x00000000" + }, + { + "name": "None", + "value": "0x00000010" + } + ] + }, + { + "name": "Allow Continue", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Yes", + "value": "0x00000000" + }, + { + "name": "No", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json new file mode 100644 index 0000000..f57fc0d --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Dream Soccer '94 (Japan, M92 hardware).json @@ -0,0 +1,285 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Time", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "2:00", + "value": "0x00000000" + }, + { + "name": "2:30", + "value": "0x00000001" + }, + { + "name": "3:00", + "value": "0x00000002" + }, + { + "name": "1:30", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Game Mode", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFEF", + "options": [ + { + "name": "Match Mode", + "value": "0x00000000" + }, + { + "name": "Power Mode", + "value": "0x00000010" + } + ] + }, + { + "name": "Starting Button", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Start", + "value": "0x00000000" + }, + { + "name": "Button 1", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + }, + { + "name": "Player Power", + "port": "DSW", + "id": 9, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFCFFFF", + "options": [ + { + "name": "1000", + "value": "0x00000000" + }, + { + "name": "2000", + "value": "0x00010000" + }, + { + "name": "1500", + "value": "0x00020000" + }, + { + "name": "500", + "value": "0x00030000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Gun Force II (US).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Gun Force II (US).json new file mode 100644 index 0000000..4c77b34 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Gun Force II (US).json @@ -0,0 +1,235 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "2", + "value": "0x00000000" + }, + { + "name": "3", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "1", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Allow Continue", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Yes", + "value": "0x00000000" + }, + { + "name": "No", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json new file mode 100644 index 0000000..a27086c --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Gunforce - Battle Fire Engulfed Terror Island (World).json @@ -0,0 +1,256 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "3", + "value": "0x00000000" + }, + { + "name": "2", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "5", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Bonus Life", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFEF", + "options": [ + { + "name": "20k/40k/90k/150k", + "value": "0x00000000" + }, + { + "name": "15k/35k/75k/120k", + "value": "0x00000010" + } + ] + }, + { + "name": "Allow Continue", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Yes", + "value": "0x00000000" + }, + { + "name": "No", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Hook (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Hook (World).json new file mode 100644 index 0000000..dc0a6d7 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Hook (World).json @@ -0,0 +1,256 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "2", + "value": "0x00000000" + }, + { + "name": "3", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "1", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Start Button", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Start", + "value": "0x00000000" + }, + { + "name": "Any", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Cabinet", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFDFF", + "options": [ + { + "name": "2 Players", + "value": "0x00000000" + }, + { + "name": "4 Players", + "value": "0x00000200" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/In The Hunt (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/In The Hunt (World).json new file mode 100644 index 0000000..4940d58 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/In The Hunt (World).json @@ -0,0 +1,235 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "3", + "value": "0x00000000" + }, + { + "name": "2", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "5", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Start Button", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Start", + "value": "0x00000000" + }, + { + "name": "Any", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json new file mode 100644 index 0000000..c145d24 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Lethal Thunder (World).json @@ -0,0 +1,264 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "3", + "value": "0x00000000" + }, + { + "name": "2", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "5", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Bonus Life", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFCFFFF", + "options": [ + { + "name": "700k/1.5M", + "value": "0x00000000" + }, + { + "name": "500k/1M", + "value": "0x00010000" + }, + { + "name": "1M/2M", + "value": "0x00020000" + }, + { + "name": "700k/1.5M/3M/4.5M", + "value": "0x00030000" + } + ] + }, + { + "name": "Allow Continue", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Yes", + "value": "0x00000000" + }, + { + "name": "No", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json new file mode 100644 index 0000000..dc0a6d7 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Major Title 2 (World, set 1).json @@ -0,0 +1,256 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "2", + "value": "0x00000000" + }, + { + "name": "3", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "1", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Start Button", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Start", + "value": "0x00000000" + }, + { + "name": "Any", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Cabinet", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFDFF", + "options": [ + { + "name": "2 Players", + "value": "0x00000000" + }, + { + "name": "4 Players", + "value": "0x00000200" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Mystic Riders (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Mystic Riders (World).json new file mode 100644 index 0000000..074aa62 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Mystic Riders (World).json @@ -0,0 +1,256 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "3", + "value": "0x00000000" + }, + { + "name": "2", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "5", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Bonus Life", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFEF", + "options": [ + { + "name": "20k/50k/90k", + "value": "0x00000000" + }, + { + "name": "15k/35k/60k", + "value": "0x00000010" + } + ] + }, + { + "name": "Allow Continue", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Yes", + "value": "0x00000000" + }, + { + "name": "No", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json new file mode 100644 index 0000000..dc0a6d7 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Ninja Baseball Bat Man (World).json @@ -0,0 +1,256 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "2", + "value": "0x00000000" + }, + { + "name": "3", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "1", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Start Button", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Start", + "value": "0x00000000" + }, + { + "name": "Any", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Cabinet", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFDFF", + "options": [ + { + "name": "2 Players", + "value": "0x00000000" + }, + { + "name": "4 Players", + "value": "0x00000200" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/R-Type Leo (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/R-Type Leo (World).json new file mode 100644 index 0000000..21e34c9 --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/R-Type Leo (World).json @@ -0,0 +1,235 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "3", + "value": "0x00000000" + }, + { + "name": "2", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "5", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Allow Continue", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Yes", + "value": "0x00000000" + }, + { + "name": "No", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json new file mode 100644 index 0000000..0f04d1e --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Superior Soldiers (US).json @@ -0,0 +1,177 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Start Button", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Start", + "value": "0x00000000" + }, + { + "name": "Any", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Undercover Cops (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Undercover Cops (World).json new file mode 100644 index 0000000..3cb092e --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Undercover Cops (World).json @@ -0,0 +1,256 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "2", + "value": "0x00000000" + }, + { + "name": "3", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "1", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Start Button", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Start", + "value": "0x00000000" + }, + { + "name": "Any", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Cabinet", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFDFF", + "options": [ + { + "name": "2 Players", + "value": "0x00000000" + }, + { + "name": "3 Players", + "value": "0x00000200" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json new file mode 100644 index 0000000..3cb092e --- /dev/null +++ b/pkg/pocket/Presets/opengateware.irem_m92/Interact/irem_m92/opengateware.irem_m92/Undercover Cops - Alpha Renewal Version (World).json @@ -0,0 +1,256 @@ +{ + "interact": { + "magic": "APF_VER_1", + "variables": [ + { + "name": "Reset Core", + "id": 0, + "type": "action", + "enabled": true, + "address": "0xF0000000", + "value": 1 + }, + { + "name": "Lives", + "port": "DSW", + "id": 1, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFFC", + "options": [ + { + "name": "2", + "value": "0x00000000" + }, + { + "name": "3", + "value": "0x00000001" + }, + { + "name": "4", + "value": "0x00000002" + }, + { + "name": "1", + "value": "0x00000003" + } + ] + }, + { + "name": "Difficulty", + "port": "DSW", + "id": 2, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFF3", + "options": [ + { + "name": "Normal", + "value": "0x00000000" + }, + { + "name": "Easy", + "value": "0x00000004" + }, + { + "name": "Hard", + "value": "0x00000008" + }, + { + "name": "Very Easy", + "value": "0x0000000C" + } + ] + }, + { + "name": "Start Button", + "port": "DSW", + "id": 3, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFDF", + "options": [ + { + "name": "Start", + "value": "0x00000000" + }, + { + "name": "Any", + "value": "0x00000020" + } + ] + }, + { + "name": "Demo Sounds", + "port": "DSW", + "id": 4, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFFBF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000040" + } + ] + }, + { + "name": "Service Mode", + "port": "DSW", + "id": 5, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFF7F", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000080" + } + ] + }, + { + "name": "Flip Screen", + "port": "DSW", + "id": 6, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFEFF", + "options": [ + { + "name": "Off", + "value": "0x00000000" + }, + { + "name": "On", + "value": "0x00000100" + } + ] + }, + { + "name": "Cabinet", + "port": "DSW", + "id": 7, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFFFDFF", + "options": [ + { + "name": "2 Players", + "value": "0x00000000" + }, + { + "name": "3 Players", + "value": "0x00000200" + } + ] + }, + { + "name": "Coin Mode", + "port": "DSW", + "id": 8, + "type": "list", + "enabled": true, + "persist": true, + "address": "0xF1000000", + "defaultval": 0, + "mask": "0xFFFF0FFF", + "options": [ + { + "name": "1C/1C", + "value": "0x00000000" + }, + { + "name": "2C/1C", + "value": "0x00001000" + }, + { + "name": "3C/1C", + "value": "0x00002000" + }, + { + "name": "4C/1C", + "value": "0x00003000" + }, + { + "name": "5C/1C", + "value": "0x00004000" + }, + { + "name": "6C/1C", + "value": "0x00005000" + }, + { + "name": "1C/2C", + "value": "0x00006000" + }, + { + "name": "1C/3C", + "value": "0x00007000" + }, + { + "name": "1C/4C", + "value": "0x00008000" + }, + { + "name": "1C/5C", + "value": "0x00009000" + }, + { + "name": "1C/6C", + "value": "0x0000A000" + }, + { + "name": "2C/3C", + "value": "0x0000B000" + }, + { + "name": "3C/2C", + "value": "0x0000C000" + }, + { + "name": "4C/3C", + "value": "0x0000D000" + }, + { + "name": "2S/1C", + "value": "0x0000E000" + }, + { + "name": "Free Play", + "value": "0x0000F000" + } + ] + } + ], + "messages": [] + } +} \ No newline at end of file diff --git a/platform/pocket/audio/audio_fifo.sv b/platform/pocket/audio/audio_fifo.sv new file mode 100644 index 0000000..bf17df2 --- /dev/null +++ b/platform/pocket/audio/audio_fifo.sv @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Audio FIFO Controller +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2022, Adam Gastineau +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module audio_fifo + ( + // Clocks + input wire clk_sys, + input wire audio_mclk, + // Core Audio + input wire [15:0] core_al, + input wire [15:0] core_ar, + // Synced Audio + output logic [15:0] audio_l, + output logic [15:0] audio_r + ); + + localparam READ_DELAY = 1, + READ_WRITE = 2; + + logic [1:0] read_state = 0; + logic wrreq = 0; + logic rdreq = 0; + logic empty; + + logic [15:0] prev_al, prev_ar; + logic [15:0] fifo_al, fifo_ar; + + always_ff @(posedge clk_sys) begin : fifoWriteControl + prev_al <= core_al; + prev_ar <= core_ar; + wrreq <= 0; + if (core_al != prev_al || core_ar != prev_ar) begin + wrreq <= 1; + end + end + + dcfifo #( + .intended_device_family ( "Cyclone V" ), + .lpm_numwords ( 4 ), + .lpm_showahead ( "OFF" ), + .lpm_type ( "dcfifo" ), + .lpm_width ( 32 ), + .lpm_widthu ( 2 ), + .overflow_checking ( "ON" ), + .rdsync_delaypipe ( 5 ), + .underflow_checking ( "ON" ), + .use_eab ( "ON" ), + .wrsync_delaypipe ( 5 ) + ) dcfifo_component ( + // Write + .wrclk ( clk_sys ), + .wrreq ( wrreq ), + .data ( {core_al, core_ar} ), + // Read + .rdclk ( audio_mclk ), + .rdreq ( rdreq ), + .rdempty ( empty ), + .q ( {fifo_al, fifo_ar} ) + ); + + always_ff @(posedge audio_mclk) begin : fifoReadControl + rdreq <= 0; + if (~empty) begin + read_state <= READ_DELAY; + rdreq <= 1; + end + case (read_state) + READ_DELAY: begin + read_state <= READ_WRITE; + end + READ_WRITE: begin + read_state <= 0; + audio_l <= fifo_al; + audio_r <= fifo_ar; + end + endcase + end + +endmodule diff --git a/platform/pocket/audio/audio_mixer.sv b/platform/pocket/audio/audio_mixer.sv new file mode 100644 index 0000000..323ae77 --- /dev/null +++ b/platform/pocket/audio/audio_mixer.sv @@ -0,0 +1,185 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Audio Mixer +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module audio_mixer + #( + parameter DW = 16, //! Audio Data Width + parameter STEREO = 1, //! Stereo Audio + parameter MUTE_PAUSE = 1, //! Mute on Pause + parameter AUDIO_FILTER = 0 //! Enable Audio Filters ROM + ) ( + // Clocks and Reset + input logic clk_74b, //! Clock 74.25Mhz + input logic clk_sys, //! Core System Clock + input logic reset, //! Reset + // Controls + input logic [3:0] afilter_sw, //! Predefined Audio Filter Switch + input logic [3:0] vol_att, //! Volume ([0] Max | [7] Min) + input logic [1:0] mix, //! [0] No Mix | [1] 25% | [2] 50% | [3] 100% (mono) + input logic pause_core, //! Mute Audio + // Audio From Core + input logic is_signed, //! Signed Audio + input logic [DW-1:0] core_l, //! Left Channel Audio from Core + input logic [DW-1:0] core_r, //! Right Channel Audio from Core + // Pocket I2S + output logic audio_mclk, //! Serial Master Clock + output logic audio_lrck, //! Left/Right clock + output logic audio_dac //! Serialized data + ); + + //!------------------------------------------------------------------------- + //! Audio Clocks + //! MCLK: 12.288MHz (256*Fs, where Fs = 48000Khz) + //! SCLK: 3.072mhz (MCLK/4) + //!------------------------------------------------------------------------- + logic audio_sclk; + + mf_audio_pll audio_pll + ( + .refclk ( clk_74b ), + .rst ( 0 ), + .outclk_0 ( audio_mclk ), + .outclk_1 ( audio_sclk ) + ); + + //!------------------------------------------------------------------------- + //! Pad core_l/core_r with zeros to maintain a consistent size of 16 bits + //!------------------------------------------------------------------------- + logic [15:0] core_al, core_ar; + + assign core_al = DW == 16 ? core_l : {core_l, {16-DW{1'b0}}}; + assign core_ar = STEREO ? DW == 16 ? core_r : {core_r, {16-DW{1'b0}}} : core_al; + + //!------------------------------------------------------------------------- + //! Synchronize audio with FIFO + //!------------------------------------------------------------------------- + logic [15:0] fifo_al, fifo_ar; + + audio_fifo audio_fifo + ( + // Clocks + .clk_sys ( clk_sys ), + .audio_mclk ( audio_mclk ), + // Core Audio + .core_al ( core_al ), + .core_ar ( core_ar ), + // Synced Audio + .audio_l ( fifo_al ), + .audio_r ( fifo_ar ) + ); + + //!------------------------------------------------------------------------- + //! Low Pass Filter + //!------------------------------------------------------------------------- + logic [31:0] aflt_rate; + logic [39:0] acx; + logic [7:0] acx0, acx1, acx2; + logic [23:0] acy0, acy1, acy2; + + generate + if(AUDIO_FILTER == 1) begin + arcade_filters arcade_filters + ( + .clk ( audio_mclk ), + .afilter_sw ( afilter_sw ), + .aflt_rate ( aflt_rate ), + .acx ( acx ), + .acx0 ( acx0 ), + .acx1 ( acx1 ), + .acx2 ( acx2 ), + .acy0 ( acy0 ), + .acy1 ( acy1 ), + .acy2 ( acy2 ) + ); + end + else begin + assign aflt_rate = 32'd7056000; // Sampling Frequency + assign acx = 40'd4258969; // Base gain + assign acx0 = 8'd3; // gain scale for X0 + assign acx1 = 8'd3; // gain scale for X1 + assign acx2 = 8'd1; // gain scale for X2 + assign acy0 = -24'd6216759; // gain scale for Y0 + assign acy1 = 24'd6143386; // gain scale for Y1 + assign acy2 = -24'd2023767; // gain scale for Y2 + end + endgenerate + + //!------------------------------------------------------------------------- + //! Audio Filters + //!------------------------------------------------------------------------- + logic [15:0] audio_l, audio_r; + logic mute_audio; + + assign mute_audio = MUTE_PAUSE ? pause_core : 1'b0; + + audio_filters audio_filters + ( + .clk ( audio_mclk ), + .reset ( reset ), + // Controls + .att ( {mute_audio, vol_att} ), + .mix ( mix ), + // Audio Filter + .flt_rate ( aflt_rate ), + .cx ( acx ), + .cx0 ( acx0 ), + .cx1 ( acx1 ), + .cx2 ( acx2 ), + .cy0 ( acy0 ), + .cy1 ( acy1 ), + .cy2 ( acy2 ), + // Audio from Core + .is_signed ( is_signed ), + .core_l ( fifo_al ), + .core_r ( fifo_ar ), + // Filtered Audio Output + .audio_l ( audio_l ), + .audio_r ( audio_r ) + ); + + //!------------------------------------------------------------------------- + //! Pocket I2S Output + //!------------------------------------------------------------------------- + pocket_i2s pocket_i2s + ( + // Serial Clock + .audio_sclk ( audio_sclk ), // [i] + // Audio Input + .audio_l ( audio_l ), // [i] + .audio_r ( audio_r ), // [i] + // Pocket I2S Interface + .audio_dac ( audio_dac ), // [o] + .audio_lrck ( audio_lrck ) // [o] + ); + +endmodule diff --git a/platform/pocket/audio/filters/arcade_filters.sv b/platform/pocket/audio/filters/arcade_filters.sv new file mode 100644 index 0000000..4165bdf --- /dev/null +++ b/platform/pocket/audio/filters/arcade_filters.sv @@ -0,0 +1,142 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Arcade Audio Filters +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module arcade_filters + ( + // Clock + input logic clk, + // Filter Switch + input logic [3:0] afilter_sw, + // Filter Config + output logic [31:0] flt_rate, // Sampling Frequency + output logic [39:0] cx, // Base gain + output logic [7:0] cx0, cx1, cx2, // gain scale for X0, X1, X2 + output logic [23:0] cy0, cy1, cy2 // gain scale for Y0, Y1, Y2 + ); + + always_ff @(posedge clk) begin + case(afilter_sw) + 1: begin // Arcade LPF 2khz 1st + flt_rate <= 32'd7056000; + cx <= 40'd425898; + cx0 <= 8'd3; + cx1 <= 8'd3; + cx2 <= 8'd1; + cy0 <= -24'd6234907; + cy1 <= 24'd6179109; + cy2 <= -24'd2041353; + end + 2: begin // Arcade LPF 2khz 2nd + flt_rate <= 32'd7056000; + cx <= 40'd2420697; + cx0 <= 8'd2; + cx1 <= 8'd1; + cx2 <= 8'd0; + cy0 <= -24'd4189022; + cy1 <= 24'd2091876; + cy2 <= 24'd0; + end + 3: begin // Arcade LPF 4khz 1st + flt_rate <= 32'd7056000; + cx <= 40'd851040; + cx0 <= 8'd3; + cx1 <= 8'd3; + cx2 <= 8'd1; + cy0 <= -24'd6231182; + cy1 <= 24'd6171753; + cy2 <= -24'd2037720; + end + 4: begin // Arcade LPF 4khz 2nd + flt_rate <= 32'd7056000; + cx <= 40'd9670619; + cx0 <= 8'd2; + cx1 <= 8'd1; + cx2 <= 8'd0; + cy0 <= -24'd4183740; + cy1 <= 24'd2086614; + cy2 <= 24'd0; + end + 5: begin // Arcade LPF 6khz 1st + flt_rate <= 32'd7056000; + cx <= 40'd1275428; + cx0 <= 8'd3; + cx1 <= 8'd3; + cx2 <= 8'd1; + cy0 <= -24'd6227464; + cy1 <= 24'd6164410; + cy2 <= -24'd2034094; + end + 6: begin // Arcade LPF 6khz 2nd + flt_rate <= 32'd7056000; + cx <= 40'd21731566; + cx0 <= 8'd2; + cx1 <= 8'd1; + cx2 <= 8'd0; + cy0 <= -24'd4178458; + cy1 <= 24'd2081365; + cy2 <= 24'd0; + end + 7: begin // Arcade LPF 8khz 1st + flt_rate <= 32'd7056000; + cx <= 40'd1699064; + cx0 <= 8'd3; + cx1 <= 8'd3; + cx2 <= 8'd1; + cy0 <= -24'd6223752; + cy1 <= 24'd6157080; + cy2 <= -24'd2030475; + end + 8: begin // Arcade LPF 8khz 2nd + flt_rate <= 32'd7056000; + cx <= 40'd38585417; + cx0 <= 8'd2; + cx1 <= 8'd1; + cx2 <= 8'd0; + cy0 <= -24'd4173176; + cy1 <= 24'd2076130; + cy2 <= 24'd0; + end + default: begin + flt_rate <= 32'd7056000; + cx <= 40'd4258969; + cx0 <= 8'd3; + cx1 <= 8'd3; + cx2 <= 8'd1; + cy0 <= -24'd6216759; + cy1 <= 24'd6143386; + cy2 <= -24'd2023767; + end + endcase + end + +endmodule diff --git a/platform/pocket/audio/filters/audio_filters.sv b/platform/pocket/audio/filters/audio_filters.sv new file mode 100644 index 0000000..3ecd6b3 --- /dev/null +++ b/platform/pocket/audio/filters/audio_filters.sv @@ -0,0 +1,205 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Audio Filters +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2020, Alexey Melnikov +// +// This source file 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 . +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module audio_filters + #( + parameter CLK_RATE = 12288000 + ) ( + input wire clk, + input wire reset, + + input wire [31:0] flt_rate, + input wire [39:0] cx, + input wire [7:0] cx0, + input wire [7:0] cx1, + input wire [7:0] cx2, + input wire [23:0] cy0, + input wire [23:0] cy1, + input wire [23:0] cy2, + input wire [4:0] att, + + input wire is_signed, + input wire [1:0] mix, + + input wire [15:0] core_l, + input wire [15:0] core_r, + + // Audio Output + output wire [15:0] audio_l, + output wire [15:0] audio_r + ); + + reg sample_rate = 0; //0 - 48KHz, 1 - 96KHz + + reg sample_ce; + always @(posedge clk) begin + reg [8:0] div = 0; + reg [1:0] add = 0; + + div <= div + add; + if(!div) begin + div <= 2'd1 << sample_rate; + add <= 2'd1 << sample_rate; + end + + sample_ce <= !div; + end + + reg flt_ce; + always @(posedge clk) begin + reg [31:0] cnt = 0; + + flt_ce = 0; + cnt = cnt + {flt_rate[30:0],1'b0}; + if(cnt >= CLK_RATE) begin + cnt = cnt - CLK_RATE; + flt_ce = 1; + end + end + + reg [15:0] cl,cr; + always @(posedge clk) begin + reg [15:0] cl1, cl2; + reg [15:0] cr1, cr2; + + cl1 <= core_l; + cl2 <= cl1; + if(cl2 == cl1) + cl <= cl2; + + cr1 <= core_r; + cr2 <= cr1; + if(cr2 == cr1) + cr <= cr2; + end + + reg a_en1 = 0, a_en2 = 0; + always @(posedge clk, posedge reset) begin + reg [1:0] dly1; + reg [14:0] dly2; + + if(reset) begin + dly1 <= 0; + dly2 <= 0; + a_en1 <= 0; + a_en2 <= 0; + end + else begin + if(flt_ce) begin + if(~&dly1) + dly1 <= dly1 + 1'd1; + else + a_en1 <= 1; + end + + if(sample_ce) begin + if(!dly2[13+sample_rate]) + dly2 <= dly2 + 1'd1; + else + a_en2 <= 1; + end + end + end + + wire [15:0] acl, acr; + iir_filter #(.use_params(0)) iir_filter + ( + .clk ( clk ), + .reset ( reset ), + + .ce ( flt_ce & a_en1 ), + .sample_ce ( sample_ce ), + + .cx ( cx ), + .cx0 ( cx0 ), + .cx1 ( cx1 ), + .cx2 ( cx2 ), + .cy0 ( cy0 ), + .cy1 ( cy1 ), + .cy2 ( cy2 ), + + .input_l ( {~is_signed ^ cl[15], cl[14:0]} ), + .input_r ( {~is_signed ^ cr[15], cr[14:0]} ), + .output_l ( acl ), + .output_r ( acr ) + ); + + wire [15:0] adl; + dc_blocker dcb_l + ( + .clk ( clk ), + .ce ( sample_ce ), + .sample_rate ( sample_rate ), + .mute ( ~a_en2 ), + .din ( acl ), + .dout ( adl ) + ); + + wire [15:0] adr; + dc_blocker dcb_r + ( + .clk ( clk ), + .ce ( sample_ce ), + .sample_rate ( sample_rate ), + .mute ( ~a_en2 ), + .din ( acr ), + .dout ( adr ) + ); + + wire [15:0] audio_l_pre; + audio_mix audmix_l + ( + .clk ( clk ), + .ce ( sample_ce ), + .att ( att ), + .mix ( mix ), + + .core_audio ( adl ), + .pre_in ( audio_r_pre ), + + .pre_out ( audio_l_pre ), + .out ( audio_l ) + ); + + wire [15:0] audio_r_pre; + audio_mix audmix_r + ( + .clk ( clk ), + .ce ( sample_ce ), + .att ( att ), + .mix ( mix ), + + .core_audio ( adr ), + .pre_in ( audio_l_pre ), + + .pre_out ( audio_r_pre ), + .out ( audio_r ) + ); + +endmodule diff --git a/platform/pocket/audio/filters/audio_mix.sv b/platform/pocket/audio/filters/audio_mix.sv new file mode 100644 index 0000000..384afb8 --- /dev/null +++ b/platform/pocket/audio/filters/audio_mix.sv @@ -0,0 +1,69 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Audio Mix +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2020, Alexey Melnikov +// +// This source file 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 . +// +//------------------------------------------------------------------------------ +// altera message_off 10230 + +`default_nettype none +`timescale 1ns/1ps + +module audio_mix + ( + input wire clk, // system clock + input wire ce, // clock enable signal + + input wire [4:0] att, // attenuation value + input wire [1:0] mix, // mixing value + + input wire [15:0] core_audio, // audio input from core + input wire [15:0] pre_in, // audio input from preamp + + output reg [15:0] pre_out = 0, // preamp output + output reg [15:0] out = 0 // final mixed audio output + ); + + reg signed [16:0] a1, a2, a3; // Signed registers for audio processing + + always @(posedge clk) begin + if (ce) begin + a1 <= { core_audio[15], core_audio }; // extend core_audio to 17 bits and store in a1 + pre_out <= a1[16:1]; // store the upper 16 bits of a1 in pre_out + + // select mixing options + case(mix) + 0: begin a2 <= a1; end // mix core_audio + 1: begin a2 <= $signed(a1) - $signed(a1[16:3]) + $signed(pre_in[15:2]); end // mix core_audio, and pre_in with attenuation + 2: begin a2 <= $signed(a1) - $signed(a1[16:2]) + $signed(pre_in[15:1]); end // mix core_audio, and pre_in with greater attenuation + 3: begin a2 <= {a1[16],a1[16:1]} + {pre_in[15],pre_in}; end // mix core_audio, and pre_in with clipping + endcase + + // if the highest bit of att is set, set a3 to 0 (Mute) else shift a2 right by att and store in a3 + a3 <= (att[4]) ? 0 : a2 >>> att[3:0]; + + // Clamping + out <= ^a3[16:15] ? { a3[16], {15{a3[15]}} } : a3[15:0]; // clamp the upper 16 bits of a3 and store in out + end + end + +endmodule diff --git a/platform/pocket/audio/filters/dc_blocker.sv b/platform/pocket/audio/filters/dc_blocker.sv new file mode 100644 index 0000000..2a856fb --- /dev/null +++ b/platform/pocket/audio/filters/dc_blocker.sv @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// DC blocker filter using a simplified IIR structure. +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2020, Alexey Melnikov +// +// This source file 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 . +// +//------------------------------------------------------------------------------ +// +// It utilizes feedback to achieve filtering, operating on a delayed version of +// the input signal (x0), a delayed version of the output signal (y1), and the +// current input and output signals (x1 and y0, respectively). +// The filter coefficients are determined by the sample rate of the input signal. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module dc_blocker + ( + input logic clk, // Input clock signal + input logic ce, // Control enable signal + input logic mute, // Mute output signal + + input logic sample_rate, // Sample rate input signal + input logic [15:0] din, // Input data signal + output logic [15:0] dout // Output data signal + ); + + // Pad the input signal with zeros + wire [39:0] x = {din[15], din, 23'd0}; + // Subtract previous input sample from current input sample + wire [39:0] x0 = x - (sample_rate ? {{11{x[39]}}, x[39:11]} : {{10{x[39]}}, x[39:10]}); + // Subtract previous output sample from current output sample + wire [39:0] y1 = y - (sample_rate ? {{10{y[39]}}, y[39:10]} : {{09{y[39]}}, y[39:09]}); + // Subtract difference between previous input and output sample from current input sample + wire [39:0] y0 = x0 - x1 + y1; + + // Registers to store previous input and output samples + reg [39:0] x1, y; + + always @(posedge clk) begin + if(ce) begin + // Update the previous input sample + x1 <= x0; + // Update the previous output sample + y <= ^y0[39:38] ? {{2{y0[39]}},{38{y0[38]}}} : y0; + end + end + + // Output the filtered sample, or zero if the mute signal is high + assign dout = mute ? 16'd0 : y[38:23]; + +endmodule diff --git a/platform/pocket/audio/filters/filter_loader.sv b/platform/pocket/audio/filters/filter_loader.sv new file mode 100644 index 0000000..f9c0297 --- /dev/null +++ b/platform/pocket/audio/filters/filter_loader.sv @@ -0,0 +1,112 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Audio Filter Loader +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module filter_loader + ( + // Clocks and Reset + input logic clk_sys, + input logic afilter_wr, + input logic [7:0] afilter_addr, + input logic [7:0] afilter_din, + // Audio From Core + output logic [31:0] flt_rate, // Sampling Frequency + output logic [39:0] cx, // Base gain + output logic [7:0] cx0, cx1, cx2, // gain scale for X0, X1, X2 + output logic [23:0] cy0, cy1, cy2 // gain scale for Y0, Y1, Y2 + ); + + always_comb begin + flt_rate = r_flt_rate; + cx = r_cx; + cx0 = r_cx0; + cx1 = r_cx1; + cx2 = r_cx2; + cy0 = r_cy0; + cy1 = r_cy1; + cy2 = r_cy2; + end + + reg [31:0] r_flt_rate = 7056000; // Sampling Frequency + reg [39:0] r_cx = 4258969; // Base gain + reg [7:0] r_cx0 = 3; // gain scale for X0 + reg [7:0] r_cx1 = 3; // gain scale for X1 + reg [7:0] r_cx2 = 1; // gain scale for X2 + reg [23:0] r_cy0 = -24'd6216759; // gain scale for Y0 + reg [23:0] r_cy1 = 24'd6143386; // gain scale for Y1 + reg [23:0] r_cy2 = -24'd2023767; // gain scale for Y2 + + always_ff @(posedge clk_sys) begin + if (afilter_wr) begin + case(afilter_addr) + //! Sampling Frequency + 8'h00: r_flt_rate[7:0] <= afilter_din; + 8'h01: r_flt_rate[15:8] <= afilter_din; + 8'h02: r_flt_rate[23:16] <= afilter_din; + 8'h03: r_flt_rate[31:24] <= afilter_din; + //! Base gain + 8'h04: r_cx[7:0] <= afilter_din; + 8'h05: r_cx[15:8] <= afilter_din; + 8'h06: r_cx[23:16] <= afilter_din; + 8'h07: r_cx[31:24] <= afilter_din; + 8'h08: r_cx[39:32] <= afilter_din; + // 8'h09: _SKIP_ + // 8'h0a: _SKIP_ + // 8'h0b: _SKIP_ + //! gain scale for X0 + 8'h0c: r_cx0 <= afilter_din; + //! gain scale for X1 + 8'h0d: r_cx1 <= afilter_din; + //! gain scale for X2 + 8'h0e: r_cx2 <= afilter_din; + //! gain scale for Y0 + 8'h0f: r_cy0[7:0] <= afilter_din; + 8'h10: r_cy0[15:8] <= afilter_din; + 8'h11: r_cy0[23:16] <= afilter_din; + // 8'h12: _SKIP_ + //! gain scale for Y1 + 8'h13: r_cy1[7:0] <= afilter_din; + 8'h14: r_cy1[15:8] <= afilter_din; + 8'h15: r_cy1[23:16] <= afilter_din; + // 8'h16: _SKIP_ + //! gain scale for Y2 + 8'h17: r_cy2[7:0] <= afilter_din; + 8'h18: r_cy2[15:8] <= afilter_din; + 8'h19: r_cy2[23:16] <= afilter_din; + // 8'h1a: _SKIP_ + // 8'h1b: _SKIP_ + default:; + endcase + end + end + +endmodule diff --git a/platform/pocket/audio/filters/filters_rom.sv b/platform/pocket/audio/filters/filters_rom.sv new file mode 100644 index 0000000..2516d5c --- /dev/null +++ b/platform/pocket/audio/filters/filters_rom.sv @@ -0,0 +1,174 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Audio Filters ROM +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module filters_rom + ( + // Clock + input logic clk, + // Filter Switch + input logic [3:0] afilter_sw, + // Filter Config + output logic [31:0] aflt_rate, // Sampling Frequency + output logic [39:0] acx, // Base gain + output logic [7:0] acx0, acx1, acx2, // gain scale for X0, X1, X2 + output logic [23:0] acy0, acy1, acy2 // gain scale for Y0, Y1, Y2 + ); + + (* ramstyle = "no_rw_check" *) reg [31:0] flt_rate[9]; + (* ramstyle = "no_rw_check" *) reg [39:0] cx[9]; + (* ramstyle = "no_rw_check" *) reg [7:0] cx0[9]; + (* ramstyle = "no_rw_check" *) reg [7:0] cx1[9]; + (* ramstyle = "no_rw_check" *) reg [7:0] cx2[9]; + (* ramstyle = "no_rw_check" *) reg [23:0] cy0[9]; + (* ramstyle = "no_rw_check" *) reg [23:0] cy1[9]; + (* ramstyle = "no_rw_check" *) reg [23:0] cy2[9]; + + always @(posedge clk) begin + aflt_rate <= flt_rate[afilter_sw]; + acx <= cx[afilter_sw]; + acx0 <= cx0[afilter_sw]; + acx1 <= cx1[afilter_sw]; + acx2 <= cx2[afilter_sw]; + acy0 <= cy0[afilter_sw]; + acy1 <= cy1[afilter_sw]; + acy2 <= cy2[afilter_sw]; + end + //! Assign Outputs --------------------------------------------------------- + + //! Arcade Filters --------------------------------------------------------- + initial begin + // Default + flt_rate[0] = 7056000; + cx[0] = 4258969; + cx0[0] = 3; + cx1[0] = 3; + cx2[0] = 1; + cy0[0] = -24'd6216759; + cy1[0] = 24'd6143386; + cy2[0] = -24'd2023767; + + // Arcade LPF 2khz 1st + flt_rate[1] = 32'd7056000; + cx[1] = 40'd425898; + cx0[1] = 8'd3; + cx1[1] = 8'd3; + cx2[1] = 8'd1; + cy0[1] = -24'd6234907; + cy1[1] = 24'd6179109; + cy2[1] = -24'd2041353; + + // Arcade LPF 2khz 2nd + flt_rate[2] = 32'd7056000; + cx[2] = 40'd2420697; + cx0[2] = 8'd2; + cx1[2] = 8'd1; + cx2[2] = 8'd0; + cy0[2] = -24'd4189022; + cy1[2] = 24'd2091876; + cy2[2] = 24'd0; + + // Arcade LPF 4khz 1st + flt_rate[3] = 32'd7056000; + cx[3] = 40'd851040; + cx0[3] = 8'd3; + cx1[3] = 8'd3; + cx2[3] = 8'd1; + cy0[3] = -24'd6231182; + cy1[3] = 24'd6171753; + cy2[3] = -24'd2037720; + + // Arcade LPF 4khz 2nd + flt_rate[4] = 32'd7056000; + cx[4] = 40'd9670619; + cx0[4] = 8'd2; + cx1[4] = 8'd1; + cx2[4] = 8'd0; + cy0[4] = -24'd4183740; + cy1[4] = 24'd2086614; + cy2[4] = 24'd0; + + // Arcade LPF 6khz 1st + flt_rate[5] = 32'd7056000; + cx[5] = 40'd1275428; + cx0[5] = 8'd3; + cx1[5] = 8'd3; + cx2[5] = 8'd1; + cy0[5] = -24'd6227464; + cy1[5] = 24'd6164410; + cy2[5] = -24'd2034094; + + // Arcade LPF 6khz 2nd + flt_rate[6] = 32'd7056000; + cx[6] = 40'd21731566; + cx0[6] = 8'd2; + cx1[6] = 8'd1; + cx2[6] = 8'd0; + cy0[6] = -24'd4178458; + cy1[6] = 24'd2081365; + cy2[6] = 24'd0; + + // Arcade LPF 8khz 1st + flt_rate[7] = 32'd7056000; + cx[7] = 40'd1699064; + cx0[7] = 8'd3; + cx1[7] = 8'd3; + cx2[7] = 8'd1; + cy0[7] = -24'd6223752; + cy1[7] = 24'd6157080; + cy2[7] = -24'd2030475; + + // Arcade LPF 8khz 2nd + flt_rate[8] = 32'd7056000; + cx[8] = 40'd38585417; + cx0[8] = 8'd2; + cx1[8] = 8'd1; + cx2[8] = 8'd0; + cy0[8] = -24'd4173176; + cy1[8] = 24'd2076130; + cy2[8] = 24'd0; + + end + + // [ 9 ] LPF 10khz 1st + Aa + // [ 10 ] LPF 12khz 1st + Aa + // [ 11 ] LPF 14khz 1st + Aa + // [ 12 ] LPF 16khz 1st + Aa + // [ 13 ] LPF 16khz 3rd Ch 1db + // [ 14 ] LPF 18khz 3rd Ch 1db + // [ 15 ] LPF 20khz 2nd Bw + // [ 16 ] LPF 20khz 3rd Bw + // [ 17 ] LPF 20khz 3rd Ch 1db + + // [ 18 ] SNES Gpm-02 LPF + +endmodule diff --git a/platform/pocket/audio/filters/iir_filter.sv b/platform/pocket/audio/filters/iir_filter.sv new file mode 100644 index 0000000..5a2cebb --- /dev/null +++ b/platform/pocket/audio/filters/iir_filter.sv @@ -0,0 +1,166 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// 3-tap IIR filter for 2 channels. +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2020, Alexey Melnikov +// +// This source file 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 . +// +//------------------------------------------------------------------------------ +// +// Can be converted to: +// - 2-tap (coeff_x2 = 0, coeff_y2 = 0) +// - 1-tap (coeff_x1,2 = 0, coeff_y1,2 = 0) +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module iir_filter + #( + parameter use_params = 1, // set to 1 to use following parameters, 0 for input port variables. + parameter stereo = 1, // 0 for mono (input_l) + + parameter coeff_x = 0.00000774701983513660, // Base gain value for X. Float. Range: 0.0 ... 0.999(9) + parameter coeff_x0 = 3, // Gain scale factor for X0. Integer. Range -7 ... +7 + parameter coeff_x1 = 3, // Gain scale factor for X1. Integer. Range -7 ... +7 + parameter coeff_x2 = 1, // Gain scale factor for X2. Integer. Range -7 ... +7 + parameter coeff_y0 = -2.96438150626551080000, // Coefficient for Y0. Float. Range -3.999(9) ... 3.999(9) + parameter coeff_y1 = 2.92939452735121100000, // Coefficient for Y1. Float. Range -3.999(9) ... 3.999(9) + parameter coeff_y2 = -0.96500747158831091000 // Coefficient for Y2. Float. Range -3.999(9) ... 3.999(9) + ) ( + input clk, + input reset, + + input ce, // must be double of calculated rate for stereo! + input sample_ce, // desired output sample rate + + input [39:0] cx, + input [7:0] cx0, + input [7:0] cx1, + input [7:0] cx2, + input [23:0] cy0, + input [23:0] cy1, + input [23:0] cy2, + + input [15:0] input_l, input_r, // signed samples + output [15:0] output_l, output_r // signed samples + ); + + localparam [39:0] pcoeff_x = coeff_x * 40'h8000000000; + localparam [31:0] pcoeff_y0 = coeff_y0 * 24'h200000; + localparam [31:0] pcoeff_y1 = coeff_y1 * 24'h200000; + localparam [31:0] pcoeff_y2 = coeff_y2 * 24'h200000; + + wire [39:0] vcoeff = use_params ? pcoeff_x : cx; + wire [23:0] vcoeff_y0 = use_params ? pcoeff_y0[23:0] : cy0; + wire [23:0] vcoeff_y1 = use_params ? pcoeff_y1[23:0] : cy1; + wire [23:0] vcoeff_y2 = use_params ? pcoeff_y2[23:0] : cy2; + + wire [59:0] inp_mul = $signed(inp) * $signed(vcoeff); + + wire [39:0] x = inp_mul[59:20]; + wire [39:0] y = x + tap0; + + wire [39:0] tap0; + iir_filter_tap iir_tap_0 + ( + .clk ( clk ), + .reset ( reset ), + .ce ( ce ), + .ch ( ch ), + .cx ( use_params ? coeff_x0[7:0] : cx0 ), + .cy ( vcoeff_y0 ), + .x ( x ), + .y ( y ), + .z ( tap1 ), + .tap ( tap0 ) + ); + + wire [39:0] tap1; + iir_filter_tap iir_tap_1 + ( + .clk ( clk ), + .reset ( reset ), + .ce ( ce ), + .ch ( ch ), + .cx ( use_params ? coeff_x1[7:0] : cx1 ), + .cy ( vcoeff_y1 ), + .x ( x ), + .y ( y ), + .z ( tap2 ), + .tap ( tap1 ) + ); + + wire [39:0] tap2; + iir_filter_tap iir_tap_2 + ( + .clk ( clk ), + .reset ( reset ), + .ce ( ce ), + .ch ( ch ), + .cx ( use_params ? coeff_x2[7:0] : cx2 ), + .cy ( vcoeff_y2 ), + .x ( x ), + .y ( y ), + .z ( 0 ), + .tap ( tap2 ) + ); + + wire [15:0] y_clamp = (~y[39] & |y[38:35]) ? 16'h7FFF : (y[39] & ~&y[38:35]) ? 16'h8000 : y[35:20]; + + reg ch = 0; + reg [15:0] out_l, out_r, out_m; + reg [15:0] inp, inp_m; + + always @(posedge clk) begin + if (ce) begin + if(!stereo) begin + ch <= 0; + inp <= input_l; + out_l <= y_clamp; + out_r <= y_clamp; + end + else begin + ch <= ~ch; + if(ch) begin + out_m <= y_clamp; + inp <= inp_m; + end + else begin + out_l <= out_m; + out_r <= y_clamp; + inp <= input_l; + inp_m <= input_r; + end + end + end + end + + reg [31:0] out; + always @(posedge clk) begin + if (sample_ce) begin + out <= {out_l, out_r}; + end + end + + assign {output_l, output_r} = out; + +endmodule diff --git a/platform/pocket/audio/filters/iir_filter_tap.sv b/platform/pocket/audio/filters/iir_filter_tap.sv new file mode 100644 index 0000000..68c50f0 --- /dev/null +++ b/platform/pocket/audio/filters/iir_filter_tap.sv @@ -0,0 +1,91 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Infinite Impulse Response (IIR) filter tap. +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2020, Alexey Melnikov +// +// This source file 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 . +// +//------------------------------------------------------------------------------ +// +// The iir_filter_tap module implements an infinite impulse response (IIR) filter +// with one tap. It takes in input data x, previous output data y, and an input z +// and calculates the output tap using a set of coefficients cx and cy. The +// coefficients are used to multiply the input data and previous output data, +// and the resulting values are then added together to produce the output tap. +// The module stores intermediate values in a logic RAM, and updates the values +// on each clock cycle based on the control signals ce and ch. The module uses +// a Verilog function to perform the multiplication of the input data with the +// coefficients. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module iir_filter_tap + ( + input wire clk, // clock signal + input wire reset, // reset signal + + input wire ce, // control signal + input wire ch, // control signal + + input wire [7:0] cx, // coefficient value + input wire [23:0] cy, // coefficient value + + input wire [39:0] x, // input data + input wire [39:0] y, // previous output data + input wire [39:0] z, // input data + output wire [39:0] tap // output data + ); + + // multiply previous output y with coefficient cy + wire signed [60:0] y_mul = $signed(y[36:0]) * $signed(cy); + + // multiply input x with coefficient cx + function [39:0] x_mul; + input [39:0] x; + begin + x_mul = 0; + if(cx[0]) x_mul = x_mul + {{4{x[39]}}, x[39:4]}; // multiply x[39:36] with cx[0] + if(cx[1]) x_mul = x_mul + {{3{x[39]}}, x[39:3]}; // multiply x[39:35] with cx[1] + if(cx[2]) x_mul = x_mul + {{2{x[39]}}, x[39:2]}; // multiply x[39:34] with cx[2] + if(cx[7]) x_mul = ~x_mul; // negate result if cx[7] is set + end + endfunction + + // use logic RAM to store intermediate values + (* ramstyle = "logic" *) reg [39:0] intreg[2]; + always @(posedge clk, posedge reset) begin + if(reset) begin + {intreg[0],intreg[1]} <= 80'd0; + end + else if(ce) begin + // update intreg[ch] with new value + intreg[ch] <= x_mul(x) - y_mul[60:21] + z; + // multiply input x with cx, subtract a portion of previous output y (specified by cy), + // add input z, and store the result in intreg[ch] + end + end + + // assign output tap to value in intreg corresponding to ch signal + assign tap = intreg[ch]; + +endmodule diff --git a/platform/pocket/audio/pocket_i2s.sv b/platform/pocket/audio/pocket_i2s.sv new file mode 100644 index 0000000..2992949 --- /dev/null +++ b/platform/pocket/audio/pocket_i2s.sv @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket I2S Audio Interface +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module pocket_i2s + ( + input wire audio_sclk, //! Serial clock + // Core Audio + input wire [15:0] audio_l, //! Left channel + input wire [15:0] audio_r, //! Right channel + // Pocket I2S Interface + output reg audio_dac, //! Serialized data + output reg audio_lrck //! Left/Right clock + ); + + //!------------------------------------------------------------------------- + //! Generate signals for digital-to-analog conversion. + //!------------------------------------------------------------------------- + reg [31:0] audio_sample_sh; // Register for shifting audio samples + reg [4:0] audio_lrck_cnt; // Register for counting LRCK (left/right clock) cycles + + always_ff @(negedge audio_sclk) begin + audio_dac <= audio_sample_sh[31]; // Set DAC output to the MSB (most significant bit) of audio_sample_sh + audio_lrck_cnt <= audio_lrck_cnt + 5'd1; + if (audio_lrck_cnt == 5'd31) begin + audio_lrck <= ~audio_lrck; // Toggle audio_lrck (switch channels) + if (~audio_lrck) begin + audio_sample_sh <= { audio_l, audio_r }; // Reload sample shifter with new audio sample + end + end + else if (audio_lrck_cnt < 5'd16) begin + audio_sample_sh <= { audio_sample_sh[30:0], 1'b0 }; // Only shift for 16 clocks per channel + end + end + +endmodule diff --git a/platform/pocket/bsp/pocket/apf_top.sv b/platform/pocket/bsp/pocket/apf_top.sv new file mode 100644 index 0000000..e697862 --- /dev/null +++ b/platform/pocket/bsp/pocket/apf_top.sv @@ -0,0 +1,464 @@ +// Software License Agreement + +// The software supplied herewith by Analogue Enterprises Limited (the "Company”), +// the Analogue Pocket Framework (“APF”), is provided and licensed to you, the +// Company's customer, solely for use in designing, testing and creating +// applications for use with Company's Products or Services. The software is +// owned by the Company and/or its licensors, and is protected under applicable +// laws, including, but not limited to, U.S. copyright law. All rights are +// reserved. By using the APF code you are agreeing to the terms of the End User +// License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula] +// and incorporated herein by reference. To the extent any use of the APF requires +// application of the MIT License or the GNU General Public License and terms of +// this APF Software License Agreement and EULA are inconsistent with such license, +// the applicable terms of the MIT License or the GNU General Public License, as +// applicable, will prevail. + +// THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED +// WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO, +// ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR +// NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM +// DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE +// MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED, +// THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND +// DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING +// THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR +// ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY +// INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES, +// INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR +// INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY +// OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY +// CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION, +// WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU +// TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH +// YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE +// FULLEST EXTENT PERMITTED BY APPLICABLE LAW. +// +// 6515C - Analogue Pocket main unit +// SOCRATES FPGA +// +// 2022-08-17 Analogue + +`default_nettype none +`timescale 1ns/1ps + +module apf_top ( + /////////////////////////////////////////////////// + // clock inputs 74.25mhz. not phase aligned, so treat these domains as asynchronous + + input wire clk_74a, // mainclk1 + input wire clk_74b, // mainclk1 + + /////////////////////////////////////////////////// + // cartridge interface + // switches between 3.3v and 5v mechanically + // output enable for multibit translators controlled by PIC32 + + // GBA AD[15:8] + inout wire [7:0] cart_tran_bank2, + output wire cart_tran_bank2_dir, + + // GBA AD[7:0] + inout wire [7:0] cart_tran_bank3, + output wire cart_tran_bank3_dir, + + // GBA A[23:16] + inout wire [7:0] cart_tran_bank1, + output wire cart_tran_bank1_dir, + + // GBA [7] PHI# + // GBA [6] WR# + // GBA [5] RD# + // GBA [4] CS1#/CS# + // [3:0] unwired + inout wire [7:4] cart_tran_bank0, + output wire cart_tran_bank0_dir, + + // GBA CS2#/RES# + inout wire cart_tran_pin30, + output wire cart_tran_pin30_dir, + // when GBC cart is inserted, this signal when low or weak will pull GBC /RES low with a special circuit + // the goal is that when unconfigured, the FPGA weak pullups won't interfere. + // thus, if GBC cart is inserted, FPGA must drive this high in order to let the level translators + // and general IO drive this pin. + output wire cart_pin30_pwroff_reset, + + // GBA IRQ/DRQ + inout wire cart_tran_pin31, + output wire cart_tran_pin31_dir, + + // infrared + // avoid driving the TX LED with DC or leaving it stuck on. pulsed usage is fine + input wire port_ir_rx, + output wire port_ir_tx, + output wire port_ir_rx_disable, + + // GBA link port + inout wire port_tran_si, + output wire port_tran_si_dir, + inout wire port_tran_so, + output wire port_tran_so_dir, + inout wire port_tran_sck, + output wire port_tran_sck_dir, + inout wire port_tran_sd, + output wire port_tran_sd_dir, + + /////////////////////////////////////////////////// + // video output to the scaler + + inout wire [11:0] scal_vid, + inout wire scal_clk, + inout wire scal_de, + inout wire scal_skip, + inout wire scal_vs, + inout wire scal_hs, + + output wire scal_audmclk, + input wire scal_audadc, + output wire scal_auddac, + output wire scal_audlrck, + + /////////////////////////////////////////////////// + // communication between main and scaler (aristotle) fpga. + // spi bus with aristotle as controller. + + inout wire bridge_spimosi, + inout wire bridge_spimiso, + inout wire bridge_spiclk, + input wire bridge_spiss, + inout wire bridge_1wire, + + /////////////////////////////////////////////////// + // cellular psram 0 and 1, two chips (64mbit x2 dual die per chip) + + output wire [21:16] cram0_a, + inout wire [15:0] cram0_dq, + input wire cram0_wait, + output wire cram0_clk, + output wire cram0_adv_n, + output wire cram0_cre, + output wire cram0_ce0_n, + output wire cram0_ce1_n, + output wire cram0_oe_n, + output wire cram0_we_n, + output wire cram0_ub_n, + output wire cram0_lb_n, + + output wire [21:16] cram1_a, + inout wire [15:0] cram1_dq, + input wire cram1_wait, + output wire cram1_clk, + output wire cram1_adv_n, + output wire cram1_cre, + output wire cram1_ce0_n, + output wire cram1_ce1_n, + output wire cram1_oe_n, + output wire cram1_we_n, + output wire cram1_ub_n, + output wire cram1_lb_n, + + /////////////////////////////////////////////////// + // sdram, 512mbit x16 + + output wire [12:0] dram_a, + output wire [1:0] dram_ba, + inout wire [15:0] dram_dq, + output wire [1:0] dram_dqm, + output wire dram_clk, + output wire dram_cke, + output wire dram_ras_n, + output wire dram_cas_n, + output wire dram_we_n, + + /////////////////////////////////////////////////// + // sram, 1mbit x16 + + output wire [16:0] sram_a, + inout wire [15:0] sram_dq, + output wire sram_oe_n, + output wire sram_we_n, + output wire sram_ub_n, + output wire sram_lb_n, + + /////////////////////////////////////////////////// + // vblank output to scaler + + input wire vblank, + + /////////////////////////////////////////////////// + // i/o to 6515D breakout usb uart + + output wire dbg_tx, + input wire dbg_rx, + + /////////////////////////////////////////////////// + // i/o pads near jtag connector user can solder to + + output wire user1, + input wire user2, + + /////////////////////////////////////////////////// + // powerup self test, do not use + + inout wire bist, + output wire vpll_feed, + + /////////////////////////////////////////////////// + // RFU internal i2c bus (DNU) + + inout wire aux_sda, + output wire aux_scl + + ); + + assign bist = 1'bZ; + + // reset generation + reg [24:0] count; + reg reset_n; + + initial begin + count <= 0; + reset_n <= 0; + end + always @(posedge clk_74a) begin + count <= count + 1'b1; + + if(count[15]) begin + // exit reset + reset_n <= 1; + end + end + + // convert 24-bit rgb data to 12-bit DDR for ARISTOTLE + wire [23:0] video_rgb; + wire video_rgb_clock; + wire video_rgb_clock_90; + wire video_de; + wire video_skip; + wire video_vs; + wire video_hs; + + mf_ddio_bidir_12 isco + ( + .oe ( 1'b1 ), + .datain_h ( video_rgb[23:12] ), + .datain_l ( video_rgb[11:0] ), + .outclock ( video_rgb_clock ), + .padio ( scal_ddio_12 ) + ); + + wire [11:0] scal_ddio_12; + assign scal_vid = scal_ddio_12; + + mf_ddio_bidir_12 iscc + ( + .oe ( 1'b1 ), + .datain_h ( {video_vs, video_hs, video_de, video_skip} ), + .datain_l ( {video_vs, video_hs, video_de, video_skip} ), + .outclock ( video_rgb_clock ), + .padio ( scal_ddio_ctrl ) + ); + + wire [3:0] scal_ddio_ctrl; + + assign scal_vs = scal_ddio_ctrl[3]; + assign scal_hs = scal_ddio_ctrl[2]; + assign scal_de = scal_ddio_ctrl[1]; + assign scal_skip = scal_ddio_ctrl[0]; + + mf_ddio_bidir_12 isclk + ( + .oe ( 1'b1 ), + .datain_h ( 1'b1 ), + .datain_l ( 1'b0 ), + .outclock ( video_rgb_clock_90 ), + .padio ( scal_clk ) + ); + + // controller data (pad) controller. + wire [31:0] cont1_key; + wire [31:0] cont2_key; + wire [31:0] cont3_key; + wire [31:0] cont4_key; + wire [31:0] cont1_joy; + wire [31:0] cont2_joy; + wire [31:0] cont3_joy; + wire [31:0] cont4_joy; + wire [15:0] cont1_trig; + wire [15:0] cont2_trig; + wire [15:0] cont3_trig; + wire [15:0] cont4_trig; + + io_pad_controller ipm + ( + .clk ( clk_74a ), + .reset_n ( reset_n ), + + .pad_1wire ( bridge_1wire ), + + .cont1_key ( cont1_key ), + .cont2_key ( cont2_key ), + .cont3_key ( cont3_key ), + .cont4_key ( cont4_key ), + .cont1_joy ( cont1_joy ), + .cont2_joy ( cont2_joy ), + .cont3_joy ( cont3_joy ), + .cont4_joy ( cont4_joy ), + .cont1_trig ( cont1_trig ), + .cont2_trig ( cont2_trig ), + .cont3_trig ( cont3_trig ), + .cont4_trig ( cont4_trig ) + ); + + // virtual pmp bridge + wire bridge_endian_little; + wire [31:0] bridge_addr; + wire bridge_rd; + wire [31:0] bridge_rd_data; + wire bridge_wr; + wire [31:0] bridge_wr_data; + + io_bridge_peripheral ibs + ( + .clk ( clk_74a ), + .reset_n ( reset_n ), + + .endian_little ( bridge_endian_little ), + + .pmp_addr ( bridge_addr ), + .pmp_rd ( bridge_rd ), + .pmp_rd_data ( bridge_rd_data ), + .pmp_wr ( bridge_wr ), + .pmp_wr_data ( bridge_wr_data ), + + .phy_spimosi ( bridge_spimosi ), + .phy_spimiso ( bridge_spimiso ), + .phy_spiclk ( bridge_spiclk ), + .phy_spiss ( bridge_spiss ) + ); + + /////////////////////////////////////////////////// + // instantiate the user core top-level + core_top ic + ( + // physical connections + .clk_74a ( clk_74a ), + .clk_74b ( clk_74b ), + + .cart_tran_bank2 ( cart_tran_bank2 ), + .cart_tran_bank2_dir ( cart_tran_bank2_dir ), + .cart_tran_bank3 ( cart_tran_bank3 ), + .cart_tran_bank3_dir ( cart_tran_bank3_dir ), + .cart_tran_bank1 ( cart_tran_bank1 ), + .cart_tran_bank1_dir ( cart_tran_bank1_dir ), + .cart_tran_bank0 ( cart_tran_bank0 ), + .cart_tran_bank0_dir ( cart_tran_bank0_dir ), + .cart_tran_pin30 ( cart_tran_pin30 ), + .cart_tran_pin30_dir ( cart_tran_pin30_dir ), + .cart_pin30_pwroff_reset ( cart_pin30_pwroff_reset ), + .cart_tran_pin31 ( cart_tran_pin31 ), + .cart_tran_pin31_dir ( cart_tran_pin31_dir ), + + .port_ir_rx ( port_ir_rx ), + .port_ir_tx ( port_ir_tx ), + .port_ir_rx_disable ( port_ir_rx_disable ), + + .port_tran_si ( port_tran_si ), + .port_tran_si_dir ( port_tran_si_dir ), + .port_tran_so ( port_tran_so ), + .port_tran_so_dir ( port_tran_so_dir ), + .port_tran_sck ( port_tran_sck ), + .port_tran_sck_dir ( port_tran_sck_dir ), + .port_tran_sd ( port_tran_sd ), + .port_tran_sd_dir ( port_tran_sd_dir ), + + .cram0_a ( cram0_a ), + .cram0_dq ( cram0_dq ), + .cram0_wait ( cram0_wait ), + .cram0_clk ( cram0_clk ), + .cram0_adv_n ( cram0_adv_n ), + .cram0_cre ( cram0_cre ), + .cram0_ce0_n ( cram0_ce0_n ), + .cram0_ce1_n ( cram0_ce1_n ), + .cram0_oe_n ( cram0_oe_n ), + .cram0_we_n ( cram0_we_n ), + .cram0_ub_n ( cram0_ub_n ), + .cram0_lb_n ( cram0_lb_n ), + .cram1_a ( cram1_a ), + .cram1_dq ( cram1_dq ), + .cram1_wait ( cram1_wait ), + .cram1_clk ( cram1_clk ), + .cram1_adv_n ( cram1_adv_n ), + .cram1_cre ( cram1_cre ), + .cram1_ce0_n ( cram1_ce0_n ), + .cram1_ce1_n ( cram1_ce1_n ), + .cram1_oe_n ( cram1_oe_n ), + .cram1_we_n ( cram1_we_n ), + .cram1_ub_n ( cram1_ub_n ), + .cram1_lb_n ( cram1_lb_n ), + + .dram_a ( dram_a ), + .dram_ba ( dram_ba ), + .dram_dq ( dram_dq ), + .dram_dqm ( dram_dqm ), + .dram_clk ( dram_clk ), + .dram_cke ( dram_cke ), + .dram_ras_n ( dram_ras_n ), + .dram_cas_n ( dram_cas_n ), + .dram_we_n ( dram_we_n ), + + .sram_a ( sram_a ), + .sram_dq ( sram_dq ), + .sram_oe_n ( sram_oe_n ), + .sram_we_n ( sram_we_n ), + .sram_ub_n ( sram_ub_n ), + .sram_lb_n ( sram_lb_n ), + + .vblank ( vblank ), + .vpll_feed ( vpll_feed ), + + .dbg_tx ( dbg_tx ), + .dbg_rx ( dbg_rx ), + .user1 ( user1 ), + .user2 ( user2 ), + + .aux_sda ( aux_sda ), + .aux_scl ( aux_scl ), + + // logical connections with user core + .video_rgb ( video_rgb ), + .video_rgb_clock ( video_rgb_clock ), + .video_rgb_clock_90 ( video_rgb_clock_90 ), + .video_de ( video_de ), + .video_skip ( video_skip ), + .video_vs ( video_vs ), + .video_hs ( video_hs ), + + .audio_mclk ( scal_audmclk ), + .audio_adc ( scal_audadc ), + .audio_dac ( scal_auddac ), + .audio_lrck ( scal_audlrck ), + + .bridge_endian_little ( bridge_endian_little ), + .bridge_addr ( bridge_addr ), + .bridge_rd ( bridge_rd ), + .bridge_rd_data ( bridge_rd_data ), + .bridge_wr ( bridge_wr ), + .bridge_wr_data ( bridge_wr_data ), + + .cont1_key ( cont1_key ), + .cont2_key ( cont2_key ), + .cont3_key ( cont3_key ), + .cont4_key ( cont4_key ), + .cont1_joy ( cont1_joy ), + .cont2_joy ( cont2_joy ), + .cont3_joy ( cont3_joy ), + .cont4_joy ( cont4_joy ), + .cont1_trig ( cont1_trig ), + .cont2_trig ( cont2_trig ), + .cont3_trig ( cont3_trig ), + .cont4_trig ( cont4_trig ) + ); + +endmodule diff --git a/platform/pocket/bsp/pocket/pinouts/system.tcl b/platform/pocket/bsp/pocket/pinouts/system.tcl new file mode 100644 index 0000000..42534de --- /dev/null +++ b/platform/pocket/bsp/pocket/pinouts/system.tcl @@ -0,0 +1,760 @@ +# ============================================================================== +# Clock Circuitry +# ============================================================================== +set_location_assignment PIN_V15 -to clk_74a +set_location_assignment PIN_H16 -to clk_74b + +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to clk_74a +set_instance_assignment -name IO_STANDARD "1.8 V" -to clk_74b + +# ============================================================================== +# SPI bus with Aristotle +# ============================================================================== +set_location_assignment PIN_T17 -to bridge_spiclk +set_location_assignment PIN_M21 -to bridge_spimiso +set_location_assignment PIN_M20 -to bridge_spimosi +set_location_assignment PIN_L19 -to bridge_1wire +set_location_assignment PIN_H14 -to bridge_spiss + +set_instance_assignment -name IO_STANDARD "1.8 V" -to bridge_spiclk +set_instance_assignment -name IO_STANDARD "1.8 V" -to bridge_spimiso +set_instance_assignment -name IO_STANDARD "1.8 V" -to bridge_spimosi +set_instance_assignment -name IO_STANDARD "1.8 V" -to bridge_1wire +set_instance_assignment -name IO_STANDARD "1.8 V" -to bridge_spiss + +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to bridge_spiclk +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to bridge_spimiso +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to bridge_spimosi +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to bridge_1wire + +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to bridge_spiclk +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to bridge_spimiso +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to bridge_spimosi +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to bridge_1wire + +# ============================================================================== +# Cartridge interface +# ============================================================================== +set_location_assignment PIN_AA9 -to cart_tran_bank0[7] +set_location_assignment PIN_AB8 -to cart_tran_bank0[6] +set_location_assignment PIN_AA8 -to cart_tran_bank0[5] +set_location_assignment PIN_AB7 -to cart_tran_bank0[4] +set_location_assignment PIN_AB6 -to cart_tran_bank0_dir +set_location_assignment PIN_AA10 -to cart_tran_bank1[7] +set_location_assignment PIN_AB10 -to cart_tran_bank1[6] +set_location_assignment PIN_Y10 -to cart_tran_bank1[5] +set_location_assignment PIN_AB11 -to cart_tran_bank1[4] +set_location_assignment PIN_Y11 -to cart_tran_bank1[3] +set_location_assignment PIN_AB12 -to cart_tran_bank1[2] +set_location_assignment PIN_AA12 -to cart_tran_bank1[1] +set_location_assignment PIN_AB13 -to cart_tran_bank1[0] +set_location_assignment PIN_AA13 -to cart_tran_bank1_dir +set_location_assignment PIN_AB15 -to cart_tran_bank2[7] +set_location_assignment PIN_AA15 -to cart_tran_bank2[6] +set_location_assignment PIN_AB17 -to cart_tran_bank2[5] +set_location_assignment PIN_AA17 -to cart_tran_bank2[4] +set_location_assignment PIN_AB18 -to cart_tran_bank2[3] +set_location_assignment PIN_AB20 -to cart_tran_bank2[0] +set_location_assignment PIN_AA19 -to cart_tran_bank2[1] +set_location_assignment PIN_AA18 -to cart_tran_bank2[2] +set_location_assignment PIN_AA14 -to cart_tran_bank2_dir +set_location_assignment PIN_AA20 -to cart_tran_bank3[7] +set_location_assignment PIN_AB21 -to cart_tran_bank3[6] +set_location_assignment PIN_AB22 -to cart_tran_bank3[5] +set_location_assignment PIN_AA22 -to cart_tran_bank3[4] +set_location_assignment PIN_Y21 -to cart_tran_bank3[3] +set_location_assignment PIN_Y22 -to cart_tran_bank3[2] +set_location_assignment PIN_W21 -to cart_tran_bank3[1] +set_location_assignment PIN_W22 -to cart_tran_bank3[0] +set_location_assignment PIN_V21 -to cart_tran_bank3_dir + +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank0[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank0[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank0[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank0[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank0_dir +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank1_dir +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank2_dir +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_bank3_dir + +# ============================================================================== +# GBA CS2#/RES# +# ============================================================================== +set_location_assignment PIN_AB5 -to cart_tran_pin30_dir +set_location_assignment PIN_L8 -to cart_tran_pin30 +set_location_assignment PIN_L17 -to cart_pin30_pwroff_reset + +set_instance_assignment -name IO_STANDARD "1.8 V" -to cart_pin30_pwroff_reset +set_instance_assignment -name IO_STANDARD "1.8 V" -to cart_tran_pin30 +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_pin30_dir + +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cart_pin30_pwroff_reset +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cart_tran_pin30 + +# ============================================================================== +# GBA IRQ/DRQ +# ============================================================================== +set_location_assignment PIN_K9 -to cart_tran_pin31 +set_location_assignment PIN_U22 -to cart_tran_pin31_dir + +set_instance_assignment -name IO_STANDARD "1.8 V" -to cart_tran_pin31 +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to cart_tran_pin31_dir + +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cart_tran_pin31 + +# ============================================================================== +# GBA link port +# ============================================================================== +set_location_assignment PIN_V10 -to port_tran_si +set_location_assignment PIN_V9 -to port_tran_si_dir +set_location_assignment PIN_J11 -to port_tran_so +set_location_assignment PIN_T13 -to port_tran_so_dir +set_location_assignment PIN_AA7 -to port_tran_sck +set_location_assignment PIN_Y9 -to port_tran_sck_dir +set_location_assignment PIN_R9 -to port_tran_sd +set_location_assignment PIN_T9 -to port_tran_sd_dir + +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to port_tran_si +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to port_tran_si_dir +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to port_tran_so_dir +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to port_tran_sck +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to port_tran_sck_dir +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to port_tran_sd +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to port_tran_sd_dir + +set_instance_assignment -name IO_STANDARD "1.8 V" -to port_tran_so + +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to port_tran_so + +# ============================================================================== +# I/O to 6515D Breakout USB UART +# ============================================================================== +set_location_assignment PIN_K21 -to dbg_tx +set_location_assignment PIN_K22 -to dbg_rx + +set_instance_assignment -name IO_STANDARD "1.8 V" -to dbg_rx +set_instance_assignment -name IO_STANDARD "1.8 V" -to dbg_tx + +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to dbg_tx + +# ============================================================================== +# Infrared +# ============================================================================== +set_location_assignment PIN_H10 -to port_ir_rx +set_location_assignment PIN_H11 -to port_ir_tx +set_location_assignment PIN_L18 -to port_ir_rx_disable + +set_instance_assignment -name IO_STANDARD "1.8 V" -to port_ir_tx +set_instance_assignment -name IO_STANDARD "1.8 V" -to port_ir_rx +set_instance_assignment -name IO_STANDARD "1.8 V" -to port_ir_rx_disable + +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to port_ir_tx +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to port_ir_rx_disable +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to port_ir_rx + +# ============================================================================== +# RFU internal I2C bus (DNU) +# ============================================================================== +set_location_assignment PIN_M16 -to aux_scl +set_location_assignment PIN_M18 -to aux_sda + +set_instance_assignment -name IO_STANDARD "1.8 V" -to aux_sda +set_instance_assignment -name IO_STANDARD "1.8 V" -to aux_scl + +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to aux_sda +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to aux_scl + +# ============================================================================== +# I/O pads near jtag connector user can solder to +# ============================================================================== +set_location_assignment PIN_M22 -to user1 +set_location_assignment PIN_L22 -to user2 + +set_instance_assignment -name IO_STANDARD "1.8 V" -to user1 +set_instance_assignment -name IO_STANDARD "1.8 V" -to user2 + +# ============================================================================== +# VBlank output to scaler +# ============================================================================== +set_location_assignment PIN_N19 -to vblank + +set_instance_assignment -name IO_STANDARD "1.8 V" -to vblank + +# ============================================================================== +# Video output to the scaler +# ============================================================================== +set_location_assignment PIN_H15 -to scal_audadc +set_location_assignment PIN_K19 -to scal_auddac +set_location_assignment PIN_K17 -to scal_audlrck +set_location_assignment PIN_K16 -to scal_audmclk +set_location_assignment PIN_R17 -to scal_clk +set_location_assignment PIN_N20 -to scal_de +set_location_assignment PIN_P17 -to scal_hs +set_location_assignment PIN_N21 -to scal_skip +set_location_assignment PIN_T15 -to scal_vs +set_location_assignment PIN_R16 -to scal_vid[11] +set_location_assignment PIN_R15 -to scal_vid[10] +set_location_assignment PIN_R22 -to scal_vid[9] +set_location_assignment PIN_T22 -to scal_vid[8] +set_location_assignment PIN_T18 -to scal_vid[7] +set_location_assignment PIN_T19 -to scal_vid[6] +set_location_assignment PIN_T20 -to scal_vid[5] +set_location_assignment PIN_P19 -to scal_vid[4] +set_location_assignment PIN_P18 -to scal_vid[3] +set_location_assignment PIN_N16 -to scal_vid[2] +set_location_assignment PIN_P22 -to scal_vid[1] +set_location_assignment PIN_R21 -to scal_vid[0] + +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_audadc +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_auddac +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_audlrck +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_audmclk +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_clk +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_de +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_hs +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_skip +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[10] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[11] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[2] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[3] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[4] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[5] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[6] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[7] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[8] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vid[9] +set_instance_assignment -name IO_STANDARD "1.8 V" -to scal_vs + +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_auddac +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_audlrck +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_audmclk +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_clk +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_de +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_hs +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_skip +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[0] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[10] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[11] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[1] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[2] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[3] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[4] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[5] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[6] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[7] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[8] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vid[9] +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to scal_vs + +# ============================================================================== +# SDRAM, 512mbit x16 +# ============================================================================== +set_location_assignment PIN_J17 -to dram_a[12] +set_location_assignment PIN_F15 -to dram_a[11] +set_location_assignment PIN_C13 -to dram_a[10] +set_location_assignment PIN_G17 -to dram_a[9] +set_location_assignment PIN_J18 -to dram_a[8] +set_location_assignment PIN_F14 -to dram_a[7] +set_location_assignment PIN_E15 -to dram_a[6] +set_location_assignment PIN_E16 -to dram_a[5] +set_location_assignment PIN_F13 -to dram_a[4] +set_location_assignment PIN_E14 -to dram_a[3] +set_location_assignment PIN_F12 -to dram_a[2] +set_location_assignment PIN_D12 -to dram_a[1] +set_location_assignment PIN_D17 -to dram_a[0] +set_location_assignment PIN_E12 -to dram_ba[1] +set_location_assignment PIN_C16 -to dram_ba[0] +set_location_assignment PIN_K20 -to dram_dq[15] +set_location_assignment PIN_G11 -to dram_dq[14] +set_location_assignment PIN_J19 -to dram_dq[13] +set_location_assignment PIN_H13 -to dram_dq[12] +set_location_assignment PIN_G13 -to dram_dq[11] +set_location_assignment PIN_G16 -to dram_dq[10] +set_location_assignment PIN_G15 -to dram_dq[9] +set_location_assignment PIN_J13 -to dram_dq[8] +set_location_assignment PIN_A12 -to dram_dq[7] +set_location_assignment PIN_A13 -to dram_dq[6] +set_location_assignment PIN_B12 -to dram_dq[5] +set_location_assignment PIN_A14 -to dram_dq[4] +set_location_assignment PIN_B13 -to dram_dq[3] +set_location_assignment PIN_A15 -to dram_dq[2] +set_location_assignment PIN_B15 -to dram_dq[1] +set_location_assignment PIN_C15 -to dram_dq[0] +set_location_assignment PIN_D13 -to dram_dqm[0] +set_location_assignment PIN_H18 -to dram_dqm[1] +set_location_assignment PIN_B16 -to dram_cas_n +set_location_assignment PIN_G18 -to dram_cke +set_location_assignment PIN_G12 -to dram_clk +set_location_assignment PIN_B11 -to dram_ras_n +set_location_assignment PIN_C11 -to dram_we_n + +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[12] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[11] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[10] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[9] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[8] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[7] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[6] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[5] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[4] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[3] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[2] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_a[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_ba[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_ba[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[15] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[14] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[13] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[12] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[11] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[10] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[9] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[8] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[7] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[6] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[5] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[4] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[3] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[2] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dq[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dqm[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_dqm[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_cas_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_cke +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_clk +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_ras_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to dram_we_n + +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[12] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[11] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[10] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[9] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[8] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[7] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[6] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_a[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_ba[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_ba[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[15] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[14] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[13] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[12] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[11] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[10] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[9] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[8] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[7] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[6] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dq[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dqm[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_dqm[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_cas_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_cke +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_ras_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to dram_we_n + +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to dram_clk + +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[2] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[3] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[4] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[5] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[6] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[7] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[8] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[9] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[10] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[11] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[12] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[13] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[14] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dq[15] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[2] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[3] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[4] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[5] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[6] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[7] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[8] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[9] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[10] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[11] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_a[12] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_ba[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_ba[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dqm[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_dqm[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_ras_n +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_cas_n +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dram_we_n +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[0] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[1] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[2] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[3] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[4] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[5] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[6] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[7] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[8] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[9] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[10] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[11] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[12] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[13] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[14] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to dram_dq[15] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[0] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[1] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[2] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[3] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[4] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[5] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[6] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[7] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[8] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[9] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[10] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[11] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[12] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[13] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[14] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to dram_dq[15] +set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|dram_* + +# ============================================================================== +# Cellular PSRAM 0 - 64mbit x2 dual die per chip +# ============================================================================== +set_location_assignment PIN_H8 -to cram0_a[21] +set_location_assignment PIN_H9 -to cram0_a[20] +set_location_assignment PIN_B7 -to cram0_a[19] +set_location_assignment PIN_B6 -to cram0_a[18] +set_location_assignment PIN_C6 -to cram0_a[17] +set_location_assignment PIN_H6 -to cram0_a[16] +set_location_assignment PIN_J9 -to cram0_dq[15] +set_location_assignment PIN_L7 -to cram0_dq[14] +set_location_assignment PIN_F9 -to cram0_dq[13] +set_location_assignment PIN_E7 -to cram0_dq[12] +set_location_assignment PIN_A8 -to cram0_dq[11] +set_location_assignment PIN_D9 -to cram0_dq[10] +set_location_assignment PIN_A10 -to cram0_dq[9] +set_location_assignment PIN_C9 -to cram0_dq[8] +set_location_assignment PIN_J7 -to cram0_dq[7] +set_location_assignment PIN_G6 -to cram0_dq[6] +set_location_assignment PIN_F10 -to cram0_dq[5] +set_location_assignment PIN_E9 -to cram0_dq[4] +set_location_assignment PIN_D7 -to cram0_dq[3] +set_location_assignment PIN_A9 -to cram0_dq[2] +set_location_assignment PIN_C8 -to cram0_dq[1] +set_location_assignment PIN_B10 -to cram0_dq[0] +set_location_assignment PIN_J8 -to cram0_adv_n +set_location_assignment PIN_B5 -to cram0_ce0_n +set_location_assignment PIN_E10 -to cram0_ce1_n +set_location_assignment PIN_G10 -to cram0_clk +set_location_assignment PIN_F7 -to cram0_cre +set_location_assignment PIN_A5 -to cram0_lb_n +set_location_assignment PIN_D6 -to cram0_oe_n +set_location_assignment PIN_A7 -to cram0_ub_n +set_location_assignment PIN_K7 -to cram0_wait +set_location_assignment PIN_G8 -to cram0_we_n + +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[2] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[3] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[4] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[5] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[6] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[7] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[8] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[9] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[10] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[11] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[12] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[13] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[14] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_dq[15] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_a[16] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_a[17] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_a[18] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_a[19] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_a[20] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_a[21] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_adv_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_ce0_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_ce1_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_clk +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_cre +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_lb_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_oe_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_ub_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_wait +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram0_we_n + +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[6] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[7] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[8] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[9] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[10] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[11] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[12] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[13] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[14] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_dq[15] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_a[16] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_a[17] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_a[18] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_a[19] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_a[20] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_a[21] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_adv_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_ce0_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_ce1_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_cre +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_lb_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_oe_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_ub_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_wait +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram0_we_n + +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to cram0_clk + +# ============================================================================== +# Cellular PSRAM 1 - 64mbit x2 dual die per chip +# ============================================================================== +set_location_assignment PIN_Y3 -to cram1_a[21] +set_location_assignment PIN_AA2 -to cram1_a[20] +set_location_assignment PIN_L2 -to cram1_a[19] +set_location_assignment PIN_N1 -to cram1_a[18] +set_location_assignment PIN_U1 -to cram1_a[17] +set_location_assignment PIN_U2 -to cram1_a[16] +set_location_assignment PIN_W8 -to cram1_dq[15] +set_location_assignment PIN_U6 -to cram1_dq[14] +set_location_assignment PIN_R7 -to cram1_dq[13] +set_location_assignment PIN_R6 -to cram1_dq[12] +set_location_assignment PIN_P7 -to cram1_dq[11] +set_location_assignment PIN_N6 -to cram1_dq[10] +set_location_assignment PIN_C2 -to cram1_dq[9] +set_location_assignment PIN_D3 -to cram1_dq[8] +set_location_assignment PIN_V6 -to cram1_dq[7] +set_location_assignment PIN_U7 -to cram1_dq[6] +set_location_assignment PIN_M6 -to cram1_dq[5] +set_location_assignment PIN_R5 -to cram1_dq[4] +set_location_assignment PIN_P6 -to cram1_dq[3] +set_location_assignment PIN_E2 -to cram1_dq[2] +set_location_assignment PIN_G2 -to cram1_dq[1] +set_location_assignment PIN_C1 -to cram1_dq[0] +set_location_assignment PIN_U8 -to cram1_adv_n +set_location_assignment PIN_N2 -to cram1_ce0_n +set_location_assignment PIN_T8 -to cram1_ce1_n +set_location_assignment PIN_W2 -to cram1_clk +set_location_assignment PIN_T7 -to cram1_cre +set_location_assignment PIN_L1 -to cram1_lb_n +set_location_assignment PIN_M7 -to cram1_oe_n +set_location_assignment PIN_G1 -to cram1_ub_n +set_location_assignment PIN_W9 -to cram1_wait +set_location_assignment PIN_AA1 -to cram1_we_n + +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[2] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[3] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[4] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[5] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[6] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[7] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[8] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[9] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[10] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[11] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[12] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[13] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[14] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_dq[15] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_a[16] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_a[17] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_a[18] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_a[19] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_a[20] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_a[21] +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_adv_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_ce0_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_ce1_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_clk +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_cre +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_lb_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_oe_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_ub_n +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_wait +set_instance_assignment -name IO_STANDARD "1.8 V" -to cram1_we_n + +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[6] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[7] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[8] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[9] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[10] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[11] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[12] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[13] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[14] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_dq[15] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_a[16] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_a[17] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_a[18] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_a[19] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_a[20] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_a[21] +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_adv_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_ce0_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_ce1_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_cre +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_lb_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_oe_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_ub_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_wait +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to cram1_we_n + +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to cram1_clk + +# ============================================================================== +# SRAM, 1mbit x16 +# ============================================================================== +set_location_assignment PIN_V16 -to sram_a[16] +set_location_assignment PIN_U12 -to sram_a[15] +set_location_assignment PIN_U15 -to sram_a[14] +set_location_assignment PIN_R10 -to sram_a[13] +set_location_assignment PIN_V14 -to sram_a[12] +set_location_assignment PIN_T10 -to sram_a[11] +set_location_assignment PIN_U11 -to sram_a[10] +set_location_assignment PIN_Y14 -to sram_a[9] +set_location_assignment PIN_U13 -to sram_a[8] +set_location_assignment PIN_Y19 -to sram_a[7] +set_location_assignment PIN_P8 -to sram_a[6] +set_location_assignment PIN_V19 -to sram_a[5] +set_location_assignment PIN_N9 -to sram_a[4] +set_location_assignment PIN_U21 -to sram_a[3] +set_location_assignment PIN_M8 -to sram_a[2] +set_location_assignment PIN_M9 -to sram_a[1] +set_location_assignment PIN_T14 -to sram_a[0] +set_location_assignment PIN_Y15 -to sram_dq[15] +set_location_assignment PIN_W16 -to sram_dq[14] +set_location_assignment PIN_Y16 -to sram_dq[13] +set_location_assignment PIN_Y17 -to sram_dq[12] +set_location_assignment PIN_V20 -to sram_dq[11] +set_location_assignment PIN_V18 -to sram_dq[10] +set_location_assignment PIN_U20 -to sram_dq[9] +set_location_assignment PIN_U16 -to sram_dq[8] +set_location_assignment PIN_R12 -to sram_dq[7] +set_location_assignment PIN_V13 -to sram_dq[6] +set_location_assignment PIN_T12 -to sram_dq[5] +set_location_assignment PIN_W19 -to sram_dq[4] +set_location_assignment PIN_Y20 -to sram_dq[3] +set_location_assignment PIN_P14 -to sram_dq[2] +set_location_assignment PIN_P9 -to sram_dq[1] +set_location_assignment PIN_N8 -to sram_dq[0] +set_location_assignment PIN_U17 -to sram_ub_n +set_location_assignment PIN_R11 -to sram_we_n +set_location_assignment PIN_R14 -to sram_oe_n +set_location_assignment PIN_P12 -to sram_lb_n + +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[13] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[14] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[15] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[16] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_a[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[13] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[14] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[15] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_dq[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_lb_n +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_oe_n +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_ub_n +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to sram_we_n + +# ============================================================================== +# Powerup self test (DO NOT USE) +# ============================================================================== +set_location_assignment PIN_P16 -to vpll_feed +set_location_assignment PIN_U10 -to bist + +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to bist +set_instance_assignment -name IO_STANDARD "1.8 V" -to vpll_feed + +set_instance_assignment -name OUTPUT_TERMINATION "SERIES 50 OHM WITHOUT CALIBRATION" -to vpll_feed \ No newline at end of file diff --git a/platform/pocket/bsp/pocket/sys_assign.tcl b/platform/pocket/bsp/pocket/sys_assign.tcl new file mode 100644 index 0000000..101a70d --- /dev/null +++ b/platform/pocket/bsp/pocket/sys_assign.tcl @@ -0,0 +1,71 @@ +# ============================================================================== +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: SOURCE +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +# ============================================================================== +# +# Platform Global/Location/Instance Assignments +# +# ============================================================================== +# Hardware Information +# ============================================================================== +set_global_assignment -name FAMILY "Cyclone V" +set_global_assignment -name DEVICE 5CEBA4F23C8 +set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 + +# ============================================================================== +# Hardware Parameters +# ============================================================================== +set_parameter -name NSX_DEVICE_ID "pocket" +set_parameter -name NSX_DEVICE_NAME "Analogue Pocket" +set_parameter -name NSX_DEVICE_PLATFORM "Intel" +set_parameter -name NSX_DEVICE_MAKER "Analogue" +set_parameter -name NSX_DEVICE_USE_HPS OFF + +# ============================================================================== +# Setup BSP +# ============================================================================== +set_global_assignment -library "framework" -name SOURCE_TCL_SCRIPT_FILE "../platform/pocket/bsp/setup.tcl" + +# ============================================================================== +# Classic Timing Assignments +# ============================================================================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# ============================================================================== +# Assembler Assignments +# ============================================================================== +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name USE_CONFIGURATION_DEVICE ON +set_global_assignment -name ENABLE_OCT_DONE OFF + +# ============================================================================== +# Fitter Assignments +# ============================================================================== +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_100MHZ + +# ============================================================================== +# Power Estimation Assignments +# ============================================================================== +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# ============================================================================== +# Advanced I/O Timing Assignments +# ============================================================================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# ============================================================================== +# Scripts +# ============================================================================== +set_global_assignment -library "framework" -name PRE_FLOW_SCRIPT_FILE "quartus_sh:$PLATFORM_ROOT/scripts/pre_flow.tcl" +set_global_assignment -library "framework" -name POST_FLOW_SCRIPT_FILE "quartus_sh:$PLATFORM_ROOT/scripts/post_flow.tcl" diff --git a/platform/pocket/bsp/pocket/sys_constr.sdc b/platform/pocket/bsp/pocket/sys_constr.sdc new file mode 100644 index 0000000..736927c --- /dev/null +++ b/platform/pocket/bsp/pocket/sys_constr.sdc @@ -0,0 +1,108 @@ +# ============================================================================== +# Quartus Prime Synopsys Design Constraint File +# Generated by OpenGateware - Gateman CLI v0.1.0 +# ============================================================================== +# Analogue Pocket SDC settings +# +# Do not edit this file +# Add your own constraints in the sdc in the project directory +# ============================================================================== +# +# DEVICE "5CEBA4F23C8" +# +# ============================================================================== +# Time Information +# ============================================================================== +set_time_format -unit ns -decimal_places 3 + +# ============================================================================== +# Create Clock +# ============================================================================== +create_clock -name clk_74a -period 13.468 [get_ports clk_74a] +create_clock -name clk_74b -period 13.468 [get_ports clk_74b] +create_clock -name bridge_spiclk -period 13.468 [get_ports bridge_spiclk] + +# ============================================================================== +# Create Generated Clock +# ============================================================================== +derive_pll_clocks -create_base_clocks + +# ============================================================================== +# Set Clock Latency +# ============================================================================== + +# ============================================================================== +# Set Clock Uncertainty +# ============================================================================== +derive_clock_uncertainty + +# ============================================================================== +# Set Input Delay +# ============================================================================== + +# ============================================================================== +# Set Output Delay +# ============================================================================== +# tDH, hold time, spec is 0.8ns +#set_output_delay -clock dram_clk -min -0.8 [get_ports {dram_a[*] dram_ba[*] dram_cke dram_dqm[*] dram_dq[*] dram_ras_n dram_cas_n dram_we_n}] +# tDS, setup time, spec is 1.5ns +#set_output_delay -clock dram_clk -max 1.5 [get_ports {dram_a[*] dram_ba[*] dram_cke dram_dqm[*] dram_dq[*] dram_ras_n dram_cas_n dram_we_n}] + +# ============================================================================== +# Set Clock Groups +# ============================================================================== +set_clock_groups -asynchronous \ + -group { bridge_spiclk } \ + -group { clk_74a } \ + -group { clk_74b } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|general[2].gpll~PLL_OUTPUT_COUNTER|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|general[4].gpll~PLL_OUTPUT_COUNTER|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|general[5].gpll~PLL_OUTPUT_COUNTER|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|cyclonev_pll|counter[1].output_counter|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|cyclonev_pll|counter[2].output_counter|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|cyclonev_pll|counter[3].output_counter|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|cyclonev_pll|counter[4].output_counter|divclk } \ + -group { ic|core_pll|core_pll_inst|altera_pll_i|cyclonev_pll|counter[5].output_counter|divclk } \ + -group { ic|u_pocket_audio_mixer|audio_pll|mf_audio_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk } \ + -group { ic|u_pocket_audio_mixer|audio_pll|mf_audio_pll_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk } + +# ============================================================================== +# Set False Path +# ============================================================================== +set_false_path -from [get_ports {bridge_1wire}] +set_false_path -from [get_ports {bridge_spimiso}] +set_false_path -from [get_ports {bridge_spimosi}] +set_false_path -from [get_ports {bridge_spiss}] + +set_false_path -to [get_ports {bridge_1wire}] +set_false_path -to [get_ports {bridge_spimiso}] +set_false_path -to [get_ports {bridge_spimosi}] +set_false_path -to [get_ports {scal_auddac}] +set_false_path -to [get_ports {scal_audlrck}] +set_false_path -to [get_ports {scal_audmclk}] +set_false_path -to [get_ports {scal_clk}] +set_false_path -to [get_ports {scal_de}] +set_false_path -to [get_ports {scal_hs}] +set_false_path -to [get_ports {scal_skip}] +set_false_path -to [get_ports {scal_vid[*]}] +set_false_path -to [get_ports {scal_vs}] + +# ============================================================================== +# Set Multicycle Path +# ============================================================================== + +# ============================================================================== +# Set Maximum Delay +# ============================================================================== + +# ============================================================================== +# Set Minimum Delay +# ============================================================================== + +# ============================================================================== +# Set Input Transition +# ============================================================================== diff --git a/platform/pocket/bsp/setup.tcl b/platform/pocket/bsp/setup.tcl new file mode 100644 index 0000000..61e9e97 --- /dev/null +++ b/platform/pocket/bsp/setup.tcl @@ -0,0 +1,55 @@ +# ============================================================================== +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: SOURCE +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +# ============================================================================== + +# ============================================================================== +# Parameters Assignments +# ============================================================================== +set FRAMEWORK_ID "pocket" +set FRAMEWORK_NAME "Analogue Pocket" +set DEVICE_FAMILY [get_global_assignment -name FAMILY] +set DEVICE_ID [get_parameter -name NSX_DEVICE_ID] + +set BUILD_ROOT "../.build" +set PKG_ROOT "../pkg" +set RTL_ROOT "../rtl" +set PLATFORM_ROOT "../platform/$FRAMEWORK_ID" +set TARGET_ROOT "../target/$FRAMEWORK_ID" +set BSP_ROOT "$PLATFORM_ROOT/bsp/$DEVICE_ID" + +# ============================================================================== +# System and Core Top Level, Pinout and Constrains +# ============================================================================== +set_global_assignment -library "framework" -name SYSTEMVERILOG_FILE "$BSP_ROOT/apf_top.sv" +set_global_assignment -library "framework" -name SDC_FILE "$BSP_ROOT/sys_constr.sdc" +set_global_assignment -library "framework" -name SOURCE_TCL_SCRIPT_FILE "$PLATFORM_ROOT/pkgIndex.tcl" +set_global_assignment -library "framework" -name QIP_FILE "$TARGET_ROOT/core.qip" +set BOARD_PINS [glob -nocomplain -types f [file join $BSP_ROOT/pinouts *.tcl]] +foreach pinout $BOARD_PINS { + set_global_assignment -library "framework" -name SOURCE_TCL_SCRIPT_FILE \"$pinout\" +} + +# Check if build_id.vh exists +checkBuildID + +# ============================================================================== +# Framework Assignments +# ============================================================================== + +# ============================================================================== +# Classic Timing Assignments +# ============================================================================== +set QUARTUS_VERSION [lindex $quartus(version) 1] +set VERSION_COMPONENTS [split $QUARTUS_VERSION "."] +set VERSION_MAJOR [lindex $VERSION_COMPONENTS 0] + +if {$VERSION_MAJOR > 17} { + set_global_assignment -name TIMING_ANALYZER_MULTICORNER_ANALYSIS ON + set_global_assignment -name TIMING_ANALYZER_REPORT_WORST_CASE_TIMING_PATHS OFF + set_global_assignment -name DISABLE_LEGACY_TIMING_ANALYZER OFF +} else { + set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON + set_global_assignment -name TIMEQUEST_REPORT_WORST_CASE_TIMING_PATHS OFF +} diff --git a/platform/pocket/helpers/synch_2.sv b/platform/pocket/helpers/synch_2.sv new file mode 100644 index 0000000..a3b3db8 --- /dev/null +++ b/platform/pocket/helpers/synch_2.sv @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// 2-stage synchronizer +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2022, Analogue Enterprises Limited +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// This creates a pipeline where each signal holds the value of the signal that +// was one clock cycle earlier. +// +// It effectively delays the 'i' input by two clock cycles and propagates it +// to the 'o' output. +// +// Useful for tasks such as synchronizing data or creating a 2-stage pipeline +// register. +//------------------------------------------------------------------------------ +// altera message_off 10036 + +`default_nettype none +`timescale 1ns/1ps + +module synch_2 + #( + parameter WIDTH = 1 + ) ( + input logic [WIDTH-1:0] i, //! Input Signal + output logic [WIDTH-1:0] o, //! Synchronized Output + input logic clk, //! Clock To Synchronize On + output logic rise, //! One-Cycle Rising Edge Pulse + output logic fall //! One-Cycle Falling Edge Pulse + ); + + logic [WIDTH-1:0] s1, s2; + + always_ff @(posedge clk) begin + {s2, o, s1} <= {o, s1, i}; + end + + generate + if(WIDTH == 1) begin : genEdges + assign rise = o & ~s2; + assign fall = ~o & s2; + end + else begin : genNoEdges + assign rise = 1'b0; + assign fall = 1'b0; + end + endgenerate + +endmodule diff --git a/platform/pocket/helpers/synch_3.sv b/platform/pocket/helpers/synch_3.sv new file mode 100644 index 0000000..65a887e --- /dev/null +++ b/platform/pocket/helpers/synch_3.sv @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// 3-stage synchronizer +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2022, Analogue Enterprises Limited +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// This creates a pipeline where each signal holds the value of the signal that +// was one clock cycle earlier. +// +// It effectively delays the 'i' input by three clock cycles and propagates it +// to the 'o' output. +// +// Useful for tasks such as synchronizing data or creating a 3-stage pipeline +// register. +//------------------------------------------------------------------------------ +// altera message_off 10036 + +`default_nettype none +`timescale 1ns/1ps + +module synch_3 + #( + parameter WIDTH = 1 + ) ( + input logic [WIDTH-1:0] i, //! Input Signal + output logic [WIDTH-1:0] o, //! Synchronized Output + input logic clk, //! Clock To Synchronize On + output logic rise, //! One-Cycle Rising Edge Pulse + output logic fall //! One-Cycle Falling Edge Pulse + ); + + logic [WIDTH-1:0] s1, s2, s3; + + always_ff @(posedge clk) begin + {s3, o, s2, s1} <= {o, s2, s1, i}; + end + + generate + if(WIDTH == 1) begin : genEdges + assign rise = o & ~s3; + assign fall = ~o & s3; + end + else begin : genNoEdges + assign rise = 1'b0; + assign fall = 1'b0; + end + endgenerate + +endmodule diff --git a/platform/pocket/interface/analog2dpad.sv b/platform/pocket/interface/analog2dpad.sv new file mode 100644 index 0000000..4f8584b --- /dev/null +++ b/platform/pocket/interface/analog2dpad.sv @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Analogue Joystick to DPAD Controller +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// Uy | 0x00 +// Lx ++ Rx | 0x00 > 0x80 < 0xFF +// Dy | 0xFF +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module analog2dpad + #( + parameter [7:0] CENTER = 8'h80, //! Analog Center Value + parameter [7:0] DEADZONE = 8'h10 //! Set Controller Deadzone + ) ( + input logic clk_sys, //! System Clock + input logic [3:0] pad_type, //! System Clock + input logic [7:0] joy_lx, joy_ly, //! Left Analog X/Y + input logic [7:0] joy_rx, joy_ry, //! Right Analog X/Y + output logic joy_up, joy_down, //! D-PAD Signals + output logic joy_left, joy_right //! D-PAD Signals + ); + + //!------------------------------------------------------------------------- + //! Analog Stick + //!------------------------------------------------------------------------- + logic ljoy_u, ljoy_d, ljoy_l, ljoy_r; + logic rjoy_u, rjoy_d, rjoy_l, rjoy_r; + + always_ff @(posedge clk_sys) begin + //! Left Analog Stick + ljoy_l <= (joy_lx < (CENTER - DEADZONE)); + ljoy_r <= (joy_lx > (CENTER + DEADZONE)); + ljoy_u <= (joy_ly < (CENTER - DEADZONE)); + ljoy_d <= (joy_ly > (CENTER + DEADZONE)); + //! Right Analog Stick + rjoy_l <= (joy_rx < (CENTER - DEADZONE)); + rjoy_r <= (joy_rx > (CENTER + DEADZONE)); + rjoy_u <= (joy_ry < (CENTER - DEADZONE)); + rjoy_d <= (joy_ry > (CENTER + DEADZONE)); + end + + //!------------------------------------------------------------------------- + //! Combine Left or Right Analog Stick into DPAD + //!------------------------------------------------------------------------- + assign joy_left = (pad_type == 4'h3) ? (ljoy_l | rjoy_l) : 1'b0; + assign joy_right = (pad_type == 4'h3) ? (ljoy_r | rjoy_r) : 1'b0; + assign joy_up = (pad_type == 4'h3) ? (ljoy_u | rjoy_u) : 1'b0; + assign joy_down = (pad_type == 4'h3) ? (ljoy_d | rjoy_d) : 1'b0; + +endmodule diff --git a/platform/pocket/interface/data_loader.sv b/platform/pocket/interface/data_loader.sv new file mode 100644 index 0000000..709520d --- /dev/null +++ b/platform/pocket/interface/data_loader.sv @@ -0,0 +1,214 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Data Loader +// +// Copyright (c) 2022, Adam Gastineau +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// Data loader: Takes APF bridge writes, sends them to storage. +// +// Takes 32-bit words from APF and splits them into four / OUTPUT_WORD_SIZE words. +// You can set the cycle delay by adjusting WRITE_MEM_CLOCK_DELAY. +//------------------------------------------------------------------------------ +// altera message_off 10230 + +`default_nettype none +`timescale 1ns/1ps + +module data_loader + #( + // Upper 4 bits of address + parameter ADDRESS_MASK_UPPER_4 = 0, + parameter ADDRESS_SIZE = 28, + // Number of clk_memory cycles to delay each write output + // Min 4. Component will assert this value is within the valid range + // Be aware that APF sends data every ~75 74MHz cycles, so you cannot send data slower than this + parameter WRITE_MEM_CLOCK_DELAY = 4, + // Number of clk_memory cycles to hold the write_en signal high + // Min 1. Component will assert this value is within the valid range + parameter WRITE_MEM_EN_CYCLE_LENGTH = 1, + // Word size in number of bytes. Can either be 1 (output 8 bits), or 2 (output 16 bits) + // Component will assert this value is within the valid range + parameter OUTPUT_WORD_SIZE = 1 + ) ( + input wire clk_74a, + input wire clk_memory, + + input wire bridge_wr, + input wire bridge_endian_little, + input wire [31:0] bridge_addr, + input wire [31:0] bridge_wr_data, + + // These outputs are synced to the memory clock + output reg write_en = 0, + output reg [ADDRESS_SIZE-1:0] write_addr = 0, + output reg [8 * OUTPUT_WORD_SIZE - 1:0] write_data = 0 + ); + +`define MAX(x, y) ((x > y) ? x : y) + + localparam WORD_SIZE = 8 * OUTPUT_WORD_SIZE; + // Only use the lower 28 bits of the address + localparam FIFO_SIZE = WORD_SIZE + 28; + + wire mem_empty; + + wire [FIFO_SIZE - 1:0] fifo_out; + + reg read_req = 0; + reg write_req = 0; + reg [31:0] shift_data; + reg [27:0] buff_bridge_addr; + + wire [FIFO_SIZE - 1:0] fifo_in = {shift_data[WORD_SIZE-1:0], buff_bridge_addr[27:0]}; + + dcfifo #( + .clocks_are_synchronized ( "FALSE" ), + .intended_device_family ( "Cyclone V" ), + .lpm_numwords ( 4 ), + .lpm_showahead ( "OFF" ), + .lpm_type ( "dcfifo" ), + .lpm_width ( FIFO_SIZE ), + .lpm_widthu ( 2 ), + .overflow_checking ( "OFF" ), + .rdsync_delaypipe ( 5 ), + .underflow_checking ( "OFF" ), + .use_eab ( "OFF" ), + .wrsync_delaypipe ( 5 ) + ) dcfifo_component ( + .data ( fifo_in ), + .rdclk ( clk_memory ), + .rdreq ( read_req ), + .wrclk ( clk_74a ), + .wrreq ( write_req ), + .q ( fifo_out ), + .rdempty ( mem_empty ) + ); + + /// APF to Mem clock + reg prev_bridge_wr = 0; + reg [2:0] write_count = 0; + reg [2:0] write_state = 0; + + localparam WRITE_START = 1; + localparam WRITE_REQ_SHIFT = 2; + + // Receive APF writes and buffer them into the memory clock domain + always @(posedge clk_74a) begin + prev_bridge_wr <= bridge_wr; + + if (~prev_bridge_wr && bridge_wr && bridge_addr[31:28] == ADDRESS_MASK_UPPER_4) begin + // Beginning APF write to core + write_state <= WRITE_REQ_SHIFT; + write_req <= 1; + write_count <= 0; + shift_data <= bridge_endian_little ? bridge_wr_data : + {bridge_wr_data[7:0], bridge_wr_data[15:8], bridge_wr_data[23:16], bridge_wr_data[31:24]}; + buff_bridge_addr <= bridge_addr[27:0]; + end + + case (write_state) + WRITE_START: begin + write_req <= 1; + write_state <= WRITE_REQ_SHIFT; + end + WRITE_REQ_SHIFT: begin + write_req <= 0; + // We will be writing again in the next cycle + shift_data <= {8'h0, shift_data[31:WORD_SIZE]}; + buff_bridge_addr <= buff_bridge_addr + OUTPUT_WORD_SIZE; + write_count <= write_count + 1; + if (write_count == (4 / OUTPUT_WORD_SIZE) - 1) begin + // Finished write + write_state <= 0; + end + else begin + write_state <= WRITE_START; + end + end + endcase + end + + /// Mem clock to core + reg [5:0] read_state = 0; + + localparam READ_DELAY = 1; + localparam READ_WRITE = 2; + localparam READ_WRITE_EN_CYCLE_OFF = READ_WRITE + WRITE_MEM_EN_CYCLE_LENGTH; + localparam READ_WRITE_END_DEFAULT = WRITE_MEM_CLOCK_DELAY - 1; + // Must use max to prevent READ_WRITE_END from being the same as READ_WRITE_EN_CYCLE_OFF + localparam READ_WRITE_END = `MAX(READ_WRITE_END_DEFAULT, READ_WRITE_EN_CYCLE_OFF + 1); + localparam HAS_DELAY = READ_WRITE_END_DEFAULT > READ_WRITE_EN_CYCLE_OFF; + + always @(posedge clk_memory) begin + if (read_state != 0) begin + read_state <= read_state + 1; + end + else if (~mem_empty) begin + // Start read + read_state <= READ_DELAY; + read_req <= 1; + end + + case (read_state) + READ_DELAY: begin + read_req <= 0; + write_en <= 0; + end + READ_WRITE: begin + // Read data is available + write_en <= 1; + // Lowest 28 bits are the address + write_addr <= fifo_out[27:0]; + write_data <= fifo_out[WORD_SIZE+27:28]; + read_req <= 0; + end + READ_WRITE_EN_CYCLE_OFF: begin + write_en <= 0; + if (!HAS_DELAY) begin + // No extra delay, immediately go back to start + read_state <= 0; + end + end + READ_WRITE_END: begin + read_state <= 0; + end + endcase + end + + initial begin + // Verify parameters + if (WRITE_MEM_CLOCK_DELAY < 4) begin + $error("WRITE_MEM_CLOCK_DELAY has a minimum value of 4. Received %d", WRITE_MEM_CLOCK_DELAY); + end + if (WRITE_MEM_EN_CYCLE_LENGTH < 1 || WRITE_MEM_EN_CYCLE_LENGTH >= WRITE_MEM_CLOCK_DELAY - 2) begin + $error("WRITE_MEM_EN_CYCLE_LENGTH must be between 1 and %d (inclusive, based off of WRITE_MEM_CLOCK_DELAY). Received %d", WRITE_MEM_CLOCK_DELAY - 2 - 1, WRITE_MEM_EN_CYCLE_LENGTH); + end + if (OUTPUT_WORD_SIZE < 1 || OUTPUT_WORD_SIZE > 2) begin + $error("OUTPUT_WORD_SIZE must be 1 or 2. Received %d", OUTPUT_WORD_SIZE); + end + end + +endmodule diff --git a/platform/pocket/interface/data_unloader.sv b/platform/pocket/interface/data_unloader.sv new file mode 100644 index 0000000..629fae8 --- /dev/null +++ b/platform/pocket/interface/data_unloader.sv @@ -0,0 +1,255 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Data Unloader +// +// Copyright (c) 2022, Adam Gastineau +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// Data unloader: Reads from memory, supplies to APF bridge. +// +// Takes four words (bytes or 16-bit words) and sends them as 32-bit words to APF. +// You can set the cycle delay by adjusting READ_MEM_CLOCK_DELAY. +//------------------------------------------------------------------------------ +// altera message_off 10230 + +`default_nettype none +`timescale 1ns/1ps + +module data_unloader + #( + // Upper 4 bits of address + parameter ADDRESS_MASK_UPPER_4 = 0, + parameter ADDRESS_SIZE = 28, + // Number of memory clock cycles it takes for a read to complete + parameter READ_MEM_CLOCK_DELAY = 1, + // Word size in number of bytes. Can either be 1 (input 8 bits), or 2 (input 16 bits) + parameter INPUT_WORD_SIZE = 1 + ) ( + input wire clk_74a, + input wire clk_memory, + + input wire bridge_rd, + input wire bridge_endian_little, + input wire [31:0] bridge_addr, + output reg [31:0] bridge_rd_data = 0, + + // These outputs are synced to the memory clock + output reg read_en = 0, + output reg [ADDRESS_SIZE-1:0] read_addr = 0, + input wire [8 * INPUT_WORD_SIZE - 1:0] read_data + ); + + localparam WORD_SIZE = 8 * INPUT_WORD_SIZE; + + // APF address to memory FIFO + reg [27:0] fifo_address_in = 0; + reg address_read_req = 0; + reg address_write_req = 0; + wire address_empty; + + wire [27:0] fifo_address_out; + + dcfifo #( + .clocks_are_synchronized ( "FALSE" ), + .intended_device_family ( "Cyclone V" ), + .lpm_numwords ( 4 ), + .lpm_showahead ( "OFF" ), + .lpm_type ( "dcfifo" ), + .lpm_width ( 28 ), + .lpm_widthu ( 2 ), + .overflow_checking ( "OFF" ), + .rdsync_delaypipe ( 5 ), + .underflow_checking ( "OFF" ), + .use_eab ( "OFF" ), + .wrsync_delaypipe ( 5 ) + ) fifo_address_req ( + .data ( fifo_address_in ), + .rdclk ( clk_memory ), + .rdreq ( address_read_req ), + .wrclk ( clk_74a ), + .wrreq ( address_write_req ), + .q ( fifo_address_out ), + .rdempty ( address_empty ) + ); + + // Memory output to APF FIFO + reg data_read_req = 0; + reg data_write_req = 0; + wire data_empty; + + reg [WORD_SIZE - 1:0] fifo_data_in = 0; + wire [WORD_SIZE - 1:0] fifo_data_out; + + dcfifo #( + .clocks_are_synchronized ( "FALSE" ), + .intended_device_family ( "Cyclone V" ), + .lpm_numwords ( 4 ), + .lpm_showahead ( "OFF" ), + .lpm_type ( "dcfifo" ), + .lpm_width ( WORD_SIZE ), + .lpm_widthu ( 2 ), + .overflow_checking ( "OFF" ), + .rdsync_delaypipe ( 5 ), + .underflow_checking ( "OFF" ), + .use_eab ( "OFF" ), + .wrsync_delaypipe ( 5 ) + ) fifo_data_response ( + .data ( fifo_data_in ), + .rdclk ( clk_74a ), + .rdreq ( data_read_req ), + .wrclk ( clk_memory ), + .wrreq ( data_write_req ), + .q ( fifo_data_out ), + .rdempty ( data_empty ) + ); + + /// APF side + reg prev_bridge_rd = 0; + reg [2:0] addr_count = 0; + reg [2:0] addr_state = 0; + + localparam ADDR_START = 1; + localparam ADDR_REQ = 2; + + // Receive APF read addresses and buffer them into the memory clock domain + always @(posedge clk_74a) begin + prev_bridge_rd <= bridge_rd; + + if (~prev_bridge_rd && bridge_rd && bridge_addr[31:28] == ADDRESS_MASK_UPPER_4) begin + // Beginning APF read from core + addr_state <= ADDR_REQ; + address_write_req <= 1; + addr_count <= 0; + fifo_address_in <= bridge_addr[27:0]; + end + + case (addr_state) + ADDR_START: begin + address_write_req <= 1; + addr_state <= ADDR_REQ; + end + ADDR_REQ: begin + address_write_req <= 0; + fifo_address_in <= fifo_address_in + INPUT_WORD_SIZE; + addr_count <= addr_count + 1; + if (addr_count == (4 / INPUT_WORD_SIZE) - 1) begin + // Finished write + addr_count <= 0; + addr_state <= 0; + end + else begin + addr_state <= ADDR_START; + end + end + endcase + end + + reg [2:0] data_send_state = 0; + reg [2:0] apf_data_count = 0; + reg [31:0] apf_bridge_write_data = 0; + + wire [31:0] apf_final_data = {fifo_data_out, apf_bridge_write_data[31-WORD_SIZE:0]}; + + localparam READ_DATA_DELAY = 1; + localparam READ_DATA_WRITE = 2; + + // Receive data from memory and write to APF bridge + always @(posedge clk_74a) begin + if (data_send_state != 0) begin + data_send_state <= data_send_state + 1; + end + else if (~data_empty) begin + // Start data read + data_send_state <= READ_DATA_DELAY; + data_read_req <= 1; + apf_data_count <= 0; + end + + case (data_send_state) + READ_DATA_DELAY: begin + data_read_req <= 0; + // Shift current APF data + apf_bridge_write_data <= apf_bridge_write_data >> WORD_SIZE; + end + READ_DATA_WRITE: begin + // Data from memory is available + if (apf_data_count == (4 / INPUT_WORD_SIZE) - 1) begin + // We have all of the data we need, send to APF + bridge_rd_data <= bridge_endian_little ? apf_final_data : { + apf_final_data[7:0], apf_final_data[15:8], apf_final_data[23:16], apf_final_data[31:24] + }; + data_send_state <= 0; + end + else begin + apf_bridge_write_data <= apf_final_data; + data_read_req <= 1; + data_send_state <= READ_DATA_DELAY; + apf_data_count <= apf_data_count + 1; + end + end + endcase + end + + /// Mem side + reg [5:0] data_read_state = 0; + + localparam READ_ADDRESS_DELAY = 1; + localparam READ_MEM_START = 2; + localparam READ_MEM_COMPLETE = READ_MEM_START + READ_MEM_CLOCK_DELAY; + localparam READ_ADDRESS_END = READ_MEM_COMPLETE + 1; + + always @(posedge clk_memory) begin + if (data_read_state != 0) begin + data_read_state <= data_read_state + 1; + end + else if (~address_empty) begin + // Start address read + data_read_state <= READ_ADDRESS_DELAY; + address_read_req <= 1; + end + + case (data_read_state) + READ_ADDRESS_DELAY: begin + address_read_req <= 0; + end + READ_MEM_START: begin + // Address read data is available + read_en <= 1; + read_addr <= fifo_address_out[ADDRESS_SIZE-1:0]; + end + READ_MEM_COMPLETE: begin + // We have data to send to APF + read_en <= 0; + data_write_req <= 1; + fifo_data_in <= read_data; + end + READ_ADDRESS_END: begin + data_write_req <= 0; + data_read_state <= 0; + end + endcase + end + +endmodule diff --git a/platform/pocket/interface/gamepad.sv b/platform/pocket/interface/gamepad.sv new file mode 100644 index 0000000..8554492 --- /dev/null +++ b/platform/pocket/interface/gamepad.sv @@ -0,0 +1,320 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket PAD Controller +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// Shifts the joystick input signal through two stages of registers, +// synchronizing it to the system clock signal, and outputs the synchronized +// joystick outputs +// +// key bitmap: +// [0] dpad_up | [ 8] trig_l1 +// [1] dpad_down | [ 9] trig_r1 +// [2] dpad_left | [10] trig_l2 +// [3] dpad_right | [11] trig_r2 +// [4] face_a | [12] trig_l3 +// [5] face_b | [13] trig_r3 +// [6] face_x | [14] face_select +// [7] face_y | [15] face_start +// [28:16] +// [31:29] type +// +// joy values - unsigned - 0x00 > 0x80 < 0xFF +// [7:0] lstick_x +// [15:8] lstick_y +// [23:16] rstick_x +// [31:24] rstick_y +// +// trigger values - unsigned - 0x00-0xFF +// [7:0] ltrig +// [15:8] rtrig +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module gamepad + #( + parameter JOY_PADS = 1, //! Total Number of Gamepads + parameter JOY_ALT = 0, //! 2 Players Alternate + parameter DEADZONE = 8'h10 //! Set Controller Deadzone + ) ( + input wire clk_sys, //! Clock to Sync To (eg: clk_sys) + //! Pocket PAD Interface + input wire [31:0] cont1_key, cont1_joy, //! Gamepad/Analog Joystick + input wire [31:0] cont2_key, cont2_joy, //! Gamepad/Analog Joystick + input wire [31:0] cont3_key, cont3_joy, //! Gamepad/Analog Joystick + input wire [31:0] cont4_key, cont4_joy, //! Gamepad/Analog Joystick + //! Input DIP Switches + input wire [7:0] inp_sw0, inp_sw1, inp_sw2, inp_sw3, //! DIP Switches + //! Player 1 + output wire p1_up, p1_down, p1_left, p1_right, //! D-PAD + output wire p1_a, p1_b, p1_x, p1_y, //! Face Buttons + output wire p1_l1, p1_l2, p1_l3, p1_se, //! Left Shoulder/Trigger/Analog Buttons/Select + output wire p1_r1, p1_r2, p1_r3, p1_st, //! Right Shoulder/Trigger/Analog Buttons/Start + output wire j1_up, j1_down, j1_left, j1_right, //! Analog 2 DPAD + output wire [7:0] j1_lx, j1_ly, j1_rx, j1_ry, //! Left/Right Analog Stick + //! Player 2 + output wire p2_up, p2_down, p2_left, p2_right, //! D-PAD + output wire p2_a, p2_b, p2_x, p2_y, //! Face Buttons + output wire p2_l1, p2_l2, p2_l3, p2_se, //! Left Shoulder/Trigger/Analog Buttons/Select + output wire p2_r1, p2_r2, p2_r3, p2_st, //! Right Shoulder/Trigger/Analog Buttons/Start + output wire j2_up, j2_down, j2_left, j2_right, //! Analog 2 DPAD + output wire [7:0] j2_lx, j2_ly, j2_rx, j2_ry, //! Left/Right Analog Stick + //! Player 3 + output wire p3_up, p3_down, p3_left, p3_right, //! D-PAD + output wire p3_a, p3_b, p3_x, p3_y, //! Face Buttons + output wire p3_l1, p3_l2, p3_l3, p3_se, //! Left Shoulder/Trigger/Analog Buttons/Select + output wire p3_r1, p3_r2, p3_r3, p3_st, //! Right Shoulder/Trigger/Analog Buttons/Start + output wire j3_up, j3_down, j3_left, j3_right, //! Analog 2 DPAD + output wire [7:0] j3_lx, j3_ly, j3_rx, j3_ry, //! Left/Right Analog Stick + //! Player 4 + output wire p4_up, p4_down, p4_left, p4_right, //! D-PAD + output wire p4_a, p4_b, p4_x, p4_y, //! Face Buttons + output wire p4_l1, p4_l2, p4_l3, p4_se, //! Left Shoulder/Trigger/Analog Buttons/Select + output wire p4_r1, p4_r2, p4_r3, p4_st, //! Right Shoulder/Trigger/Analog Buttons/Start + output wire j4_up, j4_down, j4_left, j4_right, //! Analog 2 DPAD + output wire [7:0] j4_lx, j4_ly, j4_rx, j4_ry, //! Left/Right Analog Stick + //! Single Player or Alternate 2 Players for Arcade + output wire m_up, m_down, m_left, m_right, //! Joystick + output wire m_btn1, m_btn2, m_btn3, m_btn4, //! Y/B/A/X + output wire m_btn5, m_btn6, m_btn7, m_btn8, //! L1/R1/L2/R2 + output wire m_coin, m_coin1, m_coin2, //! Coinage + output wire m_start1, m_start2, //! P1/P2 Start + //! Type + output wire [3:0] p1_type, p2_type, p3_type, p4_type, //! Controller Type + //! Joystick + output wire [15:0] joy_1, joy_2, joy_3, joy_4 //! 16 Buttons Gamepad + ); + + //!------------------------------------------------------------------------- + //! Player 1 + //!------------------------------------------------------------------------- + joypad #(.DEADZONE(DEADZONE)) u_joypad_p1 + ( + .clk_sys ( clk_sys ), + // APF PAD Interface + .cont_key ( cont1_key ), .cont_joy ( cont1_joy ), + // Interface Type + .pad_type ( p1_type ), + // Gamepad + .key_up ( p1_up ), .key_down ( p1_down ), + .key_left ( p1_left ), .key_right ( p1_right ), + .key_y ( p1_y ), .key_x ( p1_x ), + .key_b ( p1_b ), .key_a ( p1_a ), + .key_l1 ( p1_l1 ), .key_r1 ( p1_r1 ), + .key_l2 ( p1_l2 ), .key_r2 ( p1_r2 ), + .key_l3 ( p1_l3 ), .key_r3 ( p1_r3 ), + .key_se ( p1_se ), .key_st ( p1_st ), + // Analog Stick + .joy_up ( j1_up ), .joy_down ( j1_down ), + .joy_left ( j1_left ), .joy_right ( j1_right ), + .joy_lx ( j1_lx ), .joy_ly ( j1_ly ), + .joy_rx ( j1_rx ), .joy_ry ( j1_ry ), + // Combined Gamepad + .joystick ( joy_1 ) + ); + + //!------------------------------------------------------------------------- + //! Player 2 + //!------------------------------------------------------------------------- + generate + if(JOY_PADS >= 2) begin + joypad #(.DEADZONE(DEADZONE)) u_joypad_p2 + ( + .clk_sys ( clk_sys ), + // APF PAD Interface + .cont_key ( cont2_key ), .cont_joy ( cont2_joy ), + // Interface Type + .pad_type ( p2_type ), + // Gamepad + .key_up ( p2_up ), .key_down ( p2_down ), + .key_left ( p2_left ), .key_right ( p2_right ), + .key_y ( p2_y ), .key_x ( p2_x ), + .key_b ( p2_b ), .key_a ( p2_a ), + .key_l1 ( p2_l1 ), .key_r1 ( p2_r1 ), + .key_l2 ( p2_l2 ), .key_r2 ( p2_r2 ), + .key_l3 ( p2_l3 ), .key_r3 ( p2_r3 ), + .key_se ( p2_se ), .key_st ( p2_st ), + // Analog Stick + .joy_up ( j2_up ), .joy_down ( j2_down ), + .joy_left ( j2_left ), .joy_right ( j2_right ), + .joy_lx ( j2_lx ), .joy_ly ( j2_ly ), + .joy_rx ( j2_rx ), .joy_ry ( j2_ry ), + // Combined Gamepad + .joystick ( joy_2 ) + ); + end + else begin + assign { p2_up, p2_down, p2_left, p2_right } = 4'h0; + assign { p2_y , p2_x , p2_b , p2_a } = 4'h0; + assign { p2_l1, p2_r1 , p2_l2 , p2_r2 } = 4'h0; + assign { p2_l3, p2_r3 , p2_se , p2_st } = 4'h0; + assign { j2_up, j2_down, j2_left, j2_right } = 4'h0; + assign { j2_lx, j2_ly , j2_rx , j2_ry } = 32'h0; + assign { p2_type } = 4'h0; + assign { joy_2 } = 16'h0; + end + endgenerate + + //!------------------------------------------------------------------------- + //! Player 3 + //!------------------------------------------------------------------------- + generate + if(JOY_PADS >= 3) begin + joypad #(.DEADZONE(DEADZONE)) u_joypad_p3 + ( + .clk_sys ( clk_sys ), + // APF PAD Interface + .cont_key ( cont3_key ), .cont_joy ( cont3_joy ), + // Interface Type + .pad_type ( p3_type ), + // Gamepad + .key_up ( p3_up ), .key_down ( p3_down ), + .key_left ( p3_left ), .key_right ( p3_right ), + .key_y ( p3_y ), .key_x ( p3_x ), + .key_b ( p3_b ), .key_a ( p3_a ), + .key_l1 ( p3_l1 ), .key_r1 ( p3_r1 ), + .key_l2 ( p3_l2 ), .key_r2 ( p3_r2 ), + .key_l3 ( p3_l3 ), .key_r3 ( p3_r3 ), + .key_se ( p3_se ), .key_st ( p3_st ), + // Analog Stick + .joy_up ( j3_up ), .joy_down ( j3_down ), + .joy_left ( j3_left ), .joy_right ( j3_right ), + .joy_lx ( j3_lx ), .joy_ly ( j3_ly ), + .joy_rx ( j3_rx ), .joy_ry ( j3_ry ), + // Combined Gamepad + .joystick ( joy_3 ) + ); + end + else begin + assign { p3_up, p3_down, p3_left, p3_right } = 4'h0; + assign { p3_y , p3_x , p3_b , p3_a } = 4'h0; + assign { p3_l1, p3_r1 , p3_l2 , p3_r2 } = 4'h0; + assign { p3_l3, p3_r3 , p3_se , p3_st } = 4'h0; + assign { j3_up, j3_down, j3_left, j3_right } = 4'h0; + assign { j3_lx, j3_ly , j3_rx , j3_ry } = 32'h0; + assign { p3_type } = 4'h0; + assign { joy_3 } = 16'h0; + end + endgenerate + + //!------------------------------------------------------------------------- + //! Player 4 + //!------------------------------------------------------------------------- + generate + if(JOY_PADS == 4) begin + joypad #(.DEADZONE(DEADZONE)) u_joypad_p4 + ( + .clk_sys ( clk_sys ), + // APF PAD Interface + .cont_key ( cont4_key ), .cont_joy ( cont4_joy ), + // Interface Type + .pad_type ( p4_type ), + // Gamepad + .key_up ( p4_up ), .key_down ( p4_down ), + .key_left ( p4_left ), .key_right ( p4_right ), + .key_y ( p4_y ), .key_x ( p4_x ), + .key_b ( p4_b ), .key_a ( p4_a ), + .key_l1 ( p4_l1 ), .key_r1 ( p4_r1 ), + .key_l2 ( p4_l2 ), .key_r2 ( p4_r2 ), + .key_l3 ( p4_l3 ), .key_r3 ( p4_r3 ), + .key_se ( p4_se ), .key_st ( p4_st ), + // Analog Stick + .joy_up ( j4_up ), .joy_down ( j4_down ), + .joy_left ( j4_left ), .joy_right ( j4_right ), + .joy_lx ( j4_lx ), .joy_ly ( j4_ly ), + .joy_rx ( j4_rx ), .joy_ry ( j4_ry ), + // Combined Gamepad + .joystick ( joy_4 ) + ); + end + else begin + assign { p4_up, p4_down, p4_left, p4_right } = 4'h0; + assign { p4_y , p4_x , p4_b , p4_a } = 4'h0; + assign { p4_l1, p4_r1 , p4_l2 , p4_r2 } = 4'h0; + assign { p4_l3, p4_r3 , p4_se , p4_st } = 4'h0; + assign { j4_up, j4_down, j4_left, j4_right } = 4'h0; + assign { j4_lx, j4_ly , j4_rx , j4_ry } = 32'h0; + assign { p4_type } = 4'h0; + assign { joy_4 } = 16'h0; + end + endgenerate + + //!------------------------------------------------------------------------- + //! Arcade Layout / 2 Players Alternate + //!------------------------------------------------------------------------- + generate + // Alternate 2 Players for Arcade + if(JOY_PADS == 2 && JOY_ALT == 1) begin + assign m_start1 = p1_st; + assign m_start2 = p2_st; + assign m_coin1 = p1_se; + assign m_coin2 = p2_se; + assign m_coin = p1_se | p2_se; + assign m_up = p1_up | p2_up | j1_up | j2_up; + assign m_down = p1_down | p2_down | j1_down | j2_down; + assign m_left = p1_left | p2_left | j1_left | j2_left; + assign m_right = p1_right | p2_right | j1_right | j2_right; + assign m_btn1 = p1_y | p2_y; + assign m_btn2 = p1_b | p2_b; + assign m_btn3 = p1_a | p2_a; + assign m_btn4 = p1_x | p2_x; + assign m_btn5 = p1_l1 | p2_l1; + assign m_btn6 = p1_r1 | p2_r1; + assign m_btn7 = p1_l2 | p2_l2; + assign m_btn8 = p1_r2 | p2_r2; + end + // Single Players for Arcade + else if(JOY_PADS == 1 && JOY_ALT == 0) begin + assign m_start1 = p1_st; + assign m_coin1 = p1_se; + assign m_coin = p1_se; + assign m_up = p1_up | j1_up; + assign m_down = p1_down | j1_down; + assign m_left = p1_left | j1_left; + assign m_right = p1_right | j1_right; + assign m_btn1 = p1_y; + assign m_btn2 = p1_b; + assign m_btn3 = p1_a; + assign m_btn4 = p1_x; + assign m_btn5 = p1_l1; + assign m_btn6 = p1_r1; + assign m_btn7 = p1_l2; + assign m_btn8 = p1_r2; + assign { m_start2, m_coin2 } = 2'h0; + end + else begin + assign { m_coin } = 1'h0; + assign { m_up, m_down, m_left, m_right } = 4'h0; + assign { m_btn1, m_btn2, m_btn3, m_btn4 } = 4'h0; + assign { m_btn5, m_btn6, m_btn7, m_btn8 } = 4'h0; + assign { m_coin1, m_coin2, m_start1, m_start2 } = 4'h0; + end + endgenerate + +endmodule diff --git a/platform/pocket/interface/interact.sv b/platform/pocket/interface/interact.sv new file mode 100644 index 0000000..4708696 --- /dev/null +++ b/platform/pocket/interface/interact.sv @@ -0,0 +1,191 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Interact Controller for APF bridge +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// altera message_off 10762 + +`default_nettype none +`timescale 1ns/1ps + +module interact + ( + // Clocks and Reset + input wire clk_74a, //! APF Main Clock + input wire clk_sync, //! Clock to Sync to + input wire reset_n, //! APF Reset (Active Low) + // Reset Core + output logic reset_sw, //! Reset Switch + // Service Mode Switch + output logic svc_sw, //! Service Switch + // DIP Switches + output logic [7:0] dip_sw0, //! DIP Switch 1 + output logic [7:0] dip_sw1, //! DIP Switch 2 + output logic [7:0] dip_sw2, //! DIP Switch 3 + output logic [7:0] dip_sw3, //! DIP Switch 4 + // Extra DIP Switches + output logic [7:0] ext_sw0, //! Extra DIP Switch 1 + output logic [7:0] ext_sw1, //! Extra DIP Switch 2 + output logic [7:0] ext_sw2, //! Extra DIP Switch 3 + output logic [7:0] ext_sw3, //! Extra DIP Switch 4 + // Modifiers Switches + output logic [7:0] mod_sw0, //! Modifiers Switch 1 + output logic [7:0] mod_sw1, //! Modifiers Switch 2 + output logic [7:0] mod_sw2, //! Modifiers Switch 3 + output logic [7:0] mod_sw3, //! Modifiers Switch 4 + // Inputs Switches + output logic [7:0] inp_sw0, //! Inputs Switch 1 + output logic [7:0] inp_sw1, //! Inputs Switch 2 + output logic [7:0] inp_sw2, //! Inputs Switch 3 + output logic [7:0] inp_sw3, //! Inputs Switch 4 + // Status (Legacy Support) + output logic [63:0] status, //! MiST/MiSTer Legacy Status Flag + // Filters + output logic [3:0] scnl_sw, //! Scanlines + output logic [3:0] smask_sw, //! ShadowMask + output logic [3:0] afilter_sw, //! Audio Filters + output logic [3:0] vol_att, //! Volume Attenuation + // High Score NVRAM + output logic [15:0] nvram_size, //! High Score Save Size + // Analogizer + output logic [31:0] analogizer_sw, //! Analogizer/SNAC Switches + // Pocket Bridge + input wire [31:0] bridge_addr, + input wire bridge_wr, + input wire [31:0] bridge_wr_data, + input wire bridge_rd, + output logic [31:0] bridge_rd_data = 32'h0 + ); + + //!------------------------------------------------------------------------- + //! Reset Handler + //!------------------------------------------------------------------------- + reg [31:0] reset_counter; + reg reset_timer; + reg core_reset_n = 1'b1; + reg core_reset_r = 1'b1; + + always_ff @(posedge clk_74a) begin + if(reset_timer) begin + reset_counter <= 32'd8000; + core_reset_n <= 1'b0; + end + else begin + if (reset_counter == 32'h0) begin + core_reset_n <= 1'b1; + end + else begin + reset_counter <= reset_counter - 32'h1; + core_reset_n <= 1'b0; + end + end + end + + //!------------------------------------------------------------------------- + //! Read/Write APF Bridge + //!------------------------------------------------------------------------- + reg svc_mode = 1'h0; + reg [31:0] dip_switch = 32'h0; + reg [31:0] ext_switch = 32'h0; + reg [31:0] modifiers = 32'h0; + reg [31:0] filters = 32'h0; + reg [31:0] status_h = 32'h0; + reg [31:0] status_l = 32'h0; + reg [31:0] inputs = 32'h0; + reg [15:0] nvram_sz = 16'h0; + reg [31:0] analogizer = 32'h0; + + always_ff @(posedge clk_74a) begin + reset_timer <= 1'b0; //! Always default this to zero + if(bridge_wr) begin + case(bridge_addr) + 32'hF0000000: begin /* RESET ONLY */ reset_timer <= 1'b1; end //! Reset Core Command + 32'hF0000010: begin svc_mode <= bridge_wr_data[0]; reset_timer <= 1'b1; end //! Service Mode Switch + 32'hF1000000: begin dip_switch <= bridge_wr_data; reset_timer <= 1'b1; end //! DIP Switches + 32'hF2000000: begin modifiers <= bridge_wr_data; end //! Modifiers + 32'hF3000000: begin filters <= bridge_wr_data; end //! A/V Filters + 32'hF4000000: begin ext_switch <= bridge_wr_data; reset_timer <= 1'b1; end //! Extra DIP Switches + 32'hF5000000: begin nvram_sz <= bridge_wr_data[15:0]; end //! NVRAM Size in Bytes + 32'hFA000000: begin status_l <= bridge_wr_data; end //! Status Low [31:0] + 32'hFB000000: begin status_h <= bridge_wr_data; end //! Status High [63:32] + 32'hFC000000: begin inputs <= bridge_wr_data; end //! Inputs + 32'hA0000000: begin analogizer <= bridge_wr_data; end //! Analogizer + endcase + end + if(bridge_rd) begin + case(bridge_addr) + 32'hF0000000: begin bridge_rd_data <= core_reset_r; end + 32'hF0000010: begin bridge_rd_data <= {31'h0, svc_mode}; end + 32'hF1000000: begin bridge_rd_data <= dip_switch; end + 32'hF2000000: begin bridge_rd_data <= modifiers; end + 32'hF3000000: begin bridge_rd_data <= filters; end + 32'hF4000000: begin bridge_rd_data <= ext_switch; end + 32'hF5000000: begin bridge_rd_data <= {16'h0, nvram_sz}; end + 32'hFA000000: begin bridge_rd_data <= status_l; end + 32'hFB000000: begin bridge_rd_data <= status_h; end + 32'hFC000000: begin bridge_rd_data <= inputs; end + 32'hA0000000: begin bridge_rd_data <= analogizer; end + endcase + end + end + + //!------------------------------------------------------------------------- + //! Sync and Assign Outputs + //!------------------------------------------------------------------------- + wire [31:0] dip_switch_s, ext_switch_s, modifiers_s, filters_s, status_l_s, status_h_s, inputs_s, analogizer_s; + wire [15:0] nvram_sz_s; + wire svc_mode_s, core_reset_s; + + synch_3 #(32) u_sync_dsw(dip_switch, dip_switch_s, clk_sync); + synch_3 #(32) u_sync_ext(ext_switch, ext_switch_s, clk_sync); + synch_3 #(32) u_sync_mod(modifiers, modifiers_s, clk_sync); + synch_3 #(32) u_sync_flr(filters, filters_s, clk_sync); + synch_3 #(32) u_sync_stl(status_l, status_l_s, clk_sync); + synch_3 #(32) u_sync_sth(status_h, status_h_s, clk_sync); + synch_3 #(32) u_sync_inp(inputs, inputs_s, clk_sync); + synch_3 #(16) u_sync_nvm(nvram_sz, nvram_sz_s, clk_sync); + synch_3 u_sync_svc(svc_mode, svc_mode_s, clk_sync); + synch_3 u_sync_rst(core_reset_n, core_reset_s, clk_sync); + synch_3 #(32) u_sync_agr(analogizer, analogizer_s, clk_sync); + + always_comb begin + reset_sw = ~(reset_n && core_reset_s); + {dip_sw3, dip_sw2, dip_sw1, dip_sw0} = dip_switch_s; + {ext_sw3, ext_sw2, ext_sw1, ext_sw0} = ext_switch_s; + {mod_sw3, mod_sw2, mod_sw1, mod_sw0} = modifiers_s; + {inp_sw0, inp_sw1, inp_sw2, inp_sw3} = inputs_s; + scnl_sw = filters_s[3:0]; + smask_sw = filters_s[7:4]; + afilter_sw = filters_s[11:8]; + vol_att = filters_s[15:12]; + nvram_size = nvram_sz_s; + svc_sw = svc_mode_s; + status = {status_h_s, status_l_s}; + analogizer_sw = analogizer_s; + end + +endmodule diff --git a/platform/pocket/interface/joypad.sv b/platform/pocket/interface/joypad.sv new file mode 100644 index 0000000..b46824c --- /dev/null +++ b/platform/pocket/interface/joypad.sv @@ -0,0 +1,131 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Gamepad Controller +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// Shift joystick interface through 3-stages of registers and output the +// synchronized signal +// +// The value of cont_key is transferred to pkey_s1. +// The value of pkey_s1 (from the previous clock cycle) is transferred to pkey_s2. +// The value of pkey_s2 (from two clock cycles ago) is transferred to pkey_s, +// which is in the target clock domain. +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module joypad + #( + parameter DEADZONE = 8'h10 //! Set Controller Deadzone + ) ( + input wire clk_sys, //! Clock to Sync To (eg: clk_sys) + // Pocket PAD Interface + input wire [31:0] cont_key, cont_joy, //! Gamepad/Analog Joystick + // DPAD + output wire key_up, key_down, key_left, key_right, //! D-PAD + output wire key_a, key_b, key_x, key_y, //! Face Buttons + output wire key_l1, key_l2, key_l3, //! Left Shoulder/Trigger/Analog Buttons + output wire key_r1, key_r2, key_r3, //! Right Shoulder/Trigger/Analog Buttons + output wire key_se, key_st, //! Select and Start Buttons + // Analog Stick + output wire joy_up , joy_down, joy_left, joy_right, //! Analog 2 DPAD + output wire [7:0] joy_lx, joy_ly, joy_rx, joy_ry, //! Left/Right Analog Stick + // Type + output wire [3:0] pad_type, //! Controller Type + // Combined Gamepad + output wire [15:0] joystick //! Joystick + ); + + //!------------------------------------------------------------------------- + //! Gamepad + //!------------------------------------------------------------------------- + reg [31:0] pkey_s; //! Synced Joystick Register + reg [31:0] pkey_s1, pkey_s2; //! Registers for Synchronization + + always_ff @(posedge clk_sys) begin : syncKey + {pkey_s, pkey_s2, pkey_s1} <= {pkey_s2, pkey_s1, cont_key}; + end + + // D-PAD + assign key_up = pkey_s[0]; + assign key_down = pkey_s[1]; + assign key_left = pkey_s[2]; + assign key_right = pkey_s[3]; + // Face Buttons + assign key_a = pkey_s[4]; + assign key_b = pkey_s[5]; + assign key_x = pkey_s[6]; + assign key_y = pkey_s[7]; + // Shoulder/Trigger Buttons + assign key_l1 = pkey_s[8]; + assign key_r1 = pkey_s[9]; + assign key_l2 = pkey_s[10]; + assign key_r2 = pkey_s[11]; + assign key_l3 = pkey_s[12]; + assign key_r3 = pkey_s[13]; + // Select and Start Buttons + assign key_se = pkey_s[14]; + assign key_st = pkey_s[15]; + // Controller Type + assign pad_type = pkey_s[31:28]; + // Joystick + assign joystick = pkey_s[15:0]; + + //!------------------------------------------------------------------------- + //! Analog Stick + //!------------------------------------------------------------------------- + reg [31:0] pjoy_s; //! Synced Analog Register + reg [31:0] pjoy_s1, pjoy_s2; //! 2-stage register for synchronization + + // Shift joystick interface through two stages of registers and output the synchronized signal + always_ff @(posedge clk_sys) begin : syncJoy + {pjoy_s, pjoy_s2, pjoy_s1} <= {pjoy_s2, pjoy_s1, cont_joy}; + end + + // Analog Stick | 0x00 > 0x80 < 0xFF + assign joy_lx = pjoy_s[7:0]; + assign joy_ly = pjoy_s[15:8]; + assign joy_rx = pjoy_s[23:16]; + assign joy_ry = pjoy_s[31:24]; + + // Analog to DPAD + analog2dpad #(.DEADZONE(DEADZONE)) analog2dpad + ( + .clk_sys ( clk_sys ), + .pad_type ( pad_type ), + .joy_lx ( joy_lx ), + .joy_ly ( joy_ly ), + .joy_rx ( joy_rx ), + .joy_ry ( joy_ry ), + .joy_left ( joy_left ), + .joy_right ( joy_right ), + .joy_up ( joy_up ), + .joy_down ( joy_down ) + ); + +endmodule diff --git a/platform/pocket/interface/keyboard/apf2hid.sv b/platform/pocket/interface/keyboard/apf2hid.sv new file mode 100644 index 0000000..afa1c4e --- /dev/null +++ b/platform/pocket/interface/keyboard/apf2hid.sv @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module apf2hid + ( + // Clock and Reset + input logic clk, //! Clock + input logic reset, //! Reset + // APF Keyboard Port + input logic [31:0] cont3_key, //! Modifiers/Input Type + input logic [31:0] cont3_joy, //! Scan code 1-4 + input logic [15:0] cont3_trig, //! Scan code 5-6 + // USB Keyboard Output + output logic [63:0] usb_kb_hid, //! 64-bit HID Report + output logic [7:0] usb_kb_mod, //! Modifiers + output logic [7:0] usb_kb_sc1, //! Scan Code 1 + output logic [7:0] usb_kb_sc2, //! Scan Code 2 + output logic [7:0] usb_kb_sc3, //! Scan Code 3 + output logic [7:0] usb_kb_sc4, //! Scan Code 4 + output logic [7:0] usb_kb_sc5, //! Scan Code 5 + output logic [7:0] usb_kb_sc6 //! Scan Code 6 + ); + + // USB Keyboard Check + reg [3:0] key_type, key_type_s1, key_type_s2; + wire is_keyboard = (key_type == 4'h4) ? 1'b1 : 1'b0; // APF Keyboard Check + + always_ff @(posedge clk) begin : syncType + {key_type, key_type_s2, key_type_s1} <= {key_type_s2, key_type_s1, cont3_key[31:28]}; + end + + // USB HID Scancodes/Key Modifiers + wire [7:0] usb_kb_res = 8'h00; // HID Report Reserved + wire [63:0] apf_scancodes = {cont3_key[15:8], usb_kb_res, cont3_joy[31:0], cont3_trig[15:0]}; // APF HID Scancodes/Key Modifiers + reg [63:0] kb_scancodes, kb_scancodes_s1, kb_scancodes_s2; + + always_ff @(posedge clk) begin : syncKey + kb_scancodes <= kb_scancodes_s2; + kb_scancodes_s2 <= kb_scancodes_s1; + kb_scancodes_s1 <= apf_scancodes; + end + + // USB Keyboard Output + assign usb_kb_hid = is_keyboard ? kb_scancodes : 64'h00; // HID Report + assign usb_kb_mod = is_keyboard ? kb_scancodes[63:56] : 8'h00; // Modifier keys + assign usb_kb_sc1 = is_keyboard ? kb_scancodes[47:40] : 8'h00; // Keycode 1 + assign usb_kb_sc2 = is_keyboard ? kb_scancodes[39:32] : 8'h00; // Keycode 2 + assign usb_kb_sc3 = is_keyboard ? kb_scancodes[31:24] : 8'h00; // Keycode 3 + assign usb_kb_sc4 = is_keyboard ? kb_scancodes[23:16] : 8'h00; // Keycode 4 + assign usb_kb_sc5 = is_keyboard ? kb_scancodes[15:08] : 8'h00; // Keycode 5 + assign usb_kb_sc6 = is_keyboard ? kb_scancodes[07:00] : 8'h00; // Keycode 6 + +endmodule diff --git a/platform/pocket/interface/keyboard/hid2ps2_key.sv b/platform/pocket/interface/keyboard/hid2ps2_key.sv new file mode 100644 index 0000000..0341758 --- /dev/null +++ b/platform/pocket/interface/keyboard/hid2ps2_key.sv @@ -0,0 +1,233 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// altera message_off 10030 + +`default_nettype none +`timescale 1ns/1ps + +module hid2ps2_key + ( + input logic clk, //! System Clock + input logic [7:0] usb, //! USB HID ID + output logic [8:0] ps2 //! PS/2 Scancode + ); + + // Set the ram style to control implementation. + (* ramstyle = "no_rw_check" *) + logic [8:0] rom[0:255]; + + always_ff @(posedge clk) begin : ps2Scancode + ps2 <= rom[usb]; + end + + // Initialize the lookup table with default values + initial begin : generateTable + for (int i = 0; i < 256; i = i + 1) begin : setDefaultValues + rom[i] = 9'h000; // Default value (no translation) + end + + // Define translations for specific USB HID codes + rom[8'h00] = 9'h000; // Reserved (no event indicated) + rom[8'h01] = 9'h000; // Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key") + rom[8'h02] = 9'h000; // POST Fail + rom[8'h03] = 9'h000; // Error Undefined + rom[8'h04] = 9'h01C; // a and A + rom[8'h05] = 9'h032; // b and B + rom[8'h06] = 9'h021; // c and C + rom[8'h07] = 9'h023; // d and D + rom[8'h08] = 9'h024; // e and E + rom[8'h09] = 9'h02B; // f and F + rom[8'h0A] = 9'h034; // g and G + rom[8'h0B] = 9'h033; // h and H + rom[8'h0C] = 9'h043; // i and I + rom[8'h0D] = 9'h03B; // j and J + rom[8'h0E] = 9'h042; // k and K + rom[8'h0F] = 9'h04B; // l and L + rom[8'h10] = 9'h03A; // m and M + rom[8'h11] = 9'h031; // n and N + rom[8'h12] = 9'h044; // o and O + rom[8'h13] = 9'h04D; // p and P + rom[8'h14] = 9'h015; // q and Q + rom[8'h15] = 9'h02D; // r and R + rom[8'h16] = 9'h01B; // s and S + rom[8'h17] = 9'h02C; // t and T + rom[8'h18] = 9'h03C; // u and U + rom[8'h19] = 9'h02A; // v and V + rom[8'h1A] = 9'h01D; // w and W + rom[8'h1B] = 9'h022; // x and X + rom[8'h1C] = 9'h035; // y and Y + rom[8'h1D] = 9'h01A; // z and Z + rom[8'h1E] = 9'h016; // 1 and ! + rom[8'h1F] = 9'h01E; // 2 and @ + rom[8'h20] = 9'h026; // 3 and # + rom[8'h21] = 9'h025; // 4 and $ + rom[8'h22] = 9'h02E; // 5 and % + rom[8'h23] = 9'h036; // 6 and ^ + rom[8'h24] = 9'h03D; // 7 and & + rom[8'h25] = 9'h03E; // 8 and * + rom[8'h26] = 9'h046; // 9 and ( + rom[8'h27] = 9'h045; // 0 and ) + rom[8'h28] = 9'h05A; // Return (ENTER) + rom[8'h29] = 9'h076; // ESCAPE + rom[8'h2A] = 9'h066; // DELETE (Backspace) + rom[8'h2B] = 9'h00D; // Tab + rom[8'h2C] = 9'h029; // Spacebar + rom[8'h2D] = 9'h04E; // - and (underscore) + rom[8'h2E] = 9'h055; // = and + + rom[8'h2F] = 9'h054; // [ and { + rom[8'h30] = 9'h05B; // ] and } + rom[8'h31] = 9'h05D; // \ and | + rom[8'h32] = 9'h05D; // Non-US # and ~ + rom[8'h33] = 9'h04C; // ; and : + rom[8'h34] = 9'h052; // ' and " + rom[8'h35] = 9'h00E; // Grave Accent and Tilde + rom[8'h36] = 9'h041; // Keyboard, and < + rom[8'h37] = 9'h049; // . and > + rom[8'h38] = 9'h04A; // / and ? + rom[8'h39] = 9'h058; // Caps Lock + rom[8'h3A] = 9'h005; // F1 + rom[8'h3B] = 9'h006; // F2 + rom[8'h3C] = 9'h004; // F3 + rom[8'h3D] = 9'h00C; // F4 + rom[8'h3E] = 9'h003; // F5 + rom[8'h3F] = 9'h00B; // F6 + rom[8'h40] = 9'h083; // F7 + rom[8'h41] = 9'h00A; // F8 + rom[8'h42] = 9'h001; // F9 + rom[8'h43] = 9'h009; // F10 + rom[8'h44] = 9'h078; // F11 + rom[8'h45] = 9'h007; // F12 + rom[8'h46] = 9'h17C; // Print Screen + rom[8'h47] = 9'h07E; // Scroll Lock + rom[8'h48] = 9'h000; // Pause + rom[8'h49] = 9'h170; // Insert + rom[8'h4A] = 9'h16C; // Home + rom[8'h4B] = 9'h17D; // Page Up + rom[8'h4C] = 9'h171; // Delete Forward + rom[8'h4D] = 9'h169; // End + rom[8'h4E] = 9'h17A; // Page Down + rom[8'h4F] = 9'h174; // Right Arrow + rom[8'h50] = 9'h16B; // Left Arrow + rom[8'h51] = 9'h172; // Down Arrow + rom[8'h52] = 9'h175; // Up Arrow + rom[8'h53] = 9'h077; // Keypad Num Lock and Clear + rom[8'h54] = 9'h14A; // Keypad / + rom[8'h55] = 9'h07C; // Keypad * + rom[8'h56] = 9'h07B; // Keypad - + rom[8'h57] = 9'h079; // Keypad + + rom[8'h58] = 9'h15A; // Keypad ENTER + rom[8'h59] = 9'h069; // Keypad 1 and End + rom[8'h5A] = 9'h072; // Keypad 2 and Down Arrow + rom[8'h5B] = 9'h07A; // Keypad 3 and PageDn + rom[8'h5C] = 9'h06B; // Keypad 4 and Left Arrow + rom[8'h5D] = 9'h073; // Keypad 5 + rom[8'h5E] = 9'h074; // Keypad 6 and Right Arrow + rom[8'h5F] = 9'h06C; // Keypad 7 and Home + rom[8'h60] = 9'h075; // Keypad 8 and Up Arrow + rom[8'h61] = 9'h07D; // Keypad 9 and PageUp + rom[8'h62] = 9'h070; // Keypad 0 and Insert + rom[8'h63] = 9'h071; // Keypad . and Delete + // Extra Keys + rom[8'h64] = 9'h061; // Non-US \ and | - 102nd + rom[8'h65] = 9'h12F; // Application + rom[8'h66] = 9'h137; // Power + rom[8'h67] = 9'h00F; // Keypad = + rom[8'h68] = 9'h008; // F13 + rom[8'h69] = 9'h010; // F14 + rom[8'h6A] = 9'h018; // F15 + rom[8'h6B] = 9'h020; // F16 + rom[8'h6C] = 9'h028; // F17 + rom[8'h6D] = 9'h030; // F18 + rom[8'h6E] = 9'h038; // F19 + rom[8'h6F] = 9'h040; // F20 + rom[8'h70] = 9'h048; // F21 + rom[8'h71] = 9'h050; // F22 + rom[8'h72] = 9'h057; // F23 + rom[8'h73] = 9'h05F; // F24 + rom[8'h74] = 9'h000; // Execute + rom[8'h75] = 9'h000; // Help + rom[8'h76] = 9'h000; // Menu + rom[8'h77] = 9'h000; // Select + rom[8'h78] = 9'h000; // Stop + rom[8'h79] = 9'h000; // Again + rom[8'h7A] = 9'h000; // Undo + rom[8'h7B] = 9'h000; // Cut + rom[8'h7C] = 9'h000; // Copy + rom[8'h7D] = 9'h000; // Paste + rom[8'h7E] = 9'h000; // Find + rom[8'h7F] = 9'h000; // Mute + rom[8'h80] = 9'h000; // Volume Up + rom[8'h81] = 9'h000; // Volume Down + rom[8'h82] = 9'h000; // Locking Caps Lock + rom[8'h83] = 9'h000; // Locking Num Lock + rom[8'h84] = 9'h000; // Locking Scroll Lock + rom[8'h85] = 9'h06D; // Keypad Comma + rom[8'h86] = 9'h000; // Keypad Equal Sign + rom[8'h87] = 9'h051; // International1 - Ro + rom[8'h88] = 9'h013; // International2 - Katakana/Hiragana + rom[8'h89] = 9'h06A; // International3 - Yen + rom[8'h8A] = 9'h064; // International4 - Henkan + rom[8'h8B] = 9'h067; // International5 - Muhenkan + rom[8'h8C] = 9'h027; // International6 - Keypad JP Comma + rom[8'h8D] = 9'h000; // International7 + rom[8'h8E] = 9'h000; // International8 + rom[8'h8F] = 9'h000; // International9 + rom[8'h90] = 9'h0F2; // LANG1 - Hangeul + rom[8'h91] = 9'h0F1; // LANG2 - Hanja + rom[8'h92] = 9'h063; // LANG3 - Katakana + rom[8'h93] = 9'h062; // LANG4 - Hiragana + rom[8'h94] = 9'h05F; // LANG5 - Zenkaku/Hankaku + rom[8'h95] = 9'h000; // LANG6 + rom[8'h96] = 9'h000; // LANG7 + rom[8'h97] = 9'h000; // LANG8 + rom[8'h98] = 9'h000; // LANG9 + rom[8'h99] = 9'h000; // Alternate Erase + rom[8'h9A] = 9'h000; // SysReq/Attention + rom[8'h9B] = 9'h000; // Cancel + rom[8'h9C] = 9'h000; // Clear + rom[8'h9D] = 9'h000; // Prior + rom[8'h9E] = 9'h000; // Return + rom[8'h9F] = 9'h000; // Separator + rom[8'hA0] = 9'h000; // Out + rom[8'hA1] = 9'h000; // Oper + rom[8'hA2] = 9'h000; // Clear/Again + rom[8'hA3] = 9'h000; // CrSel/Props + rom[8'hA4] = 9'h000; // ExSel + rom[8'hE0] = 9'h014; // Left Control + rom[8'hE1] = 9'h012; // Left Shift + rom[8'hE2] = 9'h011; // Left Alt + rom[8'hE3] = 9'h11F; // Left GUI + rom[8'hE4] = 9'h114; // Right Control + rom[8'hE5] = 9'h059; // Right Shift + rom[8'hE6] = 9'h111; // Right Alt + rom[8'hE7] = 9'h127; // Right GUI + end + +endmodule diff --git a/platform/pocket/interface/keyboard/hid2ps2_mod.sv b/platform/pocket/interface/keyboard/hid2ps2_mod.sv new file mode 100644 index 0000000..cde4692 --- /dev/null +++ b/platform/pocket/interface/keyboard/hid2ps2_mod.sv @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module hid2ps2_mod + ( + input logic clk, + input logic [7:0] usb, + output logic [71:0] ps2 + ); + + always_ff @(posedge clk) begin : modScancode + ps2[71:63] <= (usb[0]) ? 9'h014 : 9'h00; // Left Control + ps2[62:54] <= (usb[1]) ? 9'h012 : 9'h00; // Left Shift + ps2[53:45] <= (usb[2]) ? 9'h011 : 9'h00; // Left Alt + ps2[44:36] <= (usb[3]) ? 9'h11F : 9'h00; // Left GUI + ps2[35:27] <= (usb[4]) ? 9'h114 : 9'h00; // Right Control + ps2[26:18] <= (usb[5]) ? 9'h059 : 9'h00; // Right Shift + ps2[17:09] <= (usb[6]) ? 9'h111 : 9'h00; // Right Alt + ps2[08:00] <= (usb[7]) ? 9'h127 : 9'h00; // Right GUI + end + +endmodule diff --git a/platform/pocket/interface/keyboard/kb_fifo.sv b/platform/pocket/interface/keyboard/kb_fifo.sv new file mode 100644 index 0000000..9dd5170 --- /dev/null +++ b/platform/pocket/interface/keyboard/kb_fifo.sv @@ -0,0 +1,135 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// altera message_off 10030 +// altera message_off 10230 + +`default_nettype none +`timescale 1ns/1ps + +module kb_fifo + ( + // Global + input logic clk, //! Clock + input logic reset, //! Reset + // Enqueue side + input logic [125:0] din, //! Data Input + // Dequeue side + input logic rd_en, //! Read Enable + output logic empty, //! FIFO Empty State + output logic [125:0] dout //! Data Output + ); + + parameter INIT_REPEAT_DELAY = 4'hF; // Initial delay before repeating + parameter REPEAT_RATE = 4'h4; // Repeat rate + + //!------------------------------------------------------------------------- + //! Internal Registers + //!------------------------------------------------------------------------- + logic [125:0] fifo[6:0]; // FIFO buffer + logic [125:0] prev_din; // Previous FIFO Data + logic [2:0] wr_ptr = 3'h0; // Write pointer + logic [2:0] rd_ptr = 3'h0; // Read pointer + logic [2:0] counter = 3'h0; // Count of elements in FIFO + logic wr_en = 1'b0; // Write Enable + logic full; // FIFO is Full + logic [3:0] delay_counter = 4'h0; // Delay before key starts to repeat + logic [3:0] repeat_counter = 4'h0; // Counter for key repeat rate + logic repeat_request = 1'b0; // Write Enable + logic prev_repeat_request = 1'b0; // Previous state of repeat_request + + //!------------------------------------------------------------------------- + //! FIFO State + //!------------------------------------------------------------------------- + assign empty = (counter == 0) ? 1'b1 : 1'b0; + assign full = (counter == 7) ? 1'b1 : 1'b0; + + //!------------------------------------------------------------------------- + //! Key Repeat Controller + //!------------------------------------------------------------------------- + always_ff @(posedge clk) begin : fifoKeyRepeat + if (din != 'h0 && din == prev_din && !full) begin + if (delay_counter < INIT_REPEAT_DELAY) begin + delay_counter <= delay_counter + 4'h1; + end + else if (repeat_counter < REPEAT_RATE) begin + delay_counter <= 4'h0; // Reset delay_counter after reaching the initial delay + repeat_counter <= repeat_counter + 4'h1; + end + else begin + repeat_request <= ~repeat_request; + repeat_counter <= 0; + end + end + else if (din != prev_din || din == 'h0 || wr_en) begin + delay_counter <= 4'h0; + repeat_counter <= 4'h0; + repeat_request <= 1'b0; + end + end + + //!------------------------------------------------------------------------- + //! FIFO Write Controller + //!------------------------------------------------------------------------- + always_ff @(posedge clk) begin : fifoWriteControl + prev_din <= din; + prev_repeat_request <= repeat_request; + if ((din != prev_din) || (repeat_request && !prev_repeat_request)) begin + wr_en <= 1'b1; + end + else begin + wr_en <= 1'b0; + end + end + + //!------------------------------------------------------------------------- + //! FIFO Buffer Controller + //!------------------------------------------------------------------------- + always_ff @(posedge clk) begin : fifoControl + if (reset) begin + wr_ptr <= 0; + rd_ptr <= 0; + counter <= 0; + end + else begin + if (wr_en && !full) begin + fifo[wr_ptr] <= din; + wr_ptr <= (wr_ptr + 1) % 7; + counter <= counter + 1; + end + + if (rd_en && !empty) begin + dout <= fifo[rd_ptr]; + rd_ptr <= (rd_ptr + 1) % 7; + counter <= counter - 1; + end + end + end + +endmodule diff --git a/platform/pocket/interface/keyboard/key_arbiter.sv b/platform/pocket/interface/keyboard/key_arbiter.sv new file mode 100644 index 0000000..c334fdc --- /dev/null +++ b/platform/pocket/interface/keyboard/key_arbiter.sv @@ -0,0 +1,115 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module key_arbiter + ( + input logic clk, //! Clock input + input logic reset, //! Reset input + input logic fifo_ready, //! FIFO is not empty + input logic [125:0] fifo_din, //! FIFO 126-bit input data + output logic fifo_rd, //! Read Request to FIFO when no data is being processed + output logic [3:0] key_idx, //! Key Index + output logic [8:0] scancode //! 9-bit output chunk + ); + + //!------------------------------------------------------------------------- + //! Request new data when all chunks have been processed + //!------------------------------------------------------------------------- + assign fifo_rd = !data_valid && fifo_ready; + + //!------------------------------------------------------------------------- + //! State Machine Controller + //!------------------------------------------------------------------------- + logic [3:0] cycle_counter; // Counter for clock cycles + logic data_valid; // Flag to indicate if the current data is valid + + always_ff @(posedge clk or posedge reset) begin + if (reset) begin + key_idx <= 4'h0; + cycle_counter <= 4'h0; + data_valid <= 1'b0; + end + else if(fifo_ready && !data_valid) begin + key_idx <= 4'h1; + cycle_counter <= 4'h0; + data_valid <= 1'b1; + end + else if(data_valid) begin + if (scancode == 9'h0) begin + if (key_idx < 4'hE) begin + key_idx <= key_idx + 4'b1; + end else begin + key_idx <= 4'h0; + data_valid <= 1'b0; + end + cycle_counter <= 4'h0; + end + else if (cycle_counter == 4'h4) begin + if (key_idx < 4'hE) begin + key_idx <= key_idx + 4'b1; + end else begin + key_idx <= 4'h0; + data_valid <= 1'b0; + end + cycle_counter <= 4'h0; + end + else begin + cycle_counter <= cycle_counter + 4'b1; + end + end + end + + //!------------------------------------------------------------------------- + //! State Machine Logic + //!------------------------------------------------------------------------- + always_comb begin + case (key_idx) + 4'h1: scancode = fifo_din[125:117]; // Scancode MOD 1 + 4'h2: scancode = fifo_din[116:108]; // Scancode MOD 2 + 4'h3: scancode = fifo_din[107:099]; // Scancode MOD 3 + 4'h4: scancode = fifo_din[098:090]; // Scancode MOD 4 + 4'h5: scancode = fifo_din[089:081]; // Scancode MOD 5 + 4'h6: scancode = fifo_din[080:072]; // Scancode MOD 6 + 4'h7: scancode = fifo_din[071:063]; // Scancode MOD 7 + 4'h8: scancode = fifo_din[062:054]; // Scancode MOD 8 + 4'h9: scancode = fifo_din[053:045]; // Scancode 1 + 4'hA: scancode = fifo_din[044:036]; // Scancode 2 + 4'hB: scancode = fifo_din[035:027]; // Scancode 3 + 4'hC: scancode = fifo_din[026:018]; // Scancode 4 + 4'hD: scancode = fifo_din[017:009]; // Scancode 5 + 4'hE: scancode = fifo_din[008:000]; // Scancode 6 + default: scancode = 9'h0; + endcase + end + +endmodule diff --git a/platform/pocket/interface/keyboard/key_ctl.sv b/platform/pocket/interface/keyboard/key_ctl.sv new file mode 100644 index 0000000..460a04f --- /dev/null +++ b/platform/pocket/interface/keyboard/key_ctl.sv @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module key_ctl + ( + input logic clk, //! System Clock + input logic reset, //! Reset + input logic [3:0] key_idx, //! Key Index + input logic [8:0] scancode, //! Key Scan Code + output logic key_strobe, //! Key Data Valid + output logic key_pressed, //! 1: Make (Pressed) | 0: Break (Released) + output logic [8:0] key_code //! Key Scan Code + ); + + //!------------------------------------------------------------------------- + //! Scancode Storage + //!------------------------------------------------------------------------- + reg [8:0] scancode_last, scancode_saved; + reg save_scancode; + + always_ff @(posedge clk) begin : scancodeStorage + scancode_last <= scancode; + scancode_saved <= (save_scancode) ? scancode : scancode_saved; + end + + //!------------------------------------------------------------------------- + //! Key State + //!------------------------------------------------------------------------- + typedef enum {IDLE, SAVE, PRESS, HOLD_RELEASE} KeyState; + KeyState current_state, next_state; + + //!------------------------------------------------------------------------- + //! Key Conditions + //!------------------------------------------------------------------------- + wire key_make = (scancode != scancode_last) && (scancode != 9'h0) || ( |scancode & ~|scancode_last); + wire key_break = (scancode != scancode_last) && (scancode == 9'h0) || (~|scancode & |scancode_last); + wire key_changed = (scancode != scancode_last); + + //!------------------------------------------------------------------------- + //! State Machine Controller + //!------------------------------------------------------------------------- + always_ff @(posedge clk) begin : scancodeFSMControl + current_state <= (reset) ? IDLE : next_state; + end + + always_comb begin : scancodeFSM + next_state = current_state; + save_scancode = 1'b0; + key_code = 9'h0; + key_pressed = 1'b0; + key_strobe = 1'b0; + + case (current_state) + IDLE: begin + next_state = (key_make) ? SAVE : IDLE; + end + SAVE: begin + save_scancode = 1'b1; + next_state = PRESS; + end + PRESS: begin + key_code = scancode_saved; + key_pressed = 1'b1; + key_strobe = 1'b1; + next_state = HOLD_RELEASE; + end + HOLD_RELEASE: begin + key_code = scancode_saved; + key_pressed = ~(key_break || key_changed); + key_strobe = (key_break || key_changed); + next_state = (key_break) ? IDLE : + (key_changed) ? SAVE : HOLD_RELEASE; + end + default: begin + next_state = IDLE; + end + endcase + end + +endmodule diff --git a/platform/pocket/interface/keyboard/key_mgr.sv b/platform/pocket/interface/keyboard/key_mgr.sv new file mode 100644 index 0000000..9086140 --- /dev/null +++ b/platform/pocket/interface/keyboard/key_mgr.sv @@ -0,0 +1,169 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// altera message_off 10762 + +`default_nettype none +`timescale 1ns/1ps + +module key_mgr + ( + input wire clk, //! System Clock + input wire reset, //! Reset + input wire [3:0] key_idx, //! Key Index + input wire [8:0] scancode, //! Key Scan Code + output logic key_strobe, //! Key Data Valid + output logic key_pressed, //! 1: Make (Pressed) | 0: Break (Released) + output logic [8:0] key_code //! Key Scan Code + ); + + //!------------------------------------------------------------------------- + //! Scancode Storage + //!------------------------------------------------------------------------- + reg [8:0] scancode_last[0:15]; + reg [8:0] scancode_saved[0:15]; + reg [15:0] save_scancode; + + reg key_strobe_array[0:15]; + reg key_pressed_array[0:15]; + reg [8:0] key_code_array[0:15]; + reg key_strobe_array_reg[0:15]; + reg key_pressed_array_reg[0:15]; + reg [8:0] key_code_array_reg[0:15]; + reg [15:0] save_scancode_reg; + + always_ff @(posedge clk) begin + if (reset) begin + for (int i = 0; i < 16; i++) begin + scancode_last[i] <= 9'h0; + scancode_saved[i] <= 9'h0; + end + end + else begin + for (int i = 0; i < 16; i++) begin + if (key_idx == i[3:0]) begin + scancode_last[i] <= scancode; + scancode_saved[i] <= (save_scancode[i]) ? scancode : scancode_saved[i]; + end + end + end + end + + //!------------------------------------------------------------------------- + //! Key State + //!------------------------------------------------------------------------- + typedef enum {IDLE, SAVE, PRESS, HOLD_RELEASE} KeyState; + KeyState current_state[0:15], next_state[0:15]; + + //!------------------------------------------------------------------------- + //! Key Conditions + //!------------------------------------------------------------------------- + wire key_make = (scancode != scancode_last[key_idx]) && (scancode != 9'h0) || ( |scancode & ~|scancode_last[key_idx]); + wire key_break = (scancode != scancode_last[key_idx]) && (scancode == 9'h0) || (~|scancode & |scancode_last[key_idx]); + wire key_changed = (scancode != scancode_last[key_idx]); + + //!------------------------------------------------------------------------- + //! State Machine Controller + //!------------------------------------------------------------------------- + always_ff @(posedge clk) begin + if (reset) begin + for (int i = 0; i < 16; i++) begin + current_state[i] <= IDLE; + save_scancode_reg[i] <= 0; + key_code_array_reg[i] <= 0; + key_pressed_array_reg[i] <= 0; + key_strobe_array_reg[i] <= 0; + end + end + else begin + for (int i = 0; i < 16; i++) begin + if (key_idx == i[3:0]) begin + current_state[i] <= next_state[i]; + save_scancode_reg[i] <= save_scancode[i]; + key_code_array_reg[i] <= key_code_array[i]; + key_pressed_array_reg[i] <= key_pressed_array[i]; + key_strobe_array_reg[i] <= key_strobe_array[i]; + end + end + end + end + + //!------------------------------------------------------------------------- + //! State Machine Logic + //!------------------------------------------------------------------------- + always_comb begin + for (int i = 0; i < 16; i++) begin + if (key_idx == i[3:0]) begin + next_state[i] = current_state[i]; + save_scancode[i] = 1'b0; + key_code_array[i] = 9'h0; + key_pressed_array[i] = 1'b0; + key_strobe_array[i] = 1'b0; + + case (current_state[i]) + IDLE: begin + next_state[i] = (key_make) ? SAVE : IDLE; + end + SAVE: begin + save_scancode[i] = 1'b1; + next_state[i] = PRESS; + end + PRESS: begin + key_code_array[i] = scancode_saved[i]; + key_pressed_array[i] = 1'b1; + key_strobe_array[i] = 1'b1; + next_state[i] = HOLD_RELEASE; + end + HOLD_RELEASE: begin + key_code_array[i] = scancode_saved[i]; + key_pressed_array[i] = ~(key_break || key_changed); + key_strobe_array[i] = (key_break || key_changed); + next_state[i] = (key_break) ? IDLE : + (key_changed) ? SAVE : HOLD_RELEASE; + end + default: begin + next_state[i] = IDLE; + end + endcase + end + else begin + next_state[i] = current_state[i]; + save_scancode[i] = save_scancode_reg[i]; + key_code_array[i] = key_code_array_reg[i]; + key_pressed_array[i] = key_pressed_array_reg[i]; + key_strobe_array[i] = key_strobe_array_reg[i]; + end + end + end + + assign key_code = key_code_array[key_idx]; + assign key_pressed = key_pressed_array[key_idx]; + assign key_strobe = key_strobe_array[key_idx]; + +endmodule diff --git a/platform/pocket/interface/keyboard/usb_keyboard.sv b/platform/pocket/interface/keyboard/usb_keyboard.sv new file mode 100644 index 0000000..93a6413 --- /dev/null +++ b/platform/pocket/interface/keyboard/usb_keyboard.sv @@ -0,0 +1,145 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module usb_keyboard + ( + // Clock and Reset + input logic clk, //! Clock + input logic clk_sync, //! Clock + input logic reset, //! Reset + // APF Keyboard Port + input logic [31:0] cont3_key, //! Modifiers/Input Type + input logic [31:0] cont3_joy, //! Scan code 1-4 + input logic [15:0] cont3_trig, //! Scan code 5-6 + // USB Keyboard Output + output logic [63:0] usb_kb_hid, //! 64-bit HID Report + output logic [7:0] usb_kb_mod, //! Modifiers + output logic [7:0] usb_kb_sc1, //! Scan Code 1 + output logic [7:0] usb_kb_sc2, //! Scan Code 2 + output logic [7:0] usb_kb_sc3, //! Scan Code 3 + output logic [7:0] usb_kb_sc4, //! Scan Code 4 + output logic [7:0] usb_kb_sc5, //! Scan Code 5 + output logic [7:0] usb_kb_sc6, //! Scan Code 6 + // PS/2 Keyboard Output + output logic [10:0] ps2_key = 11'h0 //! PS/2 Keyboard + ); + + //!------------------------------------------------------------------------- + //! APF to USB HID + //!------------------------------------------------------------------------- + apf2hid u_apf2hid + ( + .clk ( clk ), + .reset ( reset ), + .cont3_key ( cont3_key ), + .cont3_joy ( cont3_joy ), + .cont3_trig ( cont3_trig ), + .usb_kb_hid ( usb_kb_hid ), + .usb_kb_mod ( usb_kb_mod ), + .usb_kb_sc1 ( usb_kb_sc1 ), + .usb_kb_sc2 ( usb_kb_sc2 ), + .usb_kb_sc3 ( usb_kb_sc3 ), + .usb_kb_sc4 ( usb_kb_sc4 ), + .usb_kb_sc5 ( usb_kb_sc5 ), + .usb_kb_sc6 ( usb_kb_sc6 ) + ); + + //!------------------------------------------------------------------------- + //! Translate USB HID ID to PS/2 Scancode + //!------------------------------------------------------------------------- + logic [53:0] ps2_keys; + logic [71:0] ps2_mods; + + hid2ps2_mod u_key_mod (.clk(~clk), .usb(usb_kb_mod), .ps2(ps2_mods)); + hid2ps2_key u_key_sc1 (.clk(~clk), .usb(usb_kb_sc1), .ps2(ps2_keys[53:45])); + hid2ps2_key u_key_sc2 (.clk(~clk), .usb(usb_kb_sc2), .ps2(ps2_keys[44:36])); + hid2ps2_key u_key_sc3 (.clk(~clk), .usb(usb_kb_sc3), .ps2(ps2_keys[35:27])); + hid2ps2_key u_key_sc4 (.clk(~clk), .usb(usb_kb_sc4), .ps2(ps2_keys[26:18])); + hid2ps2_key u_key_sc5 (.clk(~clk), .usb(usb_kb_sc5), .ps2(ps2_keys[17:09])); + hid2ps2_key u_key_sc6 (.clk(~clk), .usb(usb_kb_sc6), .ps2(ps2_keys[08:00])); + + //!------------------------------------------------------------------------- + //! PS/2 Keyboard FIFO + //!------------------------------------------------------------------------- + logic [125:0] fifo_dout; + logic fifo_empty; + logic fifo_rd; + + kb_fifo u_fifo + ( + .clk ( clk ), + .reset ( reset ), + .din ( {ps2_mods, ps2_keys} ), + .rd_en ( fifo_rd ), + .empty ( fifo_empty ), + .dout ( fifo_dout ) + ); + + //!------------------------------------------------------------------------- + //! PS/2 FIFO Scancode Arbiter + //!------------------------------------------------------------------------- + logic [8:0] scancode; + logic [3:0] key_idx; + + key_arbiter u_key_arbiter + ( + .clk ( clk ), + .reset ( reset ), + .fifo_ready ( ~fifo_empty ), + .fifo_din ( fifo_dout ), + .fifo_rd ( fifo_rd ), + .key_idx ( key_idx ), + .scancode ( scancode ) + ); + + //!------------------------------------------------------------------------- + //! PS/2 Key Controller + //!------------------------------------------------------------------------- + logic strobe; + logic pressed; + logic [8:0] key_code; + + key_mgr u_key_ctl + ( + .clk ( clk ), + .reset ( reset ), + .key_idx ( key_idx ), + .scancode ( scancode ), + .key_strobe ( strobe ), + .key_pressed ( pressed ), + .key_code ( key_code ) + ); + + assign ps2_key = { strobe, pressed, key_code }; + +endmodule diff --git a/platform/pocket/interface/mame_keymap.sv b/platform/pocket/interface/mame_keymap.sv new file mode 100644 index 0000000..989ce34 --- /dev/null +++ b/platform/pocket/interface/mame_keymap.sv @@ -0,0 +1,133 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// PS/2 Keyboard to MAME Key Mapping +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// +// key bitmap: +// +// | Gamepad | Start | Coinage | +// | --------- | ----------- | ---------- | +// | [0] up | [0] start 1 | [0] coin 1 | +// | [1] down | [1] start 2 | [1] coin 2 | +// | [2] left | [2] start 3 | [2] coin 3 | +// | [3] right | [3] start 4 | [3] coin 4 | +// | [4] btn_1 | | | +// | [5] btn_2 | | | +// | [6] btn_3 | | | +// | [7] btn_4 | | | +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module mame_keymap + ( + // Clock and Reset + input wire clk, + input wire reset, + // PS/2 Interface + input wire [10:0] ps2_key, + // Gamepad Interface + output reg [3:0] start, //! Start 1,2,3,4 + output reg [3:0] coin, //! Coin 1,2,3,4 + output reg pause, //! Pause + output reg [7:0] player1, //! Player 1 + output reg [7:0] player2, //! Player 2 + output reg [7:0] player3, //! Player 3 + output reg [7:0] player4 //! Player 4 + ); + + wire pressed = ps2_key[9]; + + always_ff @(posedge clk) begin + reg old_state; + if (reset) begin + start <= 4'h0; + coin <= 4'h0; + pause <= 1'h0; + player1 <= 8'h0; + player2 <= 8'h0; + player3 <= 8'h0; + player4 <= 8'h0; + end + else begin + old_state <= ps2_key[10]; + if(old_state ^ ps2_key[10]) begin + case(ps2_key[8:0]) + 9'h016: start[0] <= pressed; // 1 + 9'h01E: start[1] <= pressed; // 2 + 9'h026: start[2] <= pressed; // 3 + 9'h025: start[3] <= pressed; // 4 + + 9'h02E: coin[0] <= pressed; // 5 + 9'h036: coin[1] <= pressed; // 6 + 9'h03D: coin[2] <= pressed; // 7 + 9'h03E: coin[2] <= pressed; // 8 + + 9'h04D: pause <= pressed; // P + + 9'h175: player1[0] <= pressed; // Up + 9'h172: player1[1] <= pressed; // Down + 9'h16B: player1[2] <= pressed; // Left + 9'h174: player1[3] <= pressed; // Right + 9'h014: player1[4] <= pressed; // Left Ctrl + 9'h011: player1[5] <= pressed; // Left Alt + 9'h029: player1[6] <= pressed; // Space + 9'h012: player1[7] <= pressed; // Left Shift + + 9'h02D: player2[0] <= pressed; // R + 9'h02B: player2[1] <= pressed; // F + 9'h023: player2[2] <= pressed; // D + 9'h034: player2[3] <= pressed; // G + 9'h01C: player2[4] <= pressed; // A + 9'h01B: player2[5] <= pressed; // S + 9'h015: player2[6] <= pressed; // Q + 9'h01D: player2[7] <= pressed; // W + + 9'h043: player3[0] <= pressed; // I + 9'h042: player3[1] <= pressed; // K + 9'h03B: player3[2] <= pressed; // J + 9'h04B: player3[3] <= pressed; // L + 9'h114: player3[4] <= pressed; // Right Ctrl + 9'h059: player3[5] <= pressed; // Right Shift + 9'h05A: player3[6] <= pressed; // Enter + + 9'h075: player4[0] <= pressed; // Keypad 8 and Up Arrow + 9'h072: player4[1] <= pressed; // Keypad 2 and Down Arrow + 9'h06B: player4[2] <= pressed; // Keypad 4 and Left Arrow + 9'h074: player4[3] <= pressed; // Keypad 6 and Right Arrow + 9'h070: player4[4] <= pressed; // Keypad 0 and Insert + 9'h071: player4[5] <= pressed; // Keypad . and Delete + 9'h15A: player4[6] <= pressed; // Keypad ENTER + endcase + end + end + end + +endmodule diff --git a/platform/pocket/interface/mame_keymap_f.sv b/platform/pocket/interface/mame_keymap_f.sv new file mode 100644 index 0000000..9f02465 --- /dev/null +++ b/platform/pocket/interface/mame_keymap_f.sv @@ -0,0 +1,156 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// PS/2 Keyboard to MAME Key Mapping +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// +// key bitmap: +// +// | Gamepad | Start | Coinage | +// | --------- | ----------- | ---------- | +// | [0] up | [0] start 1 | [0] coin 1 | +// | [1] down | [1] start 2 | [1] coin 2 | +// | [2] left | [2] start 3 | [2] coin 3 | +// | [3] right | [3] start 4 | [3] coin 4 | +// | [4] btn_1 | | | +// | [5] btn_2 | | | +// | [6] btn_3 | | | +// | [7] btn_4 | | | +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module mame_keymap_f + ( + // Clock and Reset + input wire clk, + input wire reset, + // PS/2 Interface + input wire [10:0] ps2_key, + // Gamepad Interface + // Start 1,2,3,4 + output reg kb1_start, kb2_start, kb3_start, kb4_start, + // Coin 1,2,3,4 + output reg kb1_coin, kb2_coin, kb3_coin, kb4_coin, + // Service Control + output reg kb_pause, kb_tilt, kb_test, kb_reset, + output reg kb_service, + // Player 1 + output reg kb1_up, kb1_down, kb1_left, kb1_right, //! Directional Pad + output reg kb1_btn1, kb1_btn2, kb1_btn3, kb1_btn4, //! Y/B/A/X + output reg kb1_btn5, kb1_btn6, //! L/R / Coin P1 / P1 Start + // Player 2 + output reg kb2_up, kb2_down, kb2_left, kb2_right, //! Directional Pad + output reg kb2_btn1, kb2_btn2, kb2_btn3, kb2_btn4, //! Y/B/A/X + output reg kb2_btn5, kb2_btn6, //! L/R / Coin P2 / P2 Start + // Player 3 + output reg kb3_up, kb3_down, kb3_left, kb3_right, //! Directional Pad + output reg kb3_btn1, kb3_btn2, kb3_btn3, kb3_btn4, //! Y/B/A/X + output reg kb3_btn5, kb3_btn6, //! L/R / Coin P3 / P3 Start + // Player 4 + output reg kb4_up, kb4_down, kb4_left, kb4_right, //! Directional Pad + output reg kb4_btn1, kb4_btn2, kb4_btn3, kb4_btn4, //! Y/B/A/X + output reg kb4_btn5, kb4_btn6 //! L/R / Coin P4 / P4 Start + ); + + wire pressed = ps2_key[9]; + + always_ff @(posedge clk) begin + reg old_state; + if (reset) begin + // start <= 4'h0; + // coin <= 4'h0; + // pause <= 1'h0; + // player1 <= 8'h0; + // player2 <= 8'h0; + // player3 <= 8'h0; + // player4 <= 8'h0; + end + else begin + old_state <= ps2_key[10]; + if(old_state ^ ps2_key[10]) begin + case(ps2_key[8:0]) + // Service Control + 9'h04D: kb_pause <= pressed; // P + 9'h02C: kb_tilt <= pressed; // T + 9'h006: kb_test <= pressed; // F2 + 9'h004: kb_reset <= pressed; // F3 + 9'h046: kb_service <= pressed; // 9 + // Start + 9'h016: kb1_start <= pressed; // 1 + 9'h01E: kb2_start <= pressed; // 2 + 9'h026: kb3_start <= pressed; // 3 + 9'h025: kb4_start <= pressed; // 4 + // Coinage + 9'h02E: kb1_coin <= pressed; // 5 + 9'h036: kb2_coin <= pressed; // 6 + 9'h03D: kb3_coin <= pressed; // 7 + 9'h03E: kb4_coin <= pressed; // 8 + // Player 1 + 9'h175: kb1_up <= pressed; // Up + 9'h172: kb1_down <= pressed; // Down + 9'h16B: kb1_left <= pressed; // Left + 9'h174: kb1_right <= pressed; // Right + 9'h014: kb1_btn1 <= pressed; // Left Ctrl + 9'h011: kb1_btn2 <= pressed; // Left Alt + 9'h029: kb1_btn3 <= pressed; // Space + 9'h012: kb1_btn4 <= pressed; // Left Shift + 9'h01A: kb1_btn5 <= pressed; // Z + 9'h022: kb1_btn6 <= pressed; // X + // Player 2 + 9'h02D: kb2_up <= pressed; // R + 9'h02B: kb2_down <= pressed; // F + 9'h023: kb2_left <= pressed; // D + 9'h034: kb2_right <= pressed; // G + 9'h01C: kb2_btn1 <= pressed; // A + 9'h01B: kb2_btn2 <= pressed; // S + 9'h015: kb2_btn3 <= pressed; // Q + 9'h01D: kb2_btn4 <= pressed; // W + // Player 3 + 9'h043: kb3_up <= pressed; // I + 9'h042: kb3_down <= pressed; // K + 9'h03B: kb3_left <= pressed; // J + 9'h04B: kb3_right <= pressed; // L + 9'h114: kb3_btn1 <= pressed; // Right Ctrl + 9'h059: kb3_btn2 <= pressed; // Right Shift + 9'h05A: kb3_btn3 <= pressed; // Enter + // Player 4 + 9'h075: kb4_up <= pressed; // Keypad 8 and Up Arrow + 9'h072: kb4_down <= pressed; // Keypad 2 and Down Arrow + 9'h06B: kb4_left <= pressed; // Keypad 4 and Left Arrow + 9'h074: kb4_right <= pressed; // Keypad 6 and Right Arrow + 9'h070: kb4_btn1 <= pressed; // Keypad 0 and Insert + 9'h071: kb4_btn2 <= pressed; // Keypad . and Delete + 9'h15A: kb4_btn3 <= pressed; // Keypad ENTER + endcase + end + end + end + +endmodule diff --git a/platform/pocket/interface/pause_crtl.sv b/platform/pocket/interface/pause_crtl.sv new file mode 100644 index 0000000..961c443 --- /dev/null +++ b/platform/pocket/interface/pause_crtl.sv @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Generic Pause Handling +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module pause_crtl + ( + input logic clk_sys, //! Clock to Sync To (eg: clk_sys) + input logic os_inmenu, //! Menu Status (active-high when menu is open) + input logic pause_req, //! Pause Requested by another Module + output logic pause_core //! Pause signal to Core + ); + + // Synchronize Home/Analogue Button + reg inmenu_s; + synch_2 sync_inmenu(os_inmenu, inmenu_s, clk_sys); + + assign pause_core = (inmenu_s | pause_req); + +endmodule diff --git a/platform/pocket/interface/usb_mouse.sv b/platform/pocket/interface/usb_mouse.sv new file mode 100644 index 0000000..c0fcd33 --- /dev/null +++ b/platform/pocket/interface/usb_mouse.sv @@ -0,0 +1,95 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket USB HID Keyboard/Mouse and PS/2 Scan Code Translation +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// Analogue Pocket Dock USB Notes: +// +// Mouse: +// Because mouse input data is report/event based (using deltas instead of +// absolute coordinates), a 16-bit counter is used to identify each unique +// report, and incremented each time a new report is sent. +// A comparator can be used against the current and previous counter value +// to detect new events. +// +// In the mouse data are X position delta, Y position delta, +// up to 8 buttons, and the report counter. +// Buttons, starting at bit 0 with left, right, middle, etc. +// +// | Register bit range | Function | +// | :----------------- | :----------------------- | +// | cont4_joy[31:16] | Buttons | +// | cont4_joy[15:0] | Relative X movement (LE) | +// | cont4_key[15:0] | Report counter (LE) | +// | cont4_trig[15:0] | Relative Y movement (LE) | +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module usb_mouse + ( + // Clock and Reset + input logic clk, // System Clock + input logic reset, // Reset + // APF Mouse + input logic [31:0] cont4_key, // Keypad + input logic [31:0] cont4_joy, // Joystick + input logic [15:0] cont4_trig, // Trigger + // USB Mouse + output logic mouse_left_btn, // Mouse Left Button + output logic mouse_middle_btn, // Mouse Right Button + output logic mouse_right_btn, // Mouse Middle Button + output logic signed [15:0] mouse_dx, // Mouse X + output logic signed [15:0] mouse_dy, // Mouse Y + // PS/2 Interface + output logic [24:0] ps2_mouse = 25'h0 // [24] - toggles with every event + ); + + // Mouse Internal Logic + wire [15:0] mouse_report_counter = {cont4_key[7:0], cont4_key[15:8]}; + wire [7:0] mouse_buttons; + wire signed [15:0] mouse_pointer_x; + wire signed [15:0] mouse_pointer_y; + + // USB Mouse Check + wire [3:0] key_type; + wire is_mouse = (key_type == 4'h5) ? 1'b1 : 1'b0; // APF Input Type + + synch_3 #(.WIDTH(4)) sync_mt( cont4_key[31:28], key_type, clk); + synch_3 #(.WIDTH(8)) sync_mb( cont4_joy[23:16], mouse_buttons, clk); + synch_3 #(.WIDTH(16)) sync_mx({cont4_joy[7:0], cont4_joy[15:8]}, mouse_pointer_x, clk); + synch_3 #(.WIDTH(16)) sync_my({cont4_trig[7:0], cont4_trig[15:8]}, mouse_pointer_y, clk); + + assign mouse_left_btn = mouse_buttons[0]; + assign mouse_right_btn = mouse_buttons[1]; + assign mouse_middle_btn = mouse_buttons[2]; + assign mouse_dx = mouse_pointer_x; + assign mouse_dy = mouse_pointer_y; + +endmodule diff --git a/platform/pocket/megafunctions/mf_audio_pll.qip b/platform/pocket/megafunctions/mf_audio_pll.qip new file mode 100644 index 0000000..efec938 --- /dev/null +++ b/platform/pocket/megafunctions/mf_audio_pll.qip @@ -0,0 +1,337 @@ +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_TOOL_VERSION "17.1" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "mf_audio_pll" -name MISC_FILE [file join $::quartus(qip_path) "mf_audio_pll.cmp"] +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_COMPONENT_NAME "bWZfYXVkaW9fcGxs" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_COMPONENT_VERSION "MTcuMQ==" +set_global_assignment -entity "mf_audio_pll" -library "mf_audio_pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_NAME "bWZfYXVkaW9fcGxsXzAwMDI=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_VERSION "MTcuMQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NzQuMjU=::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NzQuMjUgTUh6::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::dHJ1ZQ==::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::Mg==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::Mg==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MTIuMjg4::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::NDY5MjM2MDIz::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::NDk=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::My4wNzI=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::NDY5MjM2MDIz::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MTk2::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MTIuMjg4MDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::My4wNzIwMDAgTUh6::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T2Zm::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NCw0LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSwyNSwyNCwxLDAscGhfbXV4X2NsayxmYWxzZSx0cnVlLDk4LDk4LDEsMCxwaF9tdXhfY2xrLGZhbHNlLGZhbHNlLDEsMzAsMjAwMCw2MDIuMTEyIE1Ieiw0NjkyMzYwMjMsbm9uZSxnbGIsbV9jbnQscGhfbXV4X2NsayxmYWxzZQ==::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "mf_audio_pll" -name VERILOG_FILE [file join $::quartus(qip_path) "mf_audio_pll.v"] +set_global_assignment -library "mf_audio_pll" -name VERILOG_FILE [file join $::quartus(qip_path) "mf_audio_pll/mf_audio_pll_0002.v"] +set_global_assignment -library "mf_audio_pll" -name QIP_FILE [file join $::quartus(qip_path) "mf_audio_pll/mf_audio_pll_0002.qip"] + +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_TOOL_VERSION "17.1" +set_global_assignment -entity "mf_audio_pll_0002" -library "mf_audio_pll" -name IP_TOOL_ENV "mwpim" diff --git a/platform/pocket/megafunctions/mf_audio_pll.v b/platform/pocket/megafunctions/mf_audio_pll.v new file mode 100644 index 0000000..6633406 --- /dev/null +++ b/platform/pocket/megafunctions/mf_audio_pll.v @@ -0,0 +1,255 @@ +// megafunction wizard: %Altera PLL v17.1% +// GENERATION: XML +// mf_audio_pll.v + +// Generated using ACDS version 17.1 590 + +`timescale 1 ps / 1 ps +module mf_audio_pll ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0, // outclk0.clk + output wire outclk_1, // outclk1.clk + output wire locked // locked.export + ); + + mf_audio_pll_0002 mf_audio_pll_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .outclk_1 (outclk_1), // outclk1.clk + .locked (locked) // locked.export + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : mf_audio_pll.vo +// RELATED_FILES: mf_audio_pll.v, mf_audio_pll_0002.v diff --git a/platform/pocket/megafunctions/mf_audio_pll/mf_audio_pll_0002.qip b/platform/pocket/megafunctions/mf_audio_pll/mf_audio_pll_0002.qip new file mode 100644 index 0000000..916311f --- /dev/null +++ b/platform/pocket/megafunctions/mf_audio_pll/mf_audio_pll_0002.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*mf_audio_pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*mf_audio_pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET OFF -to "*mf_audio_pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*mf_audio_pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/platform/pocket/megafunctions/mf_audio_pll/mf_audio_pll_0002.v b/platform/pocket/megafunctions/mf_audio_pll/mf_audio_pll_0002.v new file mode 100644 index 0000000..86e4d75 --- /dev/null +++ b/platform/pocket/megafunctions/mf_audio_pll/mf_audio_pll_0002.v @@ -0,0 +1,90 @@ +`timescale 1ns/10ps +module mf_audio_pll_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'outclk1' + output wire outclk_1, + + // interface 'locked' + output wire locked +); + + altera_pll #( + .fractional_vco_multiplier("true"), + .reference_clock_frequency("74.25 MHz"), + .operation_mode("direct"), + .number_of_clocks(2), + .output_clock_frequency0("12.288000 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("3.072000 MHz"), + .phase_shift1("0 ps"), + .duty_cycle1(50), + .output_clock_frequency2("0 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("0 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("General"), + .pll_subtype("General") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_1, outclk_0}), + .locked (locked), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk) + ); +endmodule + diff --git a/platform/pocket/megafunctions/mf_datatable.qip b/platform/pocket/megafunctions/mf_datatable.qip new file mode 100644 index 0000000..9876cc0 --- /dev/null +++ b/platform/pocket/megafunctions/mf_datatable.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" +set_global_assignment -name IP_TOOL_VERSION "17.1" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "mf_datatable.v"] diff --git a/platform/pocket/megafunctions/mf_datatable.v b/platform/pocket/megafunctions/mf_datatable.v new file mode 100644 index 0000000..0db807d --- /dev/null +++ b/platform/pocket/megafunctions/mf_datatable.v @@ -0,0 +1,246 @@ +// megafunction wizard: %RAM: 2-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: mf_datatable.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 17.1.0 Build 590 10/25/2017 SJ Standard Edition +// ************************************************************ + + +//Copyright (C) 2017 Intel Corporation. All rights reserved. +//Your use of Intel Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Intel Program License +//Subscription Agreement, the Intel Quartus Prime License Agreement, +//the Intel FPGA IP License Agreement, or other applicable license +//agreement, including, without limitation, that your use is for +//the sole purpose of programming logic devices manufactured by +//Intel and sold by Intel or its authorized distributors. Please +//refer to the applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module mf_datatable ( + address_a, + address_b, + clock_a, + clock_b, + data_a, + data_b, + wren_a, + wren_b, + q_a, + q_b); + + input [7:0] address_a; + input [7:0] address_b; + input clock_a; + input clock_b; + input [31:0] data_a; + input [31:0] data_b; + input wren_a; + input wren_b; + output [31:0] q_a; + output [31:0] q_b; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock_a; + tri0 wren_a; + tri0 wren_b; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [31:0] sub_wire0; + wire [31:0] sub_wire1; + wire [31:0] q_a = sub_wire0[31:0]; + wire [31:0] q_b = sub_wire1[31:0]; + + altsyncram altsyncram_component ( + .address_a (address_a), + .address_b (address_b), + .clock0 (clock_a), + .clock1 (clock_b), + .data_a (data_a), + .data_b (data_b), + .wren_a (wren_a), + .wren_b (wren_b), + .q_a (sub_wire0), + .q_b (sub_wire1), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .eccstatus (), + .rden_a (1'b1), + .rden_b (1'b1)); + defparam + altsyncram_component.address_reg_b = "CLOCK1", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.indata_reg_b = "CLOCK1", + altsyncram_component.init_file = "../target/pocket/build_id.mif", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 256, + altsyncram_component.numwords_b = 256, + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.outdata_reg_b = "CLOCK1", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 8, + altsyncram_component.widthad_b = 8, + altsyncram_component.width_a = 32, + altsyncram_component.width_b = 32, + altsyncram_component.width_byteena_a = 1, + altsyncram_component.width_byteena_b = 1, + altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: CLRdata NUMERIC "0" +// Retrieval info: PRIVATE: CLRq NUMERIC "0" +// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRrren NUMERIC "0" +// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRwren NUMERIC "0" +// Retrieval info: PRIVATE: Clock NUMERIC "5" +// Retrieval info: PRIVATE: Clock_A NUMERIC "0" +// Retrieval info: PRIVATE: Clock_B NUMERIC "0" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MEMSIZE NUMERIC "8192" +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "../target/pocket/build_id.mif" +// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" +// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGq NUMERIC "1" +// Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: REGrren NUMERIC "0" +// Retrieval info: PRIVATE: REGwraddress NUMERIC "1" +// Retrieval info: PRIVATE: REGwren NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" +// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" +// Retrieval info: PRIVATE: VarWidth NUMERIC "0" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "32" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "32" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "32" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "32" +// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: enable NUMERIC "0" +// Retrieval info: PRIVATE: rden NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" +// Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: INIT_FILE STRING "../target/pocket/build_id.mif" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" +// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "256" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "32" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "32" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" +// Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1" +// Retrieval info: USED_PORT: address_a 0 0 8 0 INPUT NODEFVAL "address_a[7..0]" +// Retrieval info: USED_PORT: address_b 0 0 8 0 INPUT NODEFVAL "address_b[7..0]" +// Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT VCC "clock_a" +// Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL "clock_b" +// Retrieval info: USED_PORT: data_a 0 0 32 0 INPUT NODEFVAL "data_a[31..0]" +// Retrieval info: USED_PORT: data_b 0 0 32 0 INPUT NODEFVAL "data_b[31..0]" +// Retrieval info: USED_PORT: q_a 0 0 32 0 OUTPUT NODEFVAL "q_a[31..0]" +// Retrieval info: USED_PORT: q_b 0 0 32 0 OUTPUT NODEFVAL "q_b[31..0]" +// Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a" +// Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b" +// Retrieval info: CONNECT: @address_a 0 0 8 0 address_a 0 0 8 0 +// Retrieval info: CONNECT: @address_b 0 0 8 0 address_b 0 0 8 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0 +// Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 32 0 data_a 0 0 32 0 +// Retrieval info: CONNECT: @data_b 0 0 32 0 data_b 0 0 32 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0 +// Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 +// Retrieval info: CONNECT: q_a 0 0 32 0 @q_a 0 0 32 0 +// Retrieval info: CONNECT: q_b 0 0 32 0 @q_b 0 0 32 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/platform/pocket/megafunctions/mf_ddio_bidir_12.qip b/platform/pocket/megafunctions/mf_ddio_bidir_12.qip new file mode 100644 index 0000000..40c4266 --- /dev/null +++ b/platform/pocket/megafunctions/mf_ddio_bidir_12.qip @@ -0,0 +1,5 @@ +set_global_assignment -name IP_TOOL_NAME "ALTDDIO_BIDIR" +set_global_assignment -name IP_TOOL_VERSION "18.1" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.ppf"] diff --git a/platform/pocket/megafunctions/mf_ddio_bidir_12.v b/platform/pocket/megafunctions/mf_ddio_bidir_12.v new file mode 100644 index 0000000..6bac1ab --- /dev/null +++ b/platform/pocket/megafunctions/mf_ddio_bidir_12.v @@ -0,0 +1,134 @@ +// megafunction wizard: %ALTDDIO_BIDIR% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: ALTDDIO_BIDIR + +// ============================================================ +// File Name: mf_ddio_bidir_12.v +// Megafunction Name(s): +// ALTDDIO_BIDIR +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 18.1.1 Build 646 04/11/2019 SJ Lite Edition +// ************************************************************ + + +//Copyright (C) 2019 Intel Corporation. All rights reserved. +//Your use of Intel Corporation's design tools, logic functions +//and other software and tools, and any partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Intel Program License +//Subscription Agreement, the Intel Quartus Prime License Agreement, +//the Intel FPGA IP License Agreement, or other applicable license +//agreement, including, without limitation, that your use is for +//the sole purpose of programming logic devices manufactured by +//Intel and sold by Intel or its authorized distributors. Please +//refer to the applicable agreement for further details, at +//https://fpgasoftware.intel.com/eula. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module mf_ddio_bidir_12 ( + datain_h, + datain_l, + inclock, + oe, + outclock, + dataout_h, + dataout_l, + padio); + + input [11:0] datain_h; + input [11:0] datain_l; + input inclock; + input oe; + input outclock; + output [11:0] dataout_h; + output [11:0] dataout_l; + inout [11:0] padio; + + wire [11:0] sub_wire0; + wire [11:0] sub_wire1; + wire [11:0] dataout_h = sub_wire0[11:0]; + wire [11:0] dataout_l = sub_wire1[11:0]; + + altddio_bidir ALTDDIO_BIDIR_component ( + .datain_h (datain_h), + .datain_l (datain_l), + .inclock (inclock), + .oe (oe), + .outclock (outclock), + .padio (padio), + .dataout_h (sub_wire0), + .dataout_l (sub_wire1), + .aclr (1'b0), + .aset (1'b0), + .combout (), + .dqsundelayedout (), + .inclocken (1'b1), + .oe_out (), + .outclocken (1'b1), + .sclr (1'b0), + .sset (1'b0)); + defparam + ALTDDIO_BIDIR_component.extend_oe_disable = "OFF", + ALTDDIO_BIDIR_component.implement_input_in_lcell = "OFF", + ALTDDIO_BIDIR_component.intended_device_family = "Cyclone V", + ALTDDIO_BIDIR_component.invert_output = "OFF", + ALTDDIO_BIDIR_component.lpm_hint = "UNUSED", + ALTDDIO_BIDIR_component.lpm_type = "altddio_bidir", + ALTDDIO_BIDIR_component.oe_reg = "UNREGISTERED", + ALTDDIO_BIDIR_component.power_up_high = "OFF", + ALTDDIO_BIDIR_component.width = 12; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V" +// Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "OFF" +// Retrieval info: CONSTANT: IMPLEMENT_INPUT_IN_LCELL STRING "OFF" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V" +// Retrieval info: CONSTANT: INVERT_OUTPUT STRING "OFF" +// Retrieval info: CONSTANT: LPM_HINT STRING "UNUSED" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_bidir" +// Retrieval info: CONSTANT: OE_REG STRING "UNREGISTERED" +// Retrieval info: CONSTANT: POWER_UP_HIGH STRING "OFF" +// Retrieval info: CONSTANT: WIDTH NUMERIC "12" +// Retrieval info: USED_PORT: datain_h 0 0 12 0 INPUT NODEFVAL "datain_h[11..0]" +// Retrieval info: CONNECT: @datain_h 0 0 12 0 datain_h 0 0 12 0 +// Retrieval info: USED_PORT: datain_l 0 0 12 0 INPUT NODEFVAL "datain_l[11..0]" +// Retrieval info: CONNECT: @datain_l 0 0 12 0 datain_l 0 0 12 0 +// Retrieval info: USED_PORT: dataout_h 0 0 12 0 OUTPUT NODEFVAL "dataout_h[11..0]" +// Retrieval info: CONNECT: dataout_h 0 0 12 0 @dataout_h 0 0 12 0 +// Retrieval info: USED_PORT: dataout_l 0 0 12 0 OUTPUT NODEFVAL "dataout_l[11..0]" +// Retrieval info: CONNECT: dataout_l 0 0 12 0 @dataout_l 0 0 12 0 +// Retrieval info: USED_PORT: inclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "inclock" +// Retrieval info: CONNECT: @inclock 0 0 0 0 inclock 0 0 0 0 +// Retrieval info: USED_PORT: oe 0 0 0 0 INPUT NODEFVAL "oe" +// Retrieval info: CONNECT: @oe 0 0 0 0 oe 0 0 0 0 +// Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "outclock" +// Retrieval info: CONNECT: @outclock 0 0 0 0 outclock 0 0 0 0 +// Retrieval info: USED_PORT: padio 0 0 12 0 BIDIR NODEFVAL "padio[11..0]" +// Retrieval info: CONNECT: padio 0 0 12 0 @padio 0 0 12 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.qip TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.bsf FALSE TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12_inst.v FALSE TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12_bb.v FALSE TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.inc FALSE TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.cmp FALSE TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.ppf TRUE FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/platform/pocket/memory/dpram_hs.sv b/platform/pocket/memory/dpram_hs.sv new file mode 100644 index 0000000..32bf74d --- /dev/null +++ b/platform/pocket/memory/dpram_hs.sv @@ -0,0 +1,80 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Generic Simple Dual-Port RAM (Single Clock) +// +// Copyright (c) 2022, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module dpram_hs + #( + parameter aWidth = 10, //! Address Port Width + parameter dWidth = 8, //! Data Port Width + // Used as attributes, not values + parameter rStyle = "no_rw_check" + ) ( + input logic clk, //! Clock + // Port A + input logic we_a, //! Write Enable + input logic [aWidth-1:0] addr_a, //! Address + input logic [dWidth-1:0] d_a, //! Input Data Bus + output logic [dWidth-1:0] q_a = 0, //! Output Data Bus + // Port B + input logic we_b, //! Write Enables + input logic [aWidth-1:0] addr_b, //! Address + input logic [dWidth-1:0] d_b, //! Input Data Bus + output logic [dWidth-1:0] q_b = 0 //! Output Data Bus + ); + + // Set the ram style to control implementation. + (* ramstyle = rStyle *) + logic [dWidth-1:0] ram[(1 << aWidth)-1:0]; //! Register to Hold Data + + // Read/Write from/to Memory on Port A + always_ff @(posedge clk) begin : portA + if(we_a) begin + ram[addr_a] <= d_a; + q_a <= d_a; + end + else begin + q_a <= ram[addr_a]; + end + end + + // Read/Write from/to Memory on Port B + always_ff @(posedge clk) begin : portB + if(we_b) begin + ram[addr_b] <= d_b; + q_b <= d_b; + end + else begin + q_b <= ram[addr_b]; + end + end + +endmodule diff --git a/platform/pocket/memory/spram_hs.sv b/platform/pocket/memory/spram_hs.sv new file mode 100644 index 0000000..df37299 --- /dev/null +++ b/platform/pocket/memory/spram_hs.sv @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Generic Simple Single-Port RAM (Single Clock) +// +// Copyright (c) 2022, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module spram_hs + #( + parameter aWidth = 10, //! Address Port Width + parameter dWidth = 8, //! Data Port Width + // Used as attributes, not values + parameter rStyle = "no_rw_check" + ) ( + input logic clk, //! Clock + input logic we, //! Write Enable + input logic [aWidth-1:0] addr, //! Address + input logic [dWidth-1:0] d, //! Input Data Bus + output logic [dWidth-1:0] q = 0 //! Output Data Bus + ); + + // Set the ram style to control implementation. + (* ramstyle = rStyle *) + logic [dWidth-1:0] ram[(1 << aWidth)-1:0]; //! Register to Hold Data + + // Read/Write from/to Memory + always_ff @(posedge clk) begin : singlePort + if(we) begin + ram[addr] <= d; + q <= d; + end + else begin + q <= ram[addr]; + end + end + +endmodule diff --git a/platform/pocket/memory/sram_async.sv b/platform/pocket/memory/sram_async.sv new file mode 100644 index 0000000..0fd8707 --- /dev/null +++ b/platform/pocket/memory/sram_async.sv @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Async SRAM Controller +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module sram_async + #( + parameter AW = 17, //! Address Width + parameter DW = 16 //! Data Width + ) ( + // User Interface + input logic [AW-1:0] addr, //! Address + input logic [DW-1:0] din, //! Data In + output logic [DW-1:0] dout, //! Data Out + input logic we_n, //! Write Enable + input logic oe_n, //! Output Enable + input logic [1:0] be_n, //! Byte Enable - [1] Upper Byte Mask | [0] Lower Byte Mask + // SRAM Interface + output logic [AW-1:0] sram_a, //! Address + inout logic [DW-1:0] sram_dq, //! Data In/Out + output logic sram_we_n, //! Write Enable + output logic sram_oe_n, //! Output Enable + output logic sram_ub_n, //! Upper Byte Mask + output logic sram_lb_n //! Lower Byte Mask + ); + + assign sram_a = addr; + assign sram_dq = sram_we_n ? {DW{1'bZ}} : din; + assign dout = sram_dq; + + assign sram_we_n = we_n; + assign sram_oe_n = oe_n; + assign sram_ub_n = be_n[1]; + assign sram_lb_n = be_n[0]; + +endmodule diff --git a/platform/pocket/peripherals/core_bridge_cmd.sv b/platform/pocket/peripherals/core_bridge_cmd.sv new file mode 100644 index 0000000..15a52e2 --- /dev/null +++ b/platform/pocket/peripherals/core_bridge_cmd.sv @@ -0,0 +1,630 @@ +// Software License Agreement + +// The software supplied herewith by Analogue Enterprises Limited (the "Company”), +// the Analogue Pocket Framework (“APF”), is provided and licensed to you, the +// Company's customer, solely for use in designing, testing and creating +// applications for use with Company's Products or Services. The software is +// owned by the Company and/or its licensors, and is protected under applicable +// laws, including, but not limited to, U.S. copyright law. All rights are +// reserved. By using the APF code you are agreeing to the terms of the End User +// License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula] +// and incorporated herein by reference. To the extent any use of the APF requires +// application of the MIT License or the GNU General Public License and terms of +// this APF Software License Agreement and EULA are inconsistent with such license, +// the applicable terms of the MIT License or the GNU General Public License, as +// applicable, will prevail. + +// THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED +// WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO, +// ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR +// NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM +// DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE +// MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED, +// THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND +// DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING +// THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR +// ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY +// INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES, +// INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR +// INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY +// OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY +// CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION, +// WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU +// TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH +// YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE +// FULLEST EXTENT PERMITTED BY APPLICABLE LAW. +// +// bridge host/target command handler +// 2022 Analogue +// + +// mapped to 0xF8xxxxxx on bridge +// the spec is loose enough to allow implementation with either +// block rams and a soft CPU, or simply hard logic with some case statements. +// +// the implementation spec is documented, and depending on your application you +// may want to completely replace this module. this is only one of many +// possible ways to accomplish the host/target command system and data table. +// +// this module should always be clocked by a direct clock input and never a PLL, +// because it should report PLL lock status +// +// altera message_off 10030 +// altera message_off 10036 +// altera message_off 10230 +// altera message_off 10858 +// altera message_off 10762 + +`default_nettype none +`timescale 1ns/1ps + +module core_bridge_cmd + ( + input wire clk, + output reg reset_n, + + input wire bridge_endian_little, + input wire [31:0] bridge_addr, + input wire bridge_rd, + output reg [31:0] bridge_rd_data, + input wire bridge_wr, + input wire [31:0] bridge_wr_data, + + // all these signals should be synchronous to clk + // add synchronizers if these need to be used in other clock domains + input wire status_boot_done, // assert when PLLs lock and logic is ready + input wire status_setup_done, // assert when core is happy with what's been loaded into it + input wire status_running, // assert when pocket's taken core out of reset and is running + + output reg dataslot_requestread, + output reg [15:0] dataslot_requestread_id, + input wire dataslot_requestread_ack, + input wire dataslot_requestread_ok, + + output reg dataslot_requestwrite, + output reg [15:0] dataslot_requestwrite_id, + output reg [31:0] dataslot_requestwrite_size, + input wire dataslot_requestwrite_ack, + input wire dataslot_requestwrite_ok, + + output reg dataslot_update, + output reg [15:0] dataslot_update_id, + output reg [31:0] dataslot_update_size, + + output reg dataslot_allcomplete, + + output reg [31:0] rtc_epoch_seconds, + output reg [31:0] rtc_date_bcd, + output reg [31:0] rtc_time_bcd, + output reg rtc_valid, + + input wire savestate_supported, + input wire [31:0] savestate_addr, + input wire [31:0] savestate_size, + input wire [31:0] savestate_maxloadsize, + + output reg osnotify_inmenu, + output reg osnotify_docked, + output reg osnotify_grayscale, + + output reg savestate_start, // core should detect rising edge on this, + input wire savestate_start_ack, // and then assert ack for at least 1 cycle + input wire savestate_start_busy, // assert constantly while in progress after ack + input wire savestate_start_ok, // assert continuously when done, and clear when new process is started + input wire savestate_start_err, // assert continuously on error, and clear when new process is started + + output reg savestate_load, + input wire savestate_load_ack, + input wire savestate_load_busy, + input wire savestate_load_ok, + input wire savestate_load_err, + + input wire target_dataslot_read, // rising edge triggered + input wire target_dataslot_write, + input wire target_dataslot_getfile, + input wire target_dataslot_openfile, + + output reg target_dataslot_ack, // asserted upon command start until completion + output reg target_dataslot_done, // asserted upon command finish until next command is issued + output reg [2:0] target_dataslot_err, // contains result of command execution. zero is OK + + input wire [15:0] target_dataslot_id, // parameters for each of the read/reload/write commands + input wire [31:0] target_dataslot_slotoffset, + input wire [31:0] target_dataslot_bridgeaddr, + input wire [31:0] target_dataslot_length, + + input wire [31:0] target_buffer_param_struct, // bus address of the memory region APF will fetch additional parameter struct from + input wire [31:0] target_buffer_resp_struct, // bus address of the memory region APF will write its response struct to + // this should be mapped by the developer, the buffer is not implemented in this file + + input wire [9:0] datatable_addr, + input wire datatable_wren, + input wire [31:0] datatable_data, + output wire [31:0] datatable_q + ); + + // handle endianness + reg [31:0] bridge_wr_data_in; + reg [31:0] bridge_rd_data_out; + + wire endian_little_s; + synch_3 s01(bridge_endian_little, endian_little_s, clk); + + always @(*) begin + bridge_rd_data <= endian_little_s ? { + bridge_rd_data_out[7:0], + bridge_rd_data_out[15:8], + bridge_rd_data_out[23:16], + bridge_rd_data_out[31:24] + } : bridge_rd_data_out; + + bridge_wr_data_in <= endian_little_s ? { + bridge_wr_data[7:0], + bridge_wr_data[15:8], + bridge_wr_data[23:16], + bridge_wr_data[31:24] + } : bridge_wr_data; + end + + // minimalistic approach here - + // keep the commonly used registers in logic, but data table in BRAM. + // implementation could be changed quite a bit for a more advanced use case + + // host + reg [31:0] host_0; + reg [31:0] host_4 = 'h20; // host cmd parameter data at 0x20 + reg [31:0] host_8 = 'h40; // host cmd response data at 0x40 + + reg [31:0] host_20; // parameter data + reg [31:0] host_24; + reg [31:0] host_28; + reg [31:0] host_2C; + + reg [31:0] host_40; // response data + reg [31:0] host_44; + reg [31:0] host_48; + reg [31:0] host_4C; + + reg host_cmd_start; + reg [15:0] host_cmd_startval; + reg [15:0] host_cmd; + reg [15:0] host_resultcode; + + localparam [3:0] ST_IDLE = 'd0; + localparam [3:0] ST_PARSE = 'd1; + localparam [3:0] ST_WORK = 'd2; + localparam [3:0] ST_DONE_OK = 'd13; + localparam [3:0] ST_DONE_CODE = 'd14; + localparam [3:0] ST_DONE_ERR = 'd15; + reg [3:0] hstate; + + // target + reg [31:0] target_0; + reg [31:0] target_4 = 'h20; + reg [31:0] target_8 = 'h40; + + reg [31:0] target_20; // parameter data + reg [31:0] target_24; + reg [31:0] target_28; + reg [31:0] target_2C; + + reg [31:0] target_40; // response data + reg [31:0] target_44; + reg [31:0] target_48; + reg [31:0] target_4C; + + localparam [3:0] TARG_ST_IDLE = 'd0; + localparam [3:0] TARG_ST_READYTORUN = 'd1; + localparam [3:0] TARG_ST_DATASLOTOP = 'd2; + localparam [3:0] TARG_ST_WAITRESULT_RTR = 'd14; + localparam [3:0] TARG_ST_WAITRESULT_DSO = 'd15; + reg [3:0] tstate; + + reg status_setup_done_1, status_setup_done_queue; + reg target_dataslot_read_1, target_dataslot_read_queue; + reg target_dataslot_write_1, target_dataslot_write_queue; + reg target_dataslot_getfile_1, target_dataslot_getfile_queue; + reg target_dataslot_openfile_1, target_dataslot_openfile_queue; + + initial begin + reset_n <= 0; + dataslot_requestread <= 0; + dataslot_requestwrite <= 0; + dataslot_update <= 0; + dataslot_allcomplete <= 0; + rtc_valid <= 0; + savestate_start <= 0; + savestate_load <= 0; + + osnotify_inmenu <= 0; + osnotify_docked <= 0; + osnotify_grayscale <= 0; + + status_setup_done_queue <= 0; + target_dataslot_read_queue <= 0; + target_dataslot_write_queue <= 0; + target_dataslot_getfile_queue <= 0; + target_dataslot_openfile_queue <= 0; + target_dataslot_ack <= 0; + target_dataslot_done <= 0; + target_dataslot_err <= 0; + end + + always @(posedge clk) begin + // detect a rising edge on the input signal + // and flag a queue that will be cleared later + status_setup_done_1 <= status_setup_done; + target_dataslot_read_1 <= target_dataslot_read; + target_dataslot_write_1 <= target_dataslot_write; + target_dataslot_getfile_1 <= target_dataslot_getfile; + target_dataslot_openfile_1 <= target_dataslot_openfile; + + if(status_setup_done & ~status_setup_done_1) begin + status_setup_done_queue <= 1; + end + if(target_dataslot_read & ~target_dataslot_read_1) begin + target_dataslot_read_queue <= 1; + end + if(target_dataslot_write & ~target_dataslot_write_1) begin + target_dataslot_write_queue <= 1; + end + if(target_dataslot_getfile & ~target_dataslot_getfile_1) begin + target_dataslot_getfile_queue <= 1; + end + if(target_dataslot_openfile & ~target_dataslot_openfile_1) begin + target_dataslot_openfile_queue <= 1; + end + + b_datatable_wren <= 0; + b_datatable_addr <= bridge_addr >> 2; + + if(bridge_wr) begin + casex(bridge_addr) + 32'hF8xx00xx: begin + case(bridge_addr[7:0]) + 8'h0: begin + host_0 <= bridge_wr_data_in; // command/status + // check for command + if(bridge_wr_data_in[31:16] == 16'h434D) begin + // host wants us to do a command + host_cmd_startval <= bridge_wr_data_in[15:0]; + host_cmd_start <= 1; + end + end + 8'h20: host_20 <= bridge_wr_data_in; // parameter data regs + 8'h24: host_24 <= bridge_wr_data_in; + 8'h28: host_28 <= bridge_wr_data_in; + 8'h2C: host_2C <= bridge_wr_data_in; + endcase + end + 32'hF8xx10xx: begin + case(bridge_addr[7:0]) + 8'h0: target_0 <= bridge_wr_data_in; // command/status + 8'h4: target_4 <= bridge_wr_data_in; // parameter data pointer + 8'h8: target_8 <= bridge_wr_data_in; // response data pointer + 8'h40: target_40 <= bridge_wr_data_in; // response data regs + 8'h44: target_44 <= bridge_wr_data_in; + 8'h48: target_48 <= bridge_wr_data_in; + 8'h4C: target_4C <= bridge_wr_data_in; + endcase + end + 32'hF8xx2xxx: begin + b_datatable_wren <= 1; + end + endcase + end + if(bridge_rd) begin + casex(bridge_addr) + 32'hF8xx00xx: begin + case(bridge_addr[7:0]) + 8'h0: bridge_rd_data_out <= host_0; // command/status + 8'h4: bridge_rd_data_out <= host_4; // parameter data pointer + 8'h8: bridge_rd_data_out <= host_8; // response data pointer + 8'h40: bridge_rd_data_out <= host_40; // response data regs + 8'h44: bridge_rd_data_out <= host_44; + 8'h48: bridge_rd_data_out <= host_48; + 8'h4C: bridge_rd_data_out <= host_4C; + endcase + end + 32'hF8xx10xx: begin + case(bridge_addr[7:0]) + 8'h0: bridge_rd_data_out <= target_0; + 8'h4: bridge_rd_data_out <= target_4; + 8'h8: bridge_rd_data_out <= target_8; + 8'h20: bridge_rd_data_out <= target_20; // parameter data regs + 8'h24: bridge_rd_data_out <= target_24; + 8'h28: bridge_rd_data_out <= target_28; + 8'h2C: bridge_rd_data_out <= target_2C; + endcase + end + 32'hF8xx2xxx: begin + bridge_rd_data_out <= b_datatable_q; + end + endcase + end + + // host > target command executer + case(hstate) + ST_IDLE: begin + dataslot_requestread <= 0; + dataslot_requestwrite <= 0; + dataslot_update <= 0; + savestate_start <= 0; + savestate_load <= 0; + + // there is no queueing. pocket will always make sure any outstanding host + // commands are finished before starting another + if(host_cmd_start) begin + host_cmd_start <= 0; + // save the command in case it gets clobbered later + host_cmd <= host_cmd_startval; + hstate <= ST_PARSE; + end + end + ST_PARSE: begin + // overwrite command semaphore with busy flag + host_0 <= {16'h4255, host_cmd}; + + case(host_cmd) + 16'h0000: begin + // Request Status + host_resultcode <= 1; // default: booting + if(status_boot_done) begin + host_resultcode <= 2; // setup + if(status_setup_done) begin + host_resultcode <= 3; // idle + end + else if(status_running) begin + host_resultcode <= 4; // running + end + end + hstate <= ST_DONE_CODE; + end + 16'h0010: begin + // Reset Enter + reset_n <= 0; + hstate <= ST_DONE_OK; + end + 16'h0011: begin + // Reset Exit + reset_n <= 1; + hstate <= ST_DONE_OK; + end + 16'h0080: begin + // Data slot request read + dataslot_allcomplete <= 0; + dataslot_requestread <= 1; + dataslot_requestread_id <= host_20[15:0]; + if(dataslot_requestread_ack) begin + host_resultcode <= 0; + if(!dataslot_requestread_ok) host_resultcode <= 2; + hstate <= ST_DONE_CODE; + end + end + 16'h0082: begin + // Data slot request write + dataslot_allcomplete <= 0; + dataslot_requestwrite <= 1; + dataslot_requestwrite_id <= host_20[15:0]; + dataslot_requestwrite_size <= host_24; + if(dataslot_requestwrite_ack) begin + host_resultcode <= 0; + if(!dataslot_requestwrite_ok) host_resultcode <= 2; + hstate <= ST_DONE_CODE; + end + end + 16'h008A: begin + // Data slot update (sent on deferload marked slots only) + dataslot_update <= 1; + dataslot_update_id <= host_20[15:0]; + dataslot_update_size <= host_24; + hstate <= ST_DONE_OK; + end + 16'h008F: begin + // Data slot access all complete + dataslot_allcomplete <= 1; + hstate <= ST_DONE_OK; + end + 16'h0090: begin + // Real-time Clock Data + // user logic should detect rising edge, it is not continuously updated + rtc_valid <= 1; + rtc_epoch_seconds <= host_20; + rtc_date_bcd <= host_24; + rtc_time_bcd <= host_28; + hstate <= ST_DONE_OK; + end + 16'h00A0: begin + // Savestate: Start/Query + host_40 <= savestate_supported; + host_44 <= savestate_addr; + host_48 <= savestate_size; + + host_resultcode <= 0; + if(savestate_start_busy) host_resultcode <= 1; + if(savestate_start_ok) host_resultcode <= 2; + if(savestate_start_err) host_resultcode <= 3; + + if(host_20[0]) begin + // Request Start! + savestate_start <= 1; + // stay in this state until ack'd + if(savestate_start_ack) begin + hstate <= ST_DONE_CODE; + end + end + else begin + hstate <= ST_DONE_CODE; + end + end + 16'h00A4: begin + // Savestate: Load/Query + host_40 <= savestate_supported; + host_44 <= savestate_addr; + host_48 <= savestate_maxloadsize; + + host_resultcode <= 0; + if(savestate_load_busy) host_resultcode <= 1; + if(savestate_load_ok) host_resultcode <= 2; + if(savestate_load_err) host_resultcode <= 3; + + if(host_20[0]) begin + // Request Load! + savestate_load <= 1; + // stay in this state until ack'd + if(savestate_load_ack) begin + hstate <= ST_DONE_CODE; + end + end + else begin + hstate <= ST_DONE_CODE; + end + end + 16'h00B0: begin + // OS Notify: Menu State + osnotify_inmenu <= host_20[0]; + hstate <= ST_DONE_OK; + end + // 16'h00B1: begin + // // OS Notify: Cartridge Adapter + // // TODO: IMPLEMENT + // end + 16'h00B2: begin + // OS Notify: Docked State + osnotify_docked <= host_20[0]; + hstate <= ST_DONE_OK; + end + 16'h00B8: begin + // OS Notify: Grayscale Display Mode + osnotify_grayscale <= host_20[0]; + if(host_20[0]) begin + host_40 <= 16'h444D; + hstate <= ST_DONE_OK; + end else begin + hstate <= ST_DONE_OK; + end + end + default: begin + hstate <= ST_DONE_ERR; + end + endcase + end + ST_WORK: begin + hstate <= ST_IDLE; + end + ST_DONE_OK: begin + host_0 <= 32'h4F4B0000; // result code 0 + hstate <= ST_IDLE; + end + ST_DONE_CODE: begin + host_0 <= {16'h4F4B, host_resultcode}; + hstate <= ST_IDLE; + end + ST_DONE_ERR: begin + host_0 <= 32'h4F4BFFFF; // result code FFFF = unknown command + hstate <= ST_IDLE; + end + endcase + + // target > host command executer + case(tstate) + TARG_ST_IDLE: begin + target_dataslot_ack <= 0; + if(status_setup_done_queue) begin + status_setup_done_queue <= 0; + tstate <= TARG_ST_READYTORUN; + end + else if(target_dataslot_read_queue) begin + target_dataslot_read_queue <= 0; + target_0[15:0] <= 16'h0180; + + target_20 <= target_dataslot_id; + target_24 <= target_dataslot_slotoffset; + target_28 <= target_dataslot_bridgeaddr; + target_2C <= target_dataslot_length; + + tstate <= TARG_ST_DATASLOTOP; + end + else if(target_dataslot_write_queue) begin + target_dataslot_write_queue <= 0; + target_0[15:0] <= 16'h0184; + + target_20 <= target_dataslot_id; + target_24 <= target_dataslot_slotoffset; + target_28 <= target_dataslot_bridgeaddr; + target_2C <= target_dataslot_length; + + tstate <= TARG_ST_DATASLOTOP; + end + else if(target_dataslot_getfile_queue) begin + target_dataslot_getfile_queue <= 0; + target_0[15:0] <= 16'h0190; + + target_20 <= target_dataslot_id; + target_24 <= target_buffer_resp_struct; // pointer to the bram that will hold the response struct + // which will contain the requested filename before command completion + tstate <= TARG_ST_DATASLOTOP; + end + else if(target_dataslot_openfile_queue) begin + target_dataslot_openfile_queue <= 0; + target_0[15:0] <= 16'h0192; + + target_20 <= target_dataslot_id; + target_24 <= target_buffer_param_struct; // pointer to the bram that will hold the parameter struct + // which must contain the desired filename and flag/size before command execution + tstate <= TARG_ST_DATASLOTOP; + end + end + TARG_ST_READYTORUN: begin + target_0 <= 32'h636D_0140; + tstate <= TARG_ST_WAITRESULT_RTR; + end + TARG_ST_DATASLOTOP: begin + target_0[31:16] <= 16'h636D; + + target_dataslot_done <= 0; + target_dataslot_err <= 0; + tstate <= TARG_ST_WAITRESULT_DSO; + end + TARG_ST_WAITRESULT_DSO: begin + if(target_0[31:16] == 16'h6275) begin + target_dataslot_ack <= 1; + end + if(target_0[31:16] == 16'h6F6B) begin + // done + // save result code + target_dataslot_err <= target_0[2:0]; + // assert done + target_dataslot_done <= 1; + tstate <= TARG_ST_IDLE; + end + end + TARG_ST_WAITRESULT_RTR: begin + if(target_0[31:16] == 16'h6F6B) begin + // done + tstate <= TARG_ST_IDLE; + end + end + endcase + end + + wire [31:0] b_datatable_q; + reg [9:0] b_datatable_addr; + reg b_datatable_wren; + + mf_datatable idt + ( + .clock_a ( clk ), + .wren_a ( datatable_wren ), + .address_a ( datatable_addr ), + .data_a ( datatable_data ), + .q_a ( datatable_q ), + + .clock_b ( clk ), + .wren_b ( b_datatable_wren ), + .address_b ( b_datatable_addr ), + .data_b ( bridge_wr_data_in ), + .q_b ( b_datatable_q ) + ); + +endmodule diff --git a/platform/pocket/peripherals/io_bridge_peripheral.sv b/platform/pocket/peripherals/io_bridge_peripheral.sv new file mode 100644 index 0000000..bfb9d00 --- /dev/null +++ b/platform/pocket/peripherals/io_bridge_peripheral.sv @@ -0,0 +1,319 @@ +// Software License Agreement + +// The software supplied herewith by Analogue Enterprises Limited (the "Company”), +// the Analogue Pocket Framework (“APF”), is provided and licensed to you, the +// Company's customer, solely for use in designing, testing and creating +// applications for use with Company's Products or Services. The software is +// owned by the Company and/or its licensors, and is protected under applicable +// laws, including, but not limited to, U.S. copyright law. All rights are +// reserved. By using the APF code you are agreeing to the terms of the End User +// License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula] +// and incorporated herein by reference. To the extent any use of the APF requires +// application of the MIT License or the GNU General Public License and terms of +// this APF Software License Agreement and EULA are inconsistent with such license, +// the applicable terms of the MIT License or the GNU General Public License, as +// applicable, will prevail. + +// THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED +// WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO, +// ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR +// NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM +// DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE +// MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED, +// THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND +// DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING +// THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR +// ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY +// INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES, +// INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR +// INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY +// OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY +// CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION, +// WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU +// TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH +// YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE +// FULLEST EXTENT PERMITTED BY APPLICABLE LAW. +// +// bridge peripheral for socrates PMP bridge to heraclitus+aristotle +// 2020-2022 Analogue +// +// please note that while writes are immediate, +// reads are buffered by 1 word. this is necessary to maintain +// data throughput while reading from slower data sources like +// sdram. +// reads should always return the current bus value, and kickstart +// into the next read immediately. this way, you have the entire +// next word time to retrieve the data, instead of just a few +// cycles. +// +// the worst-case read/write timing is every 88 cycles @ 74.25mhz +// which is about 1180ns. + +`default_nettype none +`timescale 1ns/1ps + +module io_bridge_peripheral + ( + input wire clk, + input wire reset_n, + + input wire endian_little, + + output reg [31:0] pmp_addr, + output reg pmp_addr_valid, + output reg pmp_rd, + input wire [31:0] pmp_rd_data, + output reg pmp_wr, + output reg [31:0] pmp_wr_data, + + inout reg phy_spimosi, + inout reg phy_spimiso, + inout reg phy_spiclk, + input wire phy_spiss + ); + + // + // clock domain: clk (74.25mhz) rising edge + // + wire reset_n_s; + synch_3 s00(reset_n, reset_n_s, clk); + + wire endian_little_s; + synch_3 s01(endian_little, endian_little_s, clk); + + wire phy_spiss_s, phy_spiss_r, phy_spiss_f; + synch_3 s02(phy_spiss, phy_spiss_s, clk, phy_spiss_r, phy_spiss_f); + + reg [4:0] state; + localparam ST_RESET = 'd0; + localparam ST_IDLE = 'd1; + localparam ST_READ_0 = 'd2; + localparam ST_READ_1 = 'd3; + localparam ST_READ_2 = 'd4; + localparam ST_READ_3 = 'd5; + localparam ST_WRITE_0 = 'd6; + localparam ST_WRITE_1 = 'd7; + localparam ST_WRITE_2 = 'd8; + localparam ST_ADDR_0 = 'd9; + + reg [1:0] addr_cnt; + reg [1:0] data_cnt; + reg [6:0] read_cnt; + + // synchronize rd byte flag's rising edge into clk + wire rx_byte_done_s, rx_byte_done_r; + synch_3 s03(rx_byte_done, rx_byte_done_s, clk, rx_byte_done_r); + + reg [4:0] spis; + localparam ST_SIDLE = 'd1; + localparam ST_SEND_N = 'd6; + localparam ST_SEND_0 = 'd2; + localparam ST_SEND_1 = 'd3; + localparam ST_SEND_2 = 'd4; + localparam ST_SEND_3 = 'd5; + reg spis_tx; + reg [31:0] spis_word_tx; + reg [31:0] spis_word; + reg [4:0] spis_count; + reg spis_done; + + reg rx_byte_done_r_1, rx_byte_done_r_2; + reg [7:0] rx_byte_1, rx_byte_2; + + // handle reversing endianness on both ports + reg [31:0] pmp_wr_data_latch; + reg [31:0] pmp_rd_data_e; // asynchronous + reg [31:0] pmp_rd_data_buf; // buffer the last word for immediate response + always @(*) begin + pmp_wr_data <= endian_little_s ? { pmp_wr_data_latch[7:0], + pmp_wr_data_latch[15:8], + pmp_wr_data_latch[23:16], + pmp_wr_data_latch[31:24] + } : pmp_wr_data_latch; + + pmp_rd_data_e <= endian_little_s ? {pmp_rd_data[7:0], + pmp_rd_data[15:8], + pmp_rd_data[23:16], + pmp_rd_data[31:24] + } : pmp_rd_data; + end + + always @(posedge clk) begin + rx_byte_2 <= rx_byte_1; + rx_byte_1 <= rx_byte; + rx_byte_done_r_1 <= rx_byte_done_r; + rx_byte_done_r_2 <= rx_byte_done_r_1; + case(state) + ST_RESET: begin + addr_cnt <= 0; + data_cnt <= 0; + pmp_wr <= 0; + pmp_rd <= 0; + pmp_addr_valid <= 0; + spis_tx <= 0; + state <= ST_ADDR_0; + end + ST_ADDR_0: begin + // transaction has started + if(rx_byte_done_r_2) begin + case(addr_cnt) + 0: pmp_addr[31:24] <= rx_byte_2; + 1: pmp_addr[23:16] <= rx_byte_2; + 2: pmp_addr[15: 8] <= rx_byte_2; + 3: begin + pmp_addr[ 7: 0] <= {rx_byte_2[7:2], 2'b00}; + // address is latched + if( rx_byte_2[0] ) begin + data_cnt <= 0; + state <= ST_WRITE_0; + end + else begin + data_cnt <= 0; + read_cnt <= 0; + state <= ST_READ_0; + end + end + endcase + addr_cnt <= addr_cnt + 1'b1; + end + end + ST_WRITE_0: begin + // give notice, address has become valid + pmp_addr_valid <= 1; + if(rx_byte_done_r_2) begin + case(data_cnt) + 0: pmp_wr_data_latch[31:24] <= rx_byte_2; + 1: pmp_wr_data_latch[23:16] <= rx_byte_2; + 2: pmp_wr_data_latch[15: 8] <= rx_byte_2; + 3: begin + pmp_wr_data_latch[ 7: 0] <= rx_byte_2; + state <= ST_WRITE_1; + end + endcase + data_cnt <= data_cnt + 1'b1; + end + end + ST_WRITE_1: begin + pmp_wr <= 1; + state <= ST_WRITE_2; + end + ST_WRITE_2: begin + // exited upon new transaction + pmp_wr <= 0; + end + ST_READ_0: begin + pmp_addr_valid <= 1; + // delay a few cycles + read_cnt <= read_cnt + 1'b1; + if(read_cnt == 4-1) begin + // load the buffer with the current data + // and give the current buffer contents to bridge + spis_word_tx <= pmp_rd_data_e; + spis_tx <= 1; + state <= ST_READ_1; + end + end + ST_READ_1: begin + pmp_rd <= 1; + state <= ST_READ_2; + end + ST_READ_2: begin + pmp_rd <= 0; + if(spis_done) begin + spis_tx <= 0; + state <= ST_READ_3; + end + end + ST_READ_3: begin + // exited upon new transaction + end + endcase + + // + // word transmit + // + spis_done <= 0; + case(spis) + ST_SIDLE: begin + spis_count <= 0; + phy_spiclk <= 1'bZ; + phy_spimosi <= 1'bZ; + phy_spimiso <= 1'bZ; + if(spis_tx) begin + spis_word <= spis_word_tx; + spis <= ST_SEND_N; + end + end + // drive high first + ST_SEND_N: begin + phy_spiclk <= 1'b1; + phy_spimosi <= 1'b1; + phy_spimiso <= 1'b1; + spis <= ST_SEND_0; + end + // tx, shift out bits + ST_SEND_0: begin + phy_spiclk <= 0; + spis <= ST_SEND_1; + phy_spimosi <= spis_word[31]; + phy_spimiso <= spis_word[30]; + spis_word <= {spis_word[29:0], 2'b00}; + end + ST_SEND_1: begin + phy_spiclk <= 1; + spis <= ST_SEND_0; + spis_count <= spis_count + 1'b1; + if(spis_count == 15) begin + spis <= ST_SEND_2; + end + end + ST_SEND_2: begin + phy_spiclk <= 1'b1; + phy_spimosi <= 1'b1; + phy_spimiso <= 1'b1; + spis <= ST_SEND_3; + spis_done <= 1; + end + ST_SEND_3: begin + spis <= ST_SIDLE; + end + endcase + if(phy_spiss_s) begin + // select is high, go back to reset + state <= ST_RESET; + spis <= ST_SIDLE; + end + end + + // + // clock domain: phy_spiclk rising edge + // + reg [1:0] rx_latch_idx; + reg [7:0] rx_dat; + reg [7:0] rx_byte; // latched by clk, but upon a synchronized trigger + reg rx_byte_done; + + always @(posedge phy_spiclk or posedge phy_spiss) begin + if(phy_spiss) begin + // reset + rx_byte_done <= 0; + rx_latch_idx <= 0; + end + else begin + // spiclk rising edge, latch data + rx_byte_done <= 0; + case(rx_latch_idx) + 0: begin rx_dat[7:6] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 1; end + 1: begin rx_dat[5:4] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 2; end + 2: begin rx_dat[3:2] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 3; end + 3: begin + // last bit of the byte + rx_byte <= {rx_dat[7:2], phy_spimosi, phy_spimiso}; + rx_latch_idx <= 0; + rx_byte_done <= 1; + end + endcase + end + end + +endmodule diff --git a/platform/pocket/peripherals/io_pad_controller.sv b/platform/pocket/peripherals/io_pad_controller.sv new file mode 100644 index 0000000..478b22f --- /dev/null +++ b/platform/pocket/peripherals/io_pad_controller.sv @@ -0,0 +1,316 @@ +// Software License Agreement + +// The software supplied herewith by Analogue Enterprises Limited (the "Company”), +// the Analogue Pocket Framework (“APF”), is provided and licensed to you, the +// Company's customer, solely for use in designing, testing and creating +// applications for use with Company's Products or Services. The software is +// owned by the Company and/or its licensors, and is protected under applicable +// laws, including, but not limited to, U.S. copyright law. All rights are +// reserved. By using the APF code you are agreeing to the terms of the End User +// License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula] +// and incorporated herein by reference. To the extent any use of the APF requires +// application of the MIT License or the GNU General Public License and terms of +// this APF Software License Agreement and EULA are inconsistent with such license, +// the applicable terms of the MIT License or the GNU General Public License, as +// applicable, will prevail. + +// THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED +// WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO, +// ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR +// NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM +// DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE +// MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED, +// THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND +// DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING +// THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR +// ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY +// INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES, +// INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR +// INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY +// OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY +// CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION, +// WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU +// TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH +// YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE +// FULLEST EXTENT PERMITTED BY APPLICABLE LAW. +// +// pad controller +// 2020-08-17 Analogue +// + +`default_nettype none +`timescale 1ns/1ps + +module io_pad_controller + ( + input wire clk, + input wire reset_n, + + inout reg pad_1wire, + + output reg [31:0] cont1_key, + output reg [31:0] cont2_key, + output reg [31:0] cont3_key, + output reg [31:0] cont4_key, + output reg [31:0] cont1_joy, + output reg [31:0] cont2_joy, + output reg [31:0] cont3_joy, + output reg [31:0] cont4_joy, + output reg [15:0] cont1_trig, + output reg [15:0] cont2_trig, + output reg [15:0] cont3_trig, + output reg [15:0] cont4_trig, + + output reg rx_timed_out + ); + + wire reset_n_s; + synch_3 s00(reset_n, reset_n_s, clk); + + wire pad_1wire_s, pad_1wire_r, pad_1wire_f; + synch_3 s01(pad_1wire, pad_1wire_s, clk, pad_1wire_r, pad_1wire_f); + + // + // protocol fsm + // + reg [20:0] rx_timeout; // ~28ms + + reg [15:0] auto_poll_cnt; // 882us + reg auto_poll_queue; + + reg [18:0] heartbeat_cnt; // 7ms + reg heartbeat_queue; + + localparam ST_RESET = 'd0; + localparam ST_IDLE = 'd1; + localparam ST_RX_BUTTON_1 = 'd2; + localparam ST_RX_BUTTON_2 = 'd3; + localparam ST_TX_SCALER = 'd4; + localparam ST_END_TX = 'd5; + + reg [3:0] state; + reg [3:0] cnt; + + always @(posedge clk) begin + tx_word_start <= 0; + + auto_poll_cnt <= auto_poll_cnt + 1'b1; + heartbeat_cnt <= heartbeat_cnt + 1'b1; + + // increment rx timeout, override and reset when idle below + rx_timeout <= rx_timeout + 1'b1; + + case(state) + ST_RESET: begin + reset_tr_n <= 0; + rx_timed_out <= 0; + + if(&rx_timeout[19:0]) begin + state <= ST_IDLE; + end + end + ST_IDLE: begin + // idle state + reset_tr_n <= 1; + rx_timeout <= 0; + cnt <= 0; + if(auto_poll_queue) begin + auto_poll_queue <= 0; + + tx_word_start <= 1; + tx_word <= 32'h4A10000C; + + state <= ST_RX_BUTTON_1; + end + else if(heartbeat_queue) begin + heartbeat_queue <= 0; + + tx_word_start <= 1; + tx_word <= 32'h4AFE0000; + + state <= ST_END_TX; + end + end + // receive button words + ST_RX_BUTTON_1: begin + if(tx_word_done) begin + state <= ST_RX_BUTTON_2; + end + end + ST_RX_BUTTON_2: begin + if(rx_word_done) begin + cnt <= cnt + 1'b1; + case(cnt) + 0: cont1_key <= rx_word; + 1: cont1_joy <= rx_word; + 2: cont1_trig <= rx_word[15:0]; + + 3: cont2_key <= rx_word; + 4: cont2_joy <= rx_word; + 5: cont2_trig <= rx_word[15:0]; + + 6: cont3_key <= rx_word; + 7: cont3_joy <= rx_word; + 8: cont3_trig <= rx_word[15:0]; + + 9: cont4_key <= rx_word; + 10: cont4_joy <= rx_word; + 11: begin + cont4_trig <= rx_word[15:0]; + state <= ST_IDLE; + end + endcase + end + end + // do nothing + ST_END_TX: begin + // done sending, idle again + if(tx_word_done) begin + state <= ST_IDLE; + end + end + endcase + + if(&auto_poll_cnt) begin + auto_poll_queue <= 1; + end + + if(&heartbeat_cnt) begin + heartbeat_queue <= 1; + end + + if(&rx_timeout) begin + // reset protocol FSM which will also reset t/r engine + rx_timed_out <= 1; + rx_timeout <= 0; + state <= ST_RESET; + end + + if(~reset_n_s) begin + state <= ST_RESET; + end + end + + // + // word receive/transmit engine + // + reg reset_tr_n; + localparam BITLEN = 60; + + reg rx_word_done; + reg [31:0] rx_word_shift; + reg [31:0] rx_word; + + reg tx_word_start, tx_word_start_1; + reg tx_word_done; + reg [31:0] tx_word; + reg [31:0] tx_word_shift; + + reg [7:0] tr_cnt; + reg [5:0] tr_bit; + + localparam TR_IDLE = 'd1; + localparam TR_TX_START = 'd2; + localparam TR_TX_CONTINUE = 'd3; + localparam TR_TX_DONE = 'd4; + localparam TR_RX_START = 'd5; + localparam TR_RX_WAITEDGE = 'd6; + localparam TR_RX_DONE = 'd7; + + reg [3:0] tr_state; + + always @(posedge clk) begin + rx_word_done <= 0; + tx_word_done <= 0; + tx_word_start_1 <= tx_word_start; + case(tr_state) + TR_IDLE: begin + tr_bit <= 0; + tr_cnt <= 0; + pad_1wire <= 1'bZ; + if(tx_word_start & ~tx_word_start_1) begin + // transmit word + tx_word_shift <= tx_word; + tr_state <= TR_TX_START; + end + if(pad_1wire_f) begin + // receive word + tr_state <= TR_RX_START; + end + end + // transmit 32bit + TR_TX_START: begin + // insert delay + tr_cnt <= tr_cnt + 1'b1; + if(&tr_cnt) begin + // drive from tristate(high) to explicitly high to prevent glitching + pad_1wire <= 1'b1; + tr_state <= TR_TX_CONTINUE; + end + end + TR_TX_CONTINUE: begin + tr_cnt <= tr_cnt + 1'b1; + case(tr_cnt) + 0: begin + pad_1wire <= 1'b0; + end + (BITLEN/3): begin + pad_1wire <= tx_word_shift[31]; + end + (BITLEN*2/3): begin + pad_1wire <= 1'b1; + end + (BITLEN-1): begin + tr_cnt <= 0; + tx_word_shift <= {tx_word_shift[30:0], 1'b1}; + tr_bit <= tr_bit + 1'b1; + if(tr_bit == 31) begin + tr_state <= TR_TX_DONE; + end + end + endcase + end + TR_TX_DONE: begin + tx_word_done <= 1; + tr_state <= TR_IDLE; + end + // receive 32bit + TR_RX_START: begin + tr_cnt <= tr_cnt + 1'b1; + case(tr_cnt) + (BITLEN/2-4): begin + rx_word_shift <= {rx_word_shift[30:0], pad_1wire_s}; + end + (BITLEN*5/6): begin + tr_cnt <= 0; + // wait for next falling edge + tr_state <= TR_RX_WAITEDGE; + tr_bit <= tr_bit + 1'b1; + if(tr_bit == 31) begin + // if this is bit32, don't wait and finish + tr_state <= TR_RX_DONE; + end + end + endcase + end + TR_RX_WAITEDGE: begin + if(pad_1wire_f) begin + tr_state <= TR_RX_START; + end + end + TR_RX_DONE: begin + rx_word <= rx_word_shift; + rx_word_done <= 1; + tr_state <= TR_IDLE; + end + default: begin + tr_state <= TR_IDLE; + end + endcase + + if(~reset_n_s | ~reset_tr_n) begin + tr_state <= TR_IDLE; + end + end + +endmodule diff --git a/platform/pocket/pkgIndex.tcl b/platform/pocket/pkgIndex.tcl new file mode 100644 index 0000000..c3f738e --- /dev/null +++ b/platform/pocket/pkgIndex.tcl @@ -0,0 +1,68 @@ +# ============================================================================== +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: SOURCE +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +# ============================================================================== +# @file: pkgIndex.tcl +# @brief: Collection of TCL Functions for the Framework +# ============================================================================== + +source $PLATFORM_ROOT/scripts/functions.tcl + +set ignore_list {} +set pkg_proms {} +set pkg_modules [list \ + "audio" \ + "audio/filters" \ + "video" \ + "interface" \ + "interface/keyboard" \ + "megafunctions" \ + "memory" \ + "peripherals" \ + "support" \ + "helpers" +] + +switch $DEVICE_FAMILY { + "Cyclone V" { + puts "Cyclone V" + } + default { + puts "Unknown Device Family" + } +} + +switch $DEVICE_ID { + "pocket" { + puts "This is an Analogue Pocket - $PLATFORM_ROOT" + } + default { + puts "Unknown Device" + } +} + +foreach folder $pkg_modules { + set platform_files [getHDLFiles "$PLATFORM_ROOT/$folder"] + foreach file $platform_files { + if {$file in $ignore_list} { + continue + } else { + set ext [file extension $file] + set is_pll [string match "pll*" $file] + if {$is_pll && $ext eq ".v"} { + continue + } + set is_mf [string match "mf*" $file] + if {$is_mf && $ext eq ".v"} { + continue + } + switch $ext { + ".sv" { set_global_assignment -library "framework" -name SYSTEMVERILOG_FILE \"$file\" } + ".v" { set_global_assignment -library "framework" -name VERILOG_FILE \"$file\" } + ".vhd" { set_global_assignment -library "framework" -name VHDL_FILE \"$file\" } + ".qip" { set_global_assignment -library "framework" -name QIP_FILE \"$file\" } + } + } + } +} diff --git a/platform/pocket/scripts/functions.tcl b/platform/pocket/scripts/functions.tcl new file mode 100644 index 0000000..dc0b1a3 --- /dev/null +++ b/platform/pocket/scripts/functions.tcl @@ -0,0 +1,375 @@ +# ============================================================================== +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: SOURCE +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +# ============================================================================== +# @file: functions.tcl +# @brief: Collection of TCL Functions for the Framework +# ============================================================================== +package require Tcl +package require json +package require fileutil + +puts "Functions Loaded!" + +# @brief: Make an HTTP Request +# Note: HTTP/TLS package is outdated use cURL instead +# Example: +# set http_data "[httpGet https://example.com]" +proc httpGet {url} { + set command "curl -s $url" + set http_data [exec {*}$command] + return $http_data +} + +# @brief: Get a JSON response via HTTP +# Example: +# set json_data "[httpGetJSON https://www.howsmyssl.com/a/check]" +# set tls_version [dict get $json_data tls_version] +proc httpGetJSON {url} { + set http_data "[httpGet $url]" + set json_data [json::json2dict $http_data] + return $json_data +} + +# @brief: Get a JSON response via HTTP +# Example: +# set tag_name "[gitLatestReleaseTag "opengateware" "arcade-congo"]" +proc gitLatestReleaseTag {owner repo} { + set json_data "[httpGetJSON https://api.github.com/repos/$owner/$repo/releases/latest]" + set tag_name [dict get $json_data tag_name] + return $tag_name +} + +# @brief: Get HDL Files (SV, V, VHD and QIP) +proc getHDLFiles {folder} { + set file_list [glob -nocomplain -types f [file join $folder *.{sv,v,vhd,qip}]] + if {[llength $file_list] == 0} { + puts "No files found with the specified extensions in directory: $PLATFORM_ROOT" + } else { + set result {} + foreach file $file_list { + lappend result $file + } + return $result + } +} + +# @brief: Get the current date in the format YYYYMMDD +# (see: https://www.intel.com/content/www/us/en/support/programmable/support-resources/design-examples/quartus/tcl-date-time-stamp.html) +proc getDate {} { + set buildDate [ clock format [ clock seconds ] -format %Y%m%d ] + return $buildDate +} + +# @brief: Get the current date in the format YYYY-MM-DD +proc getDateDashed {} { + set buildDate [ clock format [ clock seconds ] -format %Y-%m-%d ] + return $buildDate +} + +# @brief: Get the current time in the format HHMMSS +proc getTime {} { + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + return $buildTime +} + +# @brief: Get the git hashtag for this project +proc getDigest {} { + set buildHash "" + if {[catch {exec git rev-parse --short=8 HEAD}]} { + puts "No git version control in the project" + set buildHash FEEDC0DE + } else { + set buildHash [exec git rev-parse --short=8 HEAD] + } + return $buildHash +} + +# @brief: Get the git hashtag for this project +proc getLastTag {} { + set buildTag "" + if {[catch {exec git describe --abbrev=0 --tags}]} { + puts "No git tag in the project" + set buildTag "0.0.0" + } else { + set buildTag [exec git describe --abbrev=0 --tags] + } + return $buildTag +} + +# @brief: Creates a folder if it doesn't already exist +proc createFolder {folder_path} { + if {![file isdirectory $folder_path]} { + file mkdir $folder_path + } +} + +# @brief: Search and Replace a string +# Example: +# set my_string "hello world" +# set new_string [searchReplace $my_string "world" "TCL"] +proc searchReplace {string pattern replacement} { + set result [::tcl::string::map [list $pattern $replacement] $string] + return $result +} + +# @brief: Copies the input file to the output file +proc copyFile {input_path output_path} { + file copy -force $input_file $output_file +} + +# @brief: Generate a Build ID +# Create a build_id.vh file containing build date and git commit digest +proc generateBuildID {} { + # Set the metadata for this project + set buildDate [getDate] + set buildHash [getDigest] + + # Create a Verilog Header file for output + set outputFileName "../target/pocket/build_id.vh" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "// Build ID Verilog Module" + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_HASH \"$buildHash\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Build ID Verilog Header File generated: [pwd]/$outputFileName" +} + +# @brief: Generate a JTAG Chain Description File. +# Create a .cdf file to be used with Quartus Prime Programmer +proc generateCDF {revision outpath device use_hps} { + set outputFileName "$revision.cdf" + set outputFile [open $outputFileName "w"] + + puts $outputFile "JedecChain;" + puts $outputFile " FileRevision(JESD32A);" + puts $outputFile " DefaultMfr(6E);" + puts $outputFile "" + if {$use_hps} { + puts $outputFile " P ActionCode(Ign)" + puts $outputFile " Device PartName(SOCVHPS) MfrSpec(OpMask(0));" + } + puts $outputFile " P ActionCode(Cfg)" + puts $outputFile " Device PartName($device) Path(\"$outpath/\") File(\"$revision.sof\") MfrSpec(OpMask(1));" + puts $outputFile "ChainEnd;" + puts $outputFile "" + puts $outputFile "AlteraBegin;" + puts $outputFile " ChainType(JTAG);" + puts $outputFile "AlteraEnd;" + close $outputFile + + # Send confirmation message to the Messages window + post_message "JTAG Chain Description File generated: [pwd]/$outputFileName" +} + +# @brief: Generate a Build ID +# Create a build_id.mif file containing build date, time and unique id +proc generateBuildID_MIF {} { + set buildDate [getDate] + set buildTime [getTime] + set buildUnique [expr {int(rand()*(4294967295))}] + + set buildDateNoLeadingZeros [string trimleft $buildDate "0"] + set buildTimeNoLeadingZeros [string trimleft $buildTime "0"] + set buildDate4Byte [format "%08d" $buildDateNoLeadingZeros] + set buildTime4Byte [format "%08d" $buildTimeNoLeadingZeros] + set buildUnique4Byte [format "%08x" $buildUnique] + + # Create a Memory Initialization File for output + set outputFileName "../target/pocket/build_id.mif" + set outputFile [open $outputFileName "w"] + + # Output the MIF file + puts $outputFile "-- begin_signature" + puts $outputFile "-- Build_ID" + puts $outputFile "-- end_signature" + puts $outputFile "DEPTH=256;" + puts $outputFile "WIDTH=32;" + puts $outputFile "" + puts $outputFile "ADDRESS_RADIX=HEX;" + puts $outputFile "DATA_RADIX=HEX;" + puts $outputFile "" + puts $outputFile "CONTENT" + puts $outputFile "BEGIN" + puts $outputFile "\t0E0 :\t$buildDate4Byte;" + puts $outputFile "\t0E1 :\t$buildTime4Byte;" + puts $outputFile "\t0E2 :\t$buildUnique4Byte;" + puts $outputFile "END;" + + # Close file to complete write + close $outputFile + + # Send confirmation message to the Messages window + post_message "Build ID Memory Initialization File generated: [pwd]/$outputFileName" +} + +# @brief: Generate build_id.vh if doesn't exists (avoid having to start compilation to execute pre-flow) +proc checkBuildID {} { + # set outputVerilog "../target/pocket/build_id.vh" + # if {![file exists $outputVerilog]} { generateBuildID } + set outputMIF "../target/pocket/build_id.mif" + if {![file exists $outputMIF]} { generateBuildID_MIF } +} + +# @brief: Open binary file and load into a Hex value string +proc readBinaryFile {file_path} { + set file [open $file_path rb] + set content [read $file] + close $file + + set bytes [list] + foreach byte [split $content ""] { + lappend bytes [format "%02X" [scan $byte %c]] + } + + return $bytes +} + +# @brief: Reverse bytes required for the Analogue Pocket +proc reverseBits {bytes} { + set reversed_values [list] + foreach byte $bytes { + set decimal_value [scan $byte %x] + set reversed_decimal_value 0 + for {set i 0} {$i < 8} {incr i} { + set bit [expr {($decimal_value >> $i) & 1}] + set reversed_decimal_value [expr {($reversed_decimal_value << 1) | $bit}] + } + lappend reversed_values [format "%02X" $reversed_decimal_value] + } + return $reversed_values +} + +# @brief: Convert hex values to binary and save into a file +proc saveBinaryFile {bytes output_file} { + set file [open $output_file wb] + foreach byte $bytes { + set byte [binary format c [scan $byte %x]] + puts -nonewline $file $byte + } + close $file + post_message "Reversed Bitstream File generated: [pwd]/$output_file." +} + +# @brief: Create a reversed RBF required for the Analogue Pocket +proc reverseRBF {revision outpath} { + global BUILD_ROOT + global DEVICE_ID + createFolder $BUILD_ROOT + set bytes [readBinaryFile "$outpath/$revision.rbf"] + set bytes_r [reverseBits $bytes] + set rbf_name [searchReplace $revision "_$DEVICE_ID" ""] + set target_dir [getCoreFolderName] + if {[string equal "" $target_dir]} { + saveBinaryFile $bytes_r "$BUILD_ROOT/$rbf_name.rbf_r" + } else { + saveBinaryFile $bytes_r "$BUILD_ROOT/Cores/$target_dir/$rbf_name.rbf_r" + } +} + +# @brief: Check if file contains a file extension that should be ignored +proc isExtIgnored {file_path} { + set ignore_extensions {.gitkeep .png .rom} + set file_extension [string tolower [file extension $file_path]] + if {[lsearch -exact $ignore_extensions $file_extension] != -1} { + return 1;# File is ignored + } else { + return 0;# File is not ignored + } +} + +# @brief: Create a reversed RBF required for the Analogue Pocket +proc getRelativePath {base_path path} { + set base_parts [split $base_path "/"] + set path_parts [split $path "/"] + + while {[llength $base_parts] > 0 && [llength $path_parts] > 0 && [lindex $base_parts 0] eq [lindex $path_parts 0]} { + set base_parts [lrange $base_parts 1 end] + set path_parts [lrange $path_parts 1 end] + } + + set relative_path [concat [lrepeat [llength $base_parts] ".."] $path_parts] + return [join $relative_path "/"] +} + +# @brief: Copy the entire directory structure and files from the source +# to the target directory recursively, creating any necessary folders +# along the way +proc copyDirectory {source_dir target_dir} { + if {![file isdirectory $target_dir]} { + file mkdir $target_dir + } + + set files [glob -nocomplain -directory $source_dir -type f *] + foreach file $files { + set relative_path [getRelativePath $source_dir $file] + set target_path [file join $target_dir $relative_path] + set target_dir_path [file dirname $target_path] + + if {![file isdirectory $target_dir_path]} { + file mkdir $target_dir_path + } + + if {[isExtIgnored $file]} { + puts "File ignored: $file" + continue + } else { + file copy -force $file $target_path + } + } + + set subdirs [glob -nocomplain -directory $source_dir -type d *] + foreach subdir $subdirs { + set relative_path [getRelativePath $source_dir $subdir] + set target_path [file join $target_dir $relative_path] + + copyDirectory $subdir $target_path + } +} + +# @brief: Get the folder from BUILD_ROOT/Cores +proc getCoreFolderName {} { + global BUILD_ROOT + set cores_path "$BUILD_ROOT/Cores" + set cores_folders [glob -nocomplain -directory $cores_path -type d *] + set num_cores [llength $cores_folders] + + if {$num_cores == 1} { + set folder_name [file tail [lindex $cores_folders 0]] + return $folder_name + } elseif {$num_cores == 0} { + post_message "No folder found inside $cores_path" + return "" + } else { + post_message "Multiple folders found inside $cores_path" + return "" + } +} + +# @brief: Update the core.json file with Version and Release Date +# Example: +# updateVersionReleaseDate "1.0.0" +proc updateVersionReleaseDate {version} { + set file_path "core.json" + set release_date [getDateDashed] + + if {[file exists $file_path]} { + set file_handle [open $file_path "r+"] + set file_content [read $file_handle] + + set updated_content [string map [list "<%- VERSION %>" $version "<%- RELEASE_DATE %>" $release_date] $file_content] + + seek $file_handle 0 + puts -nonewline $file_handle $updated_content + close $file_handle + + puts "Updated $file_path with version: $version and release date: $release_date." + } else { + puts "File $file_path does not exist." + } +} diff --git a/platform/pocket/scripts/post_flow.tcl b/platform/pocket/scripts/post_flow.tcl new file mode 100644 index 0000000..7ca49ce --- /dev/null +++ b/platform/pocket/scripts/post_flow.tcl @@ -0,0 +1,36 @@ +# ============================================================================== +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: SOURCE +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +# ============================================================================== +# @file: post-flow.tcl +# @brief: POST_FLOW_SCRIPT_FILE - Runs after a flow finishes +# ============================================================================== + +source ../platform/pocket/scripts/functions.tcl + +set project_name [lindex $quartus(args) 1] +set revision [lindex $quartus(args) 2] + +if {[project_exists $project_name]} { + if {[string equal "" $revision]} { + project_open $project_name -revision [get_current_revision $project_name] + } else { + project_open $project_name -revision $revision + } +} else { + post_message -type error "Project $project_name does not exist" + exit +} + +set device [get_global_assignment -name DEVICE] +set outpath [get_global_assignment -name PROJECT_OUTPUT_DIRECTORY] +set device_hps [get_parameter -name NSX_DEVICE_USE_HPS] +set use_hps [expr {$device_hps eq "ON" ? 1 : 0}] + +if [is_project_open] { + project_close +} + +generateCDF $revision $outpath $device $use_hps +# reverseRBF $revision $outpath \ No newline at end of file diff --git a/platform/pocket/scripts/pre_flow.tcl b/platform/pocket/scripts/pre_flow.tcl new file mode 100644 index 0000000..a4e157a --- /dev/null +++ b/platform/pocket/scripts/pre_flow.tcl @@ -0,0 +1,12 @@ +# ============================================================================== +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileType: SOURCE +# SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors +# ============================================================================== +# @file: pre-flow.tcl +# @brief: PRE_FLOW_SCRIPT_FILE - Runs before a flow starts +# ============================================================================== + +source ../platform/pocket/scripts/functions.tcl + +generateBuildID_MIF diff --git a/platform/pocket/support/autofire.sv b/platform/pocket/support/autofire.sv new file mode 100644 index 0000000..1df90de --- /dev/null +++ b/platform/pocket/support/autofire.sv @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Autofire/Turbo Button Controller +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// This module provides an "autofire" or "turbo" feature typically found in +// gaming controllers. When enabled, it automatically toggles the state of +// a button output at a user-defined rate, simulating rapid button presses +// without the need for manual input. +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module autofire + #( + parameter CLK = 12_000_000 //! System clock frequency in Hz. Default value is 12MHz. + ) ( + // Clock and Reset + input logic clk, //! System Clock + // Control + input logic enable, //! Control input to enable or disable the autofire feature + input logic [5:0] rate, //! User-defined rate input (0-63) indicating how many times the autofire should toggle per second + // Button In/Out + input logic btn_in, //! Input representing the original state of the button + output logic btn_out //! Output representing the toggled state when autofire is enabled or the original state when disabled + ); + + integer threshold = CLK / (2 * rate); + integer counter = 0; + logic btn_state = 0; + + always_ff @(posedge clk) begin : handleButton + if (enable) begin + if (counter >= threshold) begin + btn_state <= ~btn_state; // Toggle the state when we reach the threshold. + counter <= 0; // Reset the counter. + end + else begin + counter <= counter + 1; // Increment the counter. + end + end + else begin + counter <= 0; + btn_state <= btn_in; // Directly pass the button state if not in autofire mode. + end + end + + assign btn_out = btn_state; + +endmodule diff --git a/platform/pocket/support/data_io.sv b/platform/pocket/support/data_io.sv new file mode 100644 index 0000000..169465a --- /dev/null +++ b/platform/pocket/support/data_io.sv @@ -0,0 +1,102 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Generic Data I/O for APF bridge +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module data_io + #( + parameter MASK = 0, //! Upper 4 bits of address + parameter AW = 27, //! Address Width + parameter DW = 8, //! Data Width (8 or 16 bits) + parameter DELAY = 4, //! Number of clock cycles to delay each write output + parameter HOLD = 1 //! Number of clock cycles to hold the ioctl_wr signal high + ) ( + input logic clk_74a, + input logic clk_memory, + // Pocket Bridge Slots + input logic dataslot_requestwrite, + input logic dataslot_allcomplete, + input logic [15:0] dataslot_requestwrite_id, + // Pocket Bridge + input logic bridge_endian_little, + input logic [31:0] bridge_addr, + input logic bridge_wr, + input logic [31:0] bridge_wr_data, + // MPU <-> FPGA + output wire ioctl_download = 0, // signal indicating an active download + output wire [15:0] ioctl_index, // slot index used to upload the file + output logic ioctl_wr, + output logic [AW-1:0] ioctl_addr, + output logic [DW-1:0] ioctl_data + ); + + //!------------------------------------------------------------------------- + //! Download Signal Handler + //!------------------------------------------------------------------------- + reg ioctl_download_r = 0; + + always_ff @(posedge clk_74a) begin + if (dataslot_requestwrite) begin ioctl_download_r <= 1; end + else if(dataslot_allcomplete) begin ioctl_download_r <= 0; end + end + + //!------------------------------------------------------------------------- + //! Sync and Assign Outputs + //!------------------------------------------------------------------------- + synch_3 sync_io_dl(ioctl_download_r, ioctl_download, clk_memory); + synch_3 #(.WIDTH(16)) sync_wr_id(dataslot_requestwrite_id, ioctl_index, clk_memory); + + //!------------------------------------------------------------------------- + //! MPU -> FPGA Download + //!------------------------------------------------------------------------- + localparam WORD_SIZE = DW == 16 ? 2 : 1; + + data_loader #( + .ADDRESS_MASK_UPPER_4 ( MASK ), + .WRITE_MEM_CLOCK_DELAY ( DELAY ), + .WRITE_MEM_EN_CYCLE_LENGTH ( HOLD ), + .ADDRESS_SIZE ( AW ), + .OUTPUT_WORD_SIZE ( WORD_SIZE ) + ) data_loader_in ( + .clk_74a ( clk_74a ), + .clk_memory ( clk_memory ), + + .bridge_wr ( bridge_wr ), + .bridge_endian_little ( bridge_endian_little ), + .bridge_addr ( bridge_addr ), + .bridge_wr_data ( bridge_wr_data ), + + .write_en ( ioctl_wr ), + .write_addr ( ioctl_addr ), + .write_data ( ioctl_data ) + ); + +endmodule diff --git a/platform/pocket/support/hiscore.sv b/platform/pocket/support/hiscore.sv new file mode 100644 index 0000000..8fb6190 --- /dev/null +++ b/platform/pocket/support/hiscore.sv @@ -0,0 +1,740 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// MAME hiscore.dat support for arcade cores. +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2021, Alan Steremberg +// Copyright (c) 2021, Jim Gregory +// +// 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//------------------------------------------------------------------------------ +// +// Version history: +// 0001 - 2021-03-06 - First marked release +// 0002 - 2021-03-06 - Added HS_DUMPFORMAT localparam to identify dump version (for future use) +// Add HS_CONFIGINDEX and HS_DUMPINDEX parameters to configure ioctl_indexes +// 0003 - 2021-03-10 - Added WRITE_REPEATCOUNT and WRITE_REPEATWAIT to handle tricky write situations +// 0004 - 2021-03-15 - Fix ram_access assignment +// 0005 - 2021-03-18 - Add configurable score table width, clean up some stupid mistakes +// 0006 - 2021-03-27 - Move 'tweakable' parameters into MRA data header +// 0007 - 2021-04-15 - Improve state machine maintainability, add new 'pause padding' states +// 0008 - 2021-05-12 - Feed back core-level pause to halt startup timer +// 0009 - 2021-07-31 - Split hiscore extraction from upload (updates hiscore buffer on OSD open) +// 0010 - 2021-08-03 - Add hiscore buffer and change detection (ready for autosave!) +// 0011 - 2021-08-07 - Optional auto-save on OSD open +// 0012 - 2021-08-17 - Add variable length change detection mask +// 0013 - 2021-09-01 - Output configured signal for autosave option menu masking +// 0014 - 2021-09-09 - Fix turning on autosave w/o core reload +// 0015 - 2023-06-21 - Changes for the Analogue Pocket +// +//------------------------------------------------------------------------------ +// altera message_off 10230 + +`default_nettype none +`timescale 1ns/1ps + +module hiscore + #( + parameter HS_ADDRESSWIDTH = 10, // Max size of game RAM address for highscores + parameter HS_SCOREWIDTH = 8, // Max size of capture RAM For highscore data (default 8 = 256 bytes max) + parameter HS_CONFIGINDEX = 3, // ioctl_index for config transfer + parameter HS_DUMPINDEX = 4, // ioctl_index for dump transfer + parameter CFG_ADDRESSWIDTH = 4, // Max size of RAM address for highscore.dat entries (default 4 = 16 entries max) + parameter CFG_LENGTHWIDTH = 1, // Max size of length for each highscore.dat entries (default 1 = 256 bytes max) + parameter TARGET_PLATFORM = 1 // Platform: [1] Analogue Pocket | [2] MiMiC + ) ( + input wire clk, + input wire reset, + + input wire paused, // Signal from core confirming CPU is paused + input wire autosave, // Auto-save enabled (active high) + + input wire ioctl_upload, + output reg ioctl_upload_req, + input wire ioctl_download, + input wire ioctl_wr, + input wire [24:0] ioctl_addr, + input wire [7:0] ioctl_index, + + input wire menu_status, + + input wire [7:0] data_from_mpu, // Incoming data from HPS ioctl_dout + input wire [7:0] data_from_ram, // Incoming data from game RAM + output wire [HS_ADDRESSWIDTH-1:0] ram_address, // Address in game RAM to read/write score data + output wire [7:0] data_to_mpu, // Data to send to HPS ioctl_din + output wire [7:0] data_to_ram, // Data to send to game RAM + output reg ram_write, // Write to game RAM (active high) + output wire ram_intent_read, // RAM read required (active high) + output wire ram_intent_write, // RAM write required (active high) + output reg pause_cpu, // Pause core CPU to prepare for/relax after RAM access + output wire configured // Hiscore module has valid configuration (active high) + ); + + // Parameters read from config header + reg [31:0] START_WAIT = 32'd0; // Delay before beginning check process + reg [15:0] CHECK_WAIT = 16'hFF; // Delay between start/end check attempts + reg [15:0] CHECK_HOLD = 16'd2; // Hold time for start/end check reads + reg [15:0] WRITE_HOLD = 16'd2; // Hold time for game RAM writes + reg [15:0] WRITE_REPEATCOUNT = 16'b1; // Number of times to write score to game RAM + reg [15:0] WRITE_REPEATWAIT = 16'b1111; // Delay between subsequent write attempts to game RAM + reg [7:0] ACCESS_PAUSEPAD = 8'd4; // Cycles to wait with paused CPU before and after RAM access + reg [7:0] CHANGEMASK = 1'b0; // Length of change mask + + // State machine constants + localparam SM_STATEWIDTH = 5; // Width of state machine net + + localparam SM_INIT_RESTORE = 0; + localparam SM_TIMER = 1; + + localparam SM_CHECKPREP = 2; + localparam SM_CHECKBEGIN = 3; + localparam SM_CHECKSTARTVAL = 4; + localparam SM_CHECKENDVAL = 5; + localparam SM_CHECKCANCEL = 6; + + localparam SM_WRITEPREP = 7; + localparam SM_WRITEBEGIN = 8; + localparam SM_WRITEREADY = 9; + localparam SM_WRITEDONE = 10; + localparam SM_WRITECOMPLETE = 11; + localparam SM_WRITERETRY = 12; + + localparam SM_COMPAREINIT = 16; + localparam SM_COMPAREBEGIN = 17; + localparam SM_COMPAREREADY = 18; + localparam SM_COMPAREREAD = 19; + localparam SM_COMPAREDONE = 20; + localparam SM_COMPARECOMPLETE = 21; + + localparam SM_EXTRACTINIT = 22; + localparam SM_EXTRACT = 23; + localparam SM_EXTRACTSAVE = 24; + localparam SM_EXTRACTCOMPLETE = 25; + + localparam SM_STOPPED = 30; + + /* + Hiscore config data structure (version 1) + ----------------------------------------- + [16 byte header] + [8 byte * no. of entries] + + - Header format + 00 00 FF FF 00 FF 00 02 00 02 00 01 11 11 00 00 + [ SW ] [ CW] [ CH] [ WH] [WRC] [WRW] [PAD] + 4 byte START_WAIT + 2 byte CHECK_WAIT + 2 byte CHECK_HOLD + 2 byte WRITE_HOLD + 2 byte WRITE_REPEATCOUNT + 2 byte WRITE_REPEATWAIT + 1 byte ACCESS_PAUSEPAD + 1 byte CHANGEMASK + + - Entry format (when CFG_LENGTHWIDTH=1) + 00 00 43 0b 0f 10 01 00 + 00 00 40 23 02 04 12 00 + [ ADDR ] LEN START END PAD + + 4 bytes Address of ram entry (in core memory map) + 1 byte Length of ram entry in bytes + 1 byte Start value to check for at start of address range before proceeding + 1 byte End value to check for at end of address range before proceeding + 1 byte (padding) + + - Entry format (when CFG_LENGTHWIDTH=2) + 00 00 43 0b 00 0f 10 01 + 00 00 40 23 00 02 04 12 + [ ADDR ] [LEN ] START END + + 4 bytes Address of ram entry (in core memory map) + 2 bytes Length of ram entry in bytes + 1 byte Start value to check for at start of address range before proceeding + 1 byte End value to check for at end of address range before proceeding + + */ + + localparam HS_VERSION = 14; // Version identifier for module + localparam HS_DUMPFORMAT = 1; // Version identifier for dump format + localparam HS_HEADERLENGTH = 16; // Size of header chunk (default=16 bytes) + + // HS_DUMPFORMAT = 1 --> No header, just the extracted hiscore data + + // Hiscore config tracking + wire downloading_config; // Is hiscore configuration currently being loaded from HPS? + reg downloaded_config = 1'b0; // Has hiscore configuration been loaded successfully + wire parsing_header; // Is hiscore configuration header currently being parsed? + wire parsing_mask; // Is hiscore configuration change mask currently being parsed? (optional 2nd line of config) + + // Hiscore data tracking + wire downloading_dump; // Is hiscore data currently being loaded from HPS? + reg downloaded_dump = 1'b0; // Has hiscore data been loaded successfully + wire uploading_dump; // Is hiscore data currently being sent to HPS? + reg extracting_dump = 1'b0; // Is hiscore data currently being extracted from game RAM? + reg restoring_dump = 1'b0; // Is hiscore data currently being (or waiting to) restore to game RAM + + reg checking_scores = 1'b0; // Is state machine currently checking game RAM for highscore restore readiness + reg reading_scores = 1'b0; // Is state machine currently reading game RAM for highscore dump + reg writing_scores = 1'b0; // Is state machine currently restoring hiscore data to game RAM + + reg [3:0] initialised; // Number of times state machine has been initialised (debug only) + + assign configured = downloaded_config; + assign downloading_config = ioctl_download && (ioctl_index == HS_CONFIGINDEX); + assign parsing_header = downloading_config && (ioctl_addr < HS_HEADERLENGTH); + assign parsing_mask = downloading_config && !parsing_header && (CHANGEMASK > 8'b0) && (ioctl_addr < HS_HEADERLENGTH + CHANGEMASK); + assign downloading_dump = ioctl_download && (ioctl_index == HS_DUMPINDEX); + assign uploading_dump = ioctl_upload && (ioctl_index == HS_DUMPINDEX); + assign ram_intent_read = reading_scores | checking_scores; + assign ram_intent_write = writing_scores; + assign ram_address = ram_addr[HS_ADDRESSWIDTH-1:0]; + + reg [(SM_STATEWIDTH-1):0] state = SM_INIT_RESTORE; // Current state machine index + reg [(SM_STATEWIDTH-1):0] next_state = SM_INIT_RESTORE; // Next state machine index to move to after wait timer expires + reg [31:0] wait_timer; // Wait timer for inital/read/write delays + + reg [CFG_ADDRESSWIDTH-1:0] counter = 1'b0; // Index for current config table entry + reg [CFG_ADDRESSWIDTH-1:0] total_entries = 1'b0; // Total count of config table entries + reg reset_last = 1'b0; // Last cycle reset + reg [7:0] write_counter = 1'b0; // Index of current game RAM write attempt + + reg [255:0] change_mask; // Bit mask for dump change check + + reg [7:0] last_ioctl_index; // Last cycle HPS IO index + reg last_ioctl_download = 0; // Last cycle HPS IO download + reg [7:0] last_data_from_mpu; // Last cycle HPS IO data out + reg [7:0] last_data_from_mpu2; // Last cycle +1 HPS IO data out + reg [7:0] last_data_from_mpu3; // Last cycle +2 HPS IO data out + reg last_menu_status; // Last cycle OSD status + + reg [24:0] ram_addr; // Target RAM address for hiscore read/write + reg [24:0] base_io_addr; + wire [23:0] addr_base /* synthesis keep */; + wire [(CFG_LENGTHWIDTH*8)-1:0] length; + wire [24:0] end_addr = (addr_base + length - 1'b1); + reg [HS_SCOREWIDTH-1:0] data_addr; + reg [HS_SCOREWIDTH-1:0] buffer_addr; + wire [7:0] start_val /* synthesis keep */; + wire [7:0] end_val /* synthesis keep */; + + wire check_mask = change_mask[compare_length]/* synthesis keep */; + wire [7:0] hiscore_data_out /* synthesis keep */; + wire [7:0] hiscore_buffer_out /* synthesis keep */; + reg [19:0] compare_length = 1'b0; + reg dump_write = 1'b0; + reg buffer_write = 1'b0; + reg compare_nonzero = 1'b1; // High after extract and compare if any byte returned is non-zero + reg compare_changed = 1'b1; // High after extract and compare if any byte is different to current hiscore data + reg dump_dirty = 1'b0; // High if dump has changed since last save (or first load if no save has occurred) + + wire [23:0] address_data_in; + wire [(CFG_LENGTHWIDTH*8)-1:0] length_data_in; + + assign address_data_in = {last_data_from_mpu2, last_data_from_mpu, data_from_mpu}; + assign length_data_in = (CFG_LENGTHWIDTH == 1'b1) ? data_from_mpu : {last_data_from_mpu, data_from_mpu}; + + wire parsing_config = ~(parsing_header | parsing_mask); // Hiscore config lines are being parsed + + wire [CFG_ADDRESSWIDTH-1:0] config_upload_addr = ioctl_addr[CFG_ADDRESSWIDTH+2:3] - (9'd2 + CHANGEMASK[7:3]) /* synthesis keep */; + + wire address_we = downloading_config & parsing_config & (ioctl_addr[2:0] == 3'd3); + wire length_we = downloading_config & parsing_config & (ioctl_addr[2:0] == 3'd3 + CFG_LENGTHWIDTH); + wire startdata_we = downloading_config & parsing_config & (ioctl_addr[2:0] == 3'd4 + CFG_LENGTHWIDTH); + wire enddata_we = downloading_config & parsing_config & (ioctl_addr[2:0] == 3'd5 + CFG_LENGTHWIDTH); + + // RAM chunks used to store configuration data + // - Address table + dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(24)) address_table + ( + .clk ( clk ), + .addr_a ( config_upload_addr ), + .we_a ( address_we & ioctl_wr ), + .d_a ( address_data_in ), + .addr_b ( counter ), + .q_b ( addr_base ) + ); + // Length table - variable width depending on CFG_LENGTHWIDTH + dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(CFG_LENGTHWIDTH*8)) length_table + ( + .clk ( clk ), + .addr_a ( config_upload_addr ), + .we_a ( length_we & ioctl_wr ), + .d_a ( length_data_in ), + .addr_b ( counter ), + .q_b ( length ) + ); + // - Start data table + dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(8)) startdata_table + ( + .clk ( clk ), + .addr_a ( config_upload_addr ), + .we_a ( startdata_we & ioctl_wr ), + .d_a ( data_from_mpu ), + .addr_b ( counter ), + .q_b ( start_val ) + ); + // - End data table + dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(8)) enddata_table + ( + .clk ( clk ), + .addr_a ( config_upload_addr ), + .we_a ( enddata_we & ioctl_wr ), + .d_a ( data_from_mpu ), + .addr_b ( counter ), + .q_b ( end_val ) + ); + + // RAM chunk used to store valid hiscore data + dpram_hs #(.aWidth(HS_SCOREWIDTH),.dWidth(8)) hiscore_data + ( + .clk ( clk ), + .addr_a ( ioctl_addr[(HS_SCOREWIDTH-1):0] ), + .we_a ( downloading_dump ), + .d_a ( data_from_mpu ), + .addr_b ( data_addr ), + .we_b ( dump_write ), + .d_b ( hiscore_buffer_out ), + .q_b ( hiscore_data_out ) + ); + // RAM chunk used to store temporary high score data + dpram_hs #(.aWidth(HS_SCOREWIDTH),.dWidth(8)) hiscore_buffer + ( + .clk ( clk ), + .addr_a ( buffer_addr ), + .we_a ( buffer_write ), + .d_a ( data_from_ram ), + .q_a ( hiscore_buffer_out ) + ); + + assign data_to_ram = hiscore_data_out; + assign data_to_mpu = hiscore_data_out; + + wire [3:0] header_chunk = ioctl_addr[3:0]; + wire [7:0] mask_chunk = ioctl_addr[7:0] - 5'd16; + wire [255:0] mask_load_index = mask_chunk * 8; + + always @(posedge clk) begin + + if (downloading_config) begin + // Get header chunk data + if(parsing_header) begin + if(ioctl_wr) begin + if(header_chunk == 4'd3) START_WAIT <= { last_data_from_mpu3, last_data_from_mpu2, last_data_from_mpu, data_from_mpu }; + if(header_chunk == 4'd5) CHECK_WAIT <= { last_data_from_mpu, data_from_mpu }; + if(header_chunk == 4'd7) CHECK_HOLD <= { last_data_from_mpu, data_from_mpu }; + if(header_chunk == 4'd9) WRITE_HOLD <= { last_data_from_mpu, data_from_mpu }; + if(header_chunk == 4'd11) WRITE_REPEATCOUNT <= { last_data_from_mpu, data_from_mpu }; + if(header_chunk == 4'd13) WRITE_REPEATWAIT <= { last_data_from_mpu, data_from_mpu }; + if(header_chunk == 4'd14) ACCESS_PAUSEPAD <= data_from_mpu; + if(header_chunk == 4'd15) CHANGEMASK <= data_from_mpu; + end + end + else + if(parsing_mask) begin + if(ioctl_wr == 1'b1) + change_mask[mask_load_index +: 8] <= data_from_mpu; + end + else begin + // Keep track of the largest entry during config download + total_entries <= config_upload_addr; + end + end + + // Track completion of configuration and dump download + if(TARGET_PLATFORM == 1) begin + if (~ioctl_download && last_ioctl_download) begin + downloaded_config <= 1'b1; + downloaded_dump <= 1'b1; + end + end + else begin + if ((last_ioctl_download != ioctl_download) && (ioctl_download == 1'b0)) begin + if (last_ioctl_index == HS_CONFIGINDEX) downloaded_config <= 1'b1; + if (last_ioctl_index == HS_DUMPINDEX) downloaded_dump <= 1'b1; + end + end + + // Track last cycle values + last_ioctl_download <= ioctl_download; + last_ioctl_index <= ioctl_index; + last_menu_status <= menu_status; + + // Cascade incoming data bytes from HPS + if(ioctl_download && ioctl_wr) begin + last_data_from_mpu3 <= last_data_from_mpu2; + last_data_from_mpu2 <= last_data_from_mpu; + last_data_from_mpu <= data_from_mpu; + end + + // If we have a valid configuration then enable the hiscore system + if(downloaded_config) begin + + // Check for end of core reset to initialise state machine for restore + reset_last <= reset; + if (downloaded_dump == 1'b1 && reset_last == 1'b1 && reset == 1'b0) begin + wait_timer <= START_WAIT; + next_state <= SM_INIT_RESTORE; + state <= SM_TIMER; + counter <= 1'b0; + initialised <= initialised + 1'b1; + restoring_dump <= 1'b1; + end + else begin + // Upload scores if requested by HPS + // - Data is now sent from the hiscore data buffer rather than game RAM as in previous versions + if (uploading_dump == 1'b1) begin + // Set local address to read from hiscore data based on ioctl_address + data_addr <= ioctl_addr[HS_SCOREWIDTH-1:0]; + // Clear dump dirty flag + dump_dirty <= 1'b0; + end + + // Trigger hiscore extraction when OSD is opened + if(last_menu_status==1'b0 && menu_status==1'b1 && extracting_dump==1'b0 && uploading_dump==1'b0 && restoring_dump==1'b0) begin + extracting_dump <= 1'b1; + state <= SM_COMPAREINIT; + end + + // Extract hiscore data from game RAM and save in hiscore data buffer + if (extracting_dump == 1'b1) begin + case (state) + // Compare process states + SM_COMPAREINIT: // Initialise state machine for comparison + begin + // Setup addresses and comparison flags + buffer_addr <= 0; + data_addr <= 0; + counter <= 0; + compare_nonzero <= 1'b0; + compare_changed <= 1'b0; + compare_length <= 1'b0; + // Pause cpu and wait for next state + pause_cpu <= 1'b1; + state <= SM_TIMER; + next_state <= SM_COMPAREBEGIN; + wait_timer <= ACCESS_PAUSEPAD; + end + SM_COMPAREBEGIN: begin + // Get ready to read next line (wait until addr_base is updated) + reading_scores <= 1'b1; + state <= SM_COMPAREREADY; + end + SM_COMPAREREADY: begin + // Set ram address and wait for it to return correctly + ram_addr <= addr_base; + if(ram_addr == addr_base) begin + state <= SM_COMPAREREAD; + end + end + SM_COMPAREREAD: begin + // Setup next address and signal write enable to hiscore buffer + buffer_write <= 1'b1; + state <= SM_COMPAREDONE; + end + SM_COMPAREDONE: begin + // If RAM data has changed since last dump and there is either no mask or a 1 in the mask for this address + if (data_from_ram != hiscore_data_out && (CHANGEMASK==8'b0 || check_mask==1)) begin + // Hiscore data changed + compare_changed <= 1'b1; + end + if (data_from_ram != 8'b0) begin + // Hiscore data is not blank + compare_nonzero <= 1'b1; + end + compare_length <= compare_length + 20'b1; + // Move to next entry when last address is reached + if (ram_addr == end_addr) begin + // If this was the last entry then we are done + if (counter == total_entries) begin + state <= SM_TIMER; + reading_scores <= 1'b0; + next_state <= SM_COMPARECOMPLETE; + wait_timer <= ACCESS_PAUSEPAD; + end + else begin + // Next config line + counter <= counter + 1'b1; + state <= SM_COMPAREBEGIN; + end + end + else begin + // Keep extracting this section + state <= SM_COMPAREREAD; + ram_addr <= ram_addr + 1'b1; + end + // Always stop writing to hiscore dump ram and increment local address + buffer_addr <= buffer_addr + 1'b1; + data_addr <= data_addr + 1'b1; + buffer_write <= 1'b0; + end + SM_COMPARECOMPLETE: begin + pause_cpu <= 1'b0; + reading_scores <= 1'b0; + if (compare_changed == 1'b1 && compare_nonzero == 1'b1) begin + // If high scores have changed and are not blank, update the hiscore data from extract buffer + dump_dirty <= 1'b1; + state <= SM_EXTRACTINIT; + end + else begin + // If no change or scores are invalid leave the existing hiscore data in place + if(dump_dirty == 1'b1 && autosave == 1'b1) begin + state <= SM_EXTRACTSAVE; + end + else begin + extracting_dump <= 1'b0; + state <= SM_STOPPED; + end + end + end + SM_EXTRACTINIT: begin + // Setup address and counter + data_addr <= 0; + buffer_addr <= 0; + state <= SM_EXTRACT; + dump_write <= 1'b1; + end + SM_EXTRACT: begin + // Keep writing until end of buffer + if (buffer_addr == compare_length) begin + dump_write <= 1'b0; + state <= SM_EXTRACTSAVE; + end + // Increment buffer address and set data address to one behind + data_addr <= buffer_addr; + buffer_addr <= buffer_addr + 1'b1; + end + SM_EXTRACTSAVE: begin + if(autosave == 1'b1) begin + ioctl_upload_req <= 1'b1; + state <= SM_TIMER; + next_state <= SM_EXTRACTCOMPLETE; + wait_timer <= 4'd4; + end + else begin + extracting_dump <= 1'b0; + state <= SM_STOPPED; + end + end + SM_EXTRACTCOMPLETE: begin + ioctl_upload_req <= 1'b0; + extracting_dump <= 1'b0; + state <= SM_STOPPED; + end + endcase + end + + // If we are not uploading or resetting and valid hiscore data is available then start the state machine to write data to game RAM + if (uploading_dump == 1'b0 && downloaded_dump == 1'b1 && reset == 1'b0) begin + // State machine to write data to game RAM + case (state) + SM_INIT_RESTORE: // Start state machine + begin + // Setup base addresses + data_addr <= 0; + base_io_addr <= 25'b0; + // Reset entry counter and states + counter <= 0; + writing_scores <= 1'b0; + checking_scores <= 1'b0; + pause_cpu <= 1'b0; + state <= SM_CHECKPREP; + end + + // Start/end check states + // ---------------------- + SM_CHECKPREP: // Prepare start/end check run - pause CPU in readiness for RAM access + begin + state <= SM_TIMER; + next_state <= SM_CHECKBEGIN; + pause_cpu <= 1'b1; + wait_timer <= ACCESS_PAUSEPAD; + end + + SM_CHECKBEGIN: // Begin start/end check run - enable RAM access + begin + checking_scores <= 1'b1; + ram_addr <= {1'b0, addr_base}; + state <= SM_CHECKSTARTVAL; + wait_timer <= CHECK_HOLD; + end + + SM_CHECKSTARTVAL: // Start check + begin + // Check for matching start value + if(wait_timer != CHECK_HOLD && data_from_ram == start_val) begin + // Prepare end check + ram_addr <= end_addr; + state <= SM_CHECKENDVAL; + wait_timer <= CHECK_HOLD; + end + else begin + ram_addr <= {1'b0, addr_base}; + if (wait_timer > 1'b0) begin + wait_timer <= wait_timer - 1'b1; + end + else begin + // - If no match after read wait then stop check run and schedule restart of state machine + next_state <= SM_CHECKCANCEL; + state <= SM_TIMER; + checking_scores <= 1'b0; + wait_timer <= ACCESS_PAUSEPAD; + end + end + end + + SM_CHECKENDVAL: // End check + begin + // Check for matching end value + if (wait_timer != CHECK_HOLD & data_from_ram == end_val) begin + if (counter == total_entries) begin + // If this was the last entry then move on to writing scores to game ram + checking_scores <= 1'b0; + state <= SM_WRITEBEGIN; // Bypass SM_WRITEPREP as we are already paused + counter <= 1'b0; + write_counter <= 1'b0; + ram_write <= 1'b0; + ram_addr <= {1'b0, addr_base}; + end + else begin + // Increment counter and restart state machine to check next entry + counter <= counter + 1'b1; + state <= SM_CHECKBEGIN; + end + end + else begin + ram_addr <= end_addr; + if (wait_timer > 1'b0) begin + wait_timer <= wait_timer - 1'b1; + end + else begin + // - If no match after read wait then stop check run and schedule restart of state machine + next_state <= SM_CHECKCANCEL; + state <= SM_TIMER; + checking_scores <= 1'b0; + wait_timer <= ACCESS_PAUSEPAD; + end + end + end + + SM_CHECKCANCEL: // Cancel start/end check run - disable RAM access and keep CPU paused + begin + pause_cpu <= 1'b0; + next_state <= SM_INIT_RESTORE; + state <= SM_TIMER; + wait_timer <= CHECK_WAIT; + end + + // Write to game RAM states + // ---------------------- + SM_WRITEPREP: // Prepare to write scores - pause CPU in readiness for RAM access (only used on subsequent write attempts) + begin + state <= SM_TIMER; + next_state <= SM_WRITEBEGIN; + pause_cpu <= 1'b1; + wait_timer <= ACCESS_PAUSEPAD; + end + + SM_WRITEBEGIN: // Writing scores to game RAM begins + begin + writing_scores <= 1'b1; // Enable muxes if necessary + write_counter <= write_counter + 1'b1; + state <= SM_WRITEREADY; + end + + SM_WRITEREADY: // local ram should be correct, start write to game RAM + begin + ram_addr <= addr_base + (data_addr - base_io_addr); + state <= SM_TIMER; + next_state <= SM_WRITEDONE; + wait_timer <= WRITE_HOLD; + ram_write <= 1'b1; + end + + SM_WRITEDONE: begin + data_addr <= data_addr + 1'b1; // Increment to next byte of entry + if (ram_addr == end_addr) begin + // End of entry reached + if (counter == total_entries) begin + state <= SM_WRITECOMPLETE; + end + else begin + // Move to next entry + counter <= counter + 1'b1; + write_counter <= 1'b0; + base_io_addr <= data_addr + 1'b1; + state <= SM_WRITEBEGIN; + end + end + else begin + state <= SM_WRITEREADY; + end + ram_write <= 1'b0; + end + + SM_WRITECOMPLETE: // Hiscore write to RAM completed + begin + ram_write <= 1'b0; + writing_scores <= 1'b0; + restoring_dump <= 1'b0; + state <= SM_TIMER; + if(write_counter < WRITE_REPEATCOUNT) begin + // Schedule next write + next_state <= SM_WRITERETRY; + data_addr <= 0; + wait_timer <= WRITE_REPEATWAIT; + end + else begin + next_state <= SM_STOPPED; + wait_timer <= ACCESS_PAUSEPAD; + end + end + + SM_WRITERETRY: // Stop pause and schedule next write + begin + pause_cpu <= 1'b0; + state <= SM_TIMER; + next_state <= SM_WRITEPREP; + wait_timer <= WRITE_REPEATWAIT; + end + + SM_STOPPED: begin + pause_cpu <= 1'b0; + end + endcase + end + + if(state == SM_TIMER) // timer wait state + begin + // Do not progress timer if CPU is paused by source other than this module + // - Stops initial hiscore load delay being foiled by user pausing/entering OSD + if (paused == 1'b0 || pause_cpu == 1'b1) begin + if (wait_timer > 1'b0) begin + wait_timer <= wait_timer - 1'b1; + end + else begin + state <= next_state; + end + end + end + end + end + end + +endmodule diff --git a/platform/pocket/support/hiscore_io.sv b/platform/pocket/support/hiscore_io.sv new file mode 100644 index 0000000..75506a3 --- /dev/null +++ b/platform/pocket/support/hiscore_io.sv @@ -0,0 +1,258 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket HiScore NVRAM/SRAM I/O Controller for APF bridge +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// altera message_off 10230 + +`default_nettype none +`timescale 1ns/1ps + +module hiscore_io + #( + // HiScore + parameter HS_AW = 16, //! Max size of game RAM address for highscores + parameter HS_SW = 8, //! Max size of capture RAM For highscore data (default 8 = 256 bytes max) + parameter HS_CFG_AW = 2, //! Max size of RAM address for highscore.dat entries (default 4 = 16 entries max) + parameter HS_CFG_LW = 2, //! Max size of length for each highscore.dat entries (default 1 = 256 bytes max) + parameter HS_CONFIG = 2, //! Dataslot index for config transfer + parameter HS_DATA = 3, //! Dataslot index for save data transfer + // MPU <-> FPGA I/O + parameter HS_MASK = 4'h6, //! Upper 4 bits of address + parameter HS_WR_DELAY = 4, //! Number of clock cycles to delay each write output + parameter HS_WR_HOLD = 1, //! Number of clock cycles to hold the nvram_wr signal high + parameter HS_RD_DELAY = 4, //! Number of memory clock cycles it takes for a read to complete + // NVRAM HiScore + parameter HS_USE_NVRAM = 0, //! Use NVRAM HiScore Module + parameter HS_PAUSE_PAD = 4 //! Cycles to wait with paused CPU before and after NVRAM access + ) ( + input logic clk_74a, + input logic clk_memory, + input logic pll_core_locked, + input logic reset_sw, + input logic pause_core, + // Pocket Bridge Data Slots + input logic dataslot_requestwrite, + input logic [15:0] dataslot_requestwrite_id, + input logic dataslot_requestread, + input logic [15:0] dataslot_requestread_id, + input logic dataslot_allcomplete, + // Pocket Bridge + input logic bridge_endian_little, + input logic [31:0] bridge_addr, + input logic bridge_wr, + input logic [31:0] bridge_wr_data, + input logic bridge_rd, + output logic [31:0] bridge_rd_data = 0, + // Pocket Bridge Data Tables + output logic [9:0] datatable_addr, + output logic datatable_wren, + output logic [31:0] datatable_data, + // HiScore NVRAM Size + input logic [15:0] nvram_size, //! Number bytes required for Save + // HiScore Interface + output logic hs_write_en, + output logic [HS_AW-1:0] hs_address, + input logic [7:0] hs_data_out, + output logic [7:0] hs_data_in, + output logic hs_access_read, + output logic hs_access_write, + output logic hs_configured, + output logic hs_pause + ); + + //!------------------------------------------------------------------------- + //! Internal Wires and Registers + //!------------------------------------------------------------------------- + logic [HS_AW-1:0] nvram_rd_addr; + logic [HS_AW-1:0] nvram_wr_addr; + + logic nvram_download = 0; + logic [15:0] nvram_index; + logic nvram_wr; + logic [HS_AW-1:0] nvram_addr; + logic [7:0] nvram_dout; + + logic nvram_upload = 0; + logic nvram_upload_req; + logic [15:0] nvram_upload_index; + logic [7:0] nvram_din; + logic nvram_rd; + + //!------------------------------------------------------------------------- + //! Sync and Assignments + //!------------------------------------------------------------------------- + assign nvram_addr = nvram_wr ? nvram_wr_addr : nvram_rd_addr; + synch_3 #(.WIDTH(16)) sync_nvram_index(dataslot_requestwrite_id, nvram_index, clk_memory); + + //!------------------------------------------------------------------------- + //! Download/Upload Signal Handler + //!------------------------------------------------------------------------- + always_ff @(posedge clk_74a) begin + if (dataslot_requestwrite && (dataslot_requestwrite_id == HS_DATA) || (dataslot_requestwrite_id == HS_CONFIG)) begin + nvram_download <= 1; + end + else if(dataslot_requestread && (dataslot_requestread_id == HS_DATA)) begin + nvram_upload <= 1; + end + else if(dataslot_allcomplete) begin + nvram_download <= 0; + nvram_upload <= 0; + end + end + + //!------------------------------------------------------------------------- + //! Configure Save Data Size + //!------------------------------------------------------------------------- + always_ff @(posedge clk_74a or negedge pll_core_locked) begin + if (~pll_core_locked) begin + datatable_addr <= 0; + datatable_wren <= 0; + datatable_data <= 0; + end + else begin + datatable_addr <= HS_DATA * 2 + 1; // Data slot index, not id + datatable_wren <= 1; // Write nvram size + datatable_data <= nvram_size; // nvram size is the number bytes + end + end + + //!------------------------------------------------------------------------- + //! MPU -> FPGA Download + //!------------------------------------------------------------------------- + data_loader #( + .ADDRESS_MASK_UPPER_4 ( HS_MASK ), + .WRITE_MEM_CLOCK_DELAY ( HS_WR_DELAY ), + .WRITE_MEM_EN_CYCLE_LENGTH ( HS_WR_HOLD ), + .ADDRESS_SIZE ( HS_AW ) + ) hiscore_in ( + .clk_74a ( clk_74a ), + .clk_memory ( clk_memory ), + + .bridge_wr ( bridge_wr ), + .bridge_endian_little ( bridge_endian_little ), + .bridge_addr ( bridge_addr ), + .bridge_wr_data ( bridge_wr_data ), + + .write_en ( nvram_wr ), + .write_addr ( nvram_wr_addr ), + .write_data ( nvram_dout ) + ); + + //!------------------------------------------------------------------------- + //! FPGA -> MPU Upload + //!------------------------------------------------------------------------- + data_unloader #( + .ADDRESS_MASK_UPPER_4 ( HS_MASK ), + .READ_MEM_CLOCK_DELAY ( HS_RD_DELAY ), + .ADDRESS_SIZE ( HS_AW ) + ) hiscore_out ( + .clk_74a ( clk_74a ), + .clk_memory ( clk_memory ), + + .bridge_rd ( bridge_rd ), + .bridge_endian_little ( bridge_endian_little ), + .bridge_addr ( bridge_addr ), + .bridge_rd_data ( bridge_rd_data ), + + .read_en ( nvram_rd ), + .read_addr ( nvram_rd_addr ), + .read_data ( nvram_din ) + ); + + generate + if(HS_USE_NVRAM) begin + //!------------------------------------------------------------------------- + //! NVRAM HiScore + //!------------------------------------------------------------------------- + nvram #( + .DUMPWIDTH ( HS_SW ), + .CONFIGINDEX ( HS_CONFIG ), + .DUMPINDEX ( HS_DATA ), + .PAUSEPAD ( HS_PAUSE_PAD ) + ) nvram_hiscore_io ( + .clk ( clk_memory ), + .paused ( pause_core ), + .reset ( reset_sw ), + .autosave ( 1 ), + .OSD_STATUS ( pause_core ), + // I/O Interface + .ioctl_upload ( nvram_upload ), + .ioctl_upload_req ( nvram_upload_req ), + .ioctl_download ( nvram_download ), + .ioctl_wr ( nvram_wr ), + .ioctl_addr ( nvram_addr ), + .ioctl_index ( nvram_index ), + .ioctl_din ( nvram_din ), + .ioctl_dout ( nvram_dout ), + // Core Interface + .nvram_address ( hs_address ), + .nvram_data_out ( hs_data_out ), + .pause_cpu ( hs_pause ) + ); + end + else begin + //!------------------------------------------------------------------------- + //! HiScore + //!------------------------------------------------------------------------- + hiscore #( + .HS_ADDRESSWIDTH ( HS_AW ), + .HS_SCOREWIDTH ( HS_SW ), + .HS_CONFIGINDEX ( HS_CONFIG ), + .HS_DUMPINDEX ( HS_DATA ), + .CFG_ADDRESSWIDTH ( HS_CFG_AW ), + .CFG_LENGTHWIDTH ( HS_CFG_LW ) + ) hiscore_io ( + .clk ( clk_memory ), // [i] + .reset ( reset_sw ), // [i] + .autosave ( 1 ), // [i] + .paused ( pause_core ), // [i] + .menu_status ( pause_core ), // [i] + // I/O Interface + .ioctl_upload ( nvram_upload ), // [i] + .ioctl_upload_req ( nvram_upload_req ), // [o] + .ioctl_download ( nvram_download ), // [i] + .ioctl_wr ( nvram_wr ), // [i] + .ioctl_addr ( nvram_addr ), // [i] + .ioctl_index ( nvram_index ), // [i] + // Core Interface + .ram_address ( hs_address ), // [o] Address in game RAM to read/write score data + .data_from_ram ( hs_data_out ), // [i] Incoming data from game RAM + .data_to_ram ( hs_data_in ), // [o] Data to send to game RAM + .ram_write ( hs_write_en ), // [o] Write to game RAM (active high) + + .data_from_mpu ( nvram_dout ), // [i] Incoming data from MPU + .data_to_mpu ( nvram_din ), // [o] Data to send to MPU + .ram_intent_read ( hs_access_read ), // [o] RAM read required (active high) + .ram_intent_write ( hs_access_write ), // [o] RAM write required (active high) + .pause_cpu ( hs_pause ), // [o] Pause core CPU to prepare for/relax after RAM access + .configured ( hs_configured ) // [o] Hiscore module has valid configuration (active high) + ); + end + endgenerate + +endmodule diff --git a/platform/pocket/support/nvram.sv b/platform/pocket/support/nvram.sv new file mode 100644 index 0000000..ee128c0 --- /dev/null +++ b/platform/pocket/support/nvram.sv @@ -0,0 +1,257 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// NVRAM-style hiscore autosave support for arcade cores. +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2021, Jim Gregory +// +// 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//------------------------------------------------------------------------------ +// +// Version history: +// 0001 - 2021-10-01 - First marked release +// 0002 - 2021-10-09 - Add change mask support +// 0003 - 2023-06-21 - Changes for the Analogue Pocket +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module nvram + #( + parameter DUMPWIDTH = 8, // Address size of NVRAM for highscore data (default 8 = 256 bytes max) + parameter CONFIGINDEX = 2, // ioctl_index for config transfer + parameter DUMPINDEX = 3, // ioctl_index for dump transfer + parameter PAUSEPAD = 4, // Cycles to wait with paused CPU before and after NVRAM access + parameter TARGET_PLATFORM = 1 // Platform: [1] Analogue Pocket | [2] MiMiC + ) ( + input wire clk, + input wire paused, // Signal from core confirming CPU is paused + input wire reset, + input wire autosave, // Auto-save enabled (active high) + + input wire ioctl_upload, + output reg ioctl_upload_req, + input wire ioctl_download, + input wire ioctl_wr, + input wire [24:0] ioctl_addr, + input wire [7:0] ioctl_index, + output wire [7:0] ioctl_din, + input wire [7:0] ioctl_dout, + input wire OSD_STATUS, + + output wire [DUMPWIDTH-1:0] nvram_address, + input wire [7:0] nvram_data_out, + + output reg pause_cpu // Pause core CPU to prepare for/relax after NVRAM access + ); + + // Hiscore data tracking + reg downloaded_config = 1'b0; // Has hiscore config been loaded? + reg downloaded_dump = 1'b0; // Has hiscore data been loaded? + reg extracting_dump = 1'b0; // Is hiscore data currently extracted and checked for change? + wire downloading_config; // Is hiscore config currently being loaded? + wire downloading_dump; // Is hiscore data currently being loaded? + wire uploading_dump; // Is hiscore data currently being saved? + + assign downloading_config = ioctl_download && (ioctl_index == CONFIGINDEX); + assign downloading_dump = ioctl_download && (ioctl_index == DUMPINDEX); + assign uploading_dump = ioctl_upload && (ioctl_index == DUMPINDEX); + + // State machine constants + localparam SM_STATEWIDTH = 3; // Width of state machine net + localparam SM_IDLE = 0; + localparam SM_TIMER = 1; + localparam SM_EXTRACTINIT = 2; + localparam SM_EXTRACTREADY = 3; + localparam SM_EXTRACTNEXT = 4; + localparam SM_EXTRACTSAVE = 5; + localparam SM_EXTRACTCOMPLETE = 6; + + // State machine control + reg [(SM_STATEWIDTH-1):0] state = SM_IDLE; // Current state machine index + reg [(SM_STATEWIDTH-1):0] next_state = SM_IDLE; // Next state machine index to move to after wait timer expires + reg [31:0] wait_timer; // Wait timer for inital/read/write delays + + // Last cycle signals + reg last_reset = 1'b0; // Last cycle reset + reg last_OSD_STATUS; // Last cycle OSD status + reg [7:0] last_ioctl_index; // Last cycle HPS IO index + reg last_ioctl_download = 0; // Last cycle HPS IO download + + // Buffer RAM control signals + reg [DUMPWIDTH-1:0] buffer_addr; + reg [DUMPWIDTH-1:0] buffer_length; + wire [7:0] buffer_data_in; + reg buffer_write = 1'b0; + + assign nvram_address = buffer_addr; + + // Change detection signals + reg [DUMPWIDTH-1:0] compare_length = 1'b0; + reg compare_nonzero = 1'b1; // High after extract and compare if any byte returned is non-zero + reg compare_changed = 1'b1; // High after extract and compare if any byte is different to current hiscore data + wire [7:0] check_mask_out /* synthesis keep */; + wire check_mask = check_mask_out[buffer_addr[2:0]] /* synthesis keep */; + + // RAM used to store high score check mask + spram_hs #(.aWidth(DUMPWIDTH-3),.dWidth(8)) + mask_ram ( + .clk(clk), + .addr(downloading_config ? ioctl_addr[DUMPWIDTH-4:0] : buffer_addr[DUMPWIDTH-1:3]), + .we(downloading_config && ioctl_wr), + .d(ioctl_dout), + .q(check_mask_out) + ); + + // RAM used to store high score data buffer + spram_hs #(.aWidth(DUMPWIDTH),.dWidth(8)) + nvram_buffer ( + .clk(clk), + .addr((downloading_dump || uploading_dump) ? ioctl_addr[DUMPWIDTH-1:0] : buffer_addr), + .we(downloading_dump ? ioctl_wr : buffer_write), + .d(downloading_dump ? ioctl_dout : nvram_data_out), + .q(ioctl_din) + ); + + always @(posedge clk) begin + + // Track completion of configuration and dump download + if(TARGET_PLATFORM == 1) begin + if (~ioctl_download && last_ioctl_download) begin + downloaded_config <= 1'b1; + downloaded_dump <= 1'b1; + end + end + else begin + if ((last_ioctl_download != ioctl_download) && (ioctl_download == 1'b0)) begin + if (last_ioctl_index == CONFIGINDEX) downloaded_config <= 1'b1; + if (last_ioctl_index == DUMPINDEX) downloaded_dump <= 1'b1; + end + end + + // Track last cycle values + last_ioctl_download <= ioctl_download; + last_ioctl_index <= ioctl_index; + last_OSD_STATUS <= OSD_STATUS; + last_reset <= reset; + + // Check for end of core reset to initialise hiscore system state + if (last_reset == 1'b1 && reset == 1'b0) begin + next_state <= SM_IDLE; + state <= SM_IDLE; + extracting_dump <= 1'b0; + buffer_length <= (2**DUMPWIDTH) - 1'b1; + end + else begin + + // Trigger hiscore extraction when OSD is opened + if(last_OSD_STATUS==1'b0 && OSD_STATUS==1'b1 && extracting_dump==1'b0 && uploading_dump==1'b0) begin + extracting_dump <= 1'b1; + state <= SM_EXTRACTINIT; + end + + // Extract hiscore data from game RAM and save in hiscore data buffer + if (extracting_dump == 1'b1) begin + case (state) + SM_EXTRACTINIT: // Initialise state machine for extraction + begin + // Setup addresses and comparison flags + buffer_addr <= 1'b0; + buffer_write <= 1'b0; + compare_nonzero <= 1'b0; + compare_changed <= 1'b0; + compare_length <= 1'b0; + // Pause cpu and wait for next state + pause_cpu <= 1'b1; + state <= SM_TIMER; + next_state <= SM_EXTRACTREADY; + wait_timer <= PAUSEPAD; + ioctl_upload_req <= 1'b0; + end + SM_EXTRACTREADY: begin + // Schedule write for next cycle when addresses are ready + buffer_write <= 1'b1; + compare_length <= compare_length + 1'b1; + state <= SM_EXTRACTNEXT; + end + SM_EXTRACTNEXT: begin + if ((nvram_data_out != ioctl_din) && (downloaded_config == 1'b0 || check_mask == 1'b1)) begin + compare_changed <= 1'b1; // Hiscore data changed since last dump + end + + if (nvram_data_out != 8'b0) begin + compare_nonzero <= 1'b1; // Hiscore data is not blank + end + + // Always stop writing to hiscore dump ram and increment local address + buffer_write <= 1'b0; + buffer_addr <= buffer_addr + 1'b1; + + if (compare_length == buffer_length) begin + // Finish extract if last address is reached + state <= SM_TIMER; + next_state <= SM_EXTRACTSAVE; + wait_timer <= PAUSEPAD; + end + else begin + // Otherwise move to next byte + state <= SM_TIMER; + next_state <= SM_EXTRACTREADY; + wait_timer <= 1'b0; + end + + end + SM_EXTRACTSAVE: begin + // If high scores have changed and are not blank, then trigger autosave if enabled + if (compare_changed == 1'b1 && compare_nonzero == 1'b1 && autosave == 1'b1) begin + ioctl_upload_req <= 1'b1; + end + + // Release pause and schedule end of extraction process + pause_cpu <= 1'b0; + state <= SM_TIMER; + next_state <= SM_EXTRACTCOMPLETE; + wait_timer <= 4'd4; + end + SM_EXTRACTCOMPLETE: begin + // End extract, clear any upload request and move state machine to idle + extracting_dump <= 1'b0; + ioctl_upload_req <= 1'b0; + state <= SM_IDLE; + end + endcase + end + + if(state == SM_TIMER) // timer wait state + begin + // Do not progress timer if CPU is paused by source other than this module + if (paused == 1'b0 || pause_cpu == 1'b1) begin + if (wait_timer > 1'b0) + wait_timer <= wait_timer - 1'b1; + else + state <= next_state; + end + end + end + end + +endmodule diff --git a/platform/pocket/support/save_io.sv b/platform/pocket/support/save_io.sv new file mode 100644 index 0000000..013e4c6 --- /dev/null +++ b/platform/pocket/support/save_io.sv @@ -0,0 +1,139 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Analogue Pocket Save I/O Controller for APF bridge +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module save_io + #( + // MPU <-> FPGA (NVRAM/SAVE I/O) + parameter MASK = 4'h6, //! Upper 4 bits of address + parameter AW = 27, //! Address Width + parameter DW = 8, //! Data Width (8 or 16 bits) + parameter WR_DELAY = 4, //! Number of clock cycles to delay each write output + parameter WR_HOLD = 1, //! Number of clock cycles to hold the ioctl_wr signal high + parameter RD_DELAY = 4, //! Number of memory clock cycles it takes for a read to complete + parameter SAVE_IDX = 3 //! Dataslot index for save data transfer + ) ( + input logic clk_74a, + input logic clk_memory, + // Pocket Bridge Slots + input logic dataslot_requestwrite, + input logic [15:0] dataslot_requestwrite_id, + input logic dataslot_requestread, + input logic [15:0] dataslot_requestread_id, + input logic dataslot_allcomplete, + // Pocket Bridge + input logic bridge_endian_little, + input logic [31:0] bridge_addr, + input logic bridge_wr, + input logic [31:0] bridge_wr_data, + input logic bridge_rd, + output logic [31:0] bridge_rd_data = 0, + // MPU <-> FPGA + output logic nvram_download = 0, + output logic [15:0] nvram_index, + output logic nvram_wr, + output logic [AW-1:0] nvram_addr, + output logic [DW-1:0] nvram_dout, + output logic nvram_upload = 0, + input logic nvram_upload_req, + input logic [15:0] nvram_upload_index, + input logic [DW-1:0] nvram_din, + output logic nvram_rd + ); + + localparam WORD_SIZE = DW == 16 ? 2 : 1; + + logic [AW-1:0] nvram_rd_addr; + logic [AW-1:0] nvram_wr_addr; + + assign nvram_addr = nvram_wr ? nvram_wr_addr : nvram_rd_addr; + synch_3 #(.WIDTH(16)) sync_nvram_index(dataslot_requestwrite_id, nvram_index, clk_memory); + + always_ff @(posedge clk_74a) begin + if (dataslot_requestwrite && (dataslot_requestwrite_id == SAVE_IDX)) begin + nvram_download <= 1; + end + else if(dataslot_requestread && (dataslot_requestread_id == SAVE_IDX)) begin + nvram_upload <= 1; + end + else if(dataslot_allcomplete) begin + nvram_download <= 0; + nvram_upload <= 0; + end + end + + //!------------------------------------------------------------------------- + //! MPU -> FPGA Download + //!------------------------------------------------------------------------- + data_loader #( + .ADDRESS_MASK_UPPER_4 ( MASK ), + .WRITE_MEM_CLOCK_DELAY ( WR_DELAY ), + .WRITE_MEM_EN_CYCLE_LENGTH ( WR_HOLD ), + .ADDRESS_SIZE ( AW ), + .OUTPUT_WORD_SIZE ( WORD_SIZE ) + ) save_data_in ( + .clk_74a ( clk_74a ), + .clk_memory ( clk_memory ), + + .bridge_wr ( bridge_wr ), + .bridge_endian_little ( bridge_endian_little ), + .bridge_addr ( bridge_addr ), + .bridge_wr_data ( bridge_wr_data ), + + .write_en ( nvram_wr ), + .write_addr ( nvram_wr_addr ), + .write_data ( nvram_dout ) + ); + + //!------------------------------------------------------------------------- + //! FPGA -> MPU Upload + //!------------------------------------------------------------------------- + data_unloader #( + .ADDRESS_MASK_UPPER_4 ( MASK ), + .READ_MEM_CLOCK_DELAY ( RD_DELAY ), + .ADDRESS_SIZE ( AW ), + .INPUT_WORD_SIZE ( WORD_SIZE ) + ) save_data_out ( + .clk_74a ( clk_74a ), + .clk_memory ( clk_memory ), + + .bridge_rd ( bridge_rd ), + .bridge_endian_little ( bridge_endian_little ), + .bridge_addr ( bridge_addr ), + .bridge_rd_data ( bridge_rd_data ), + + .read_en ( nvram_rd ), + .read_addr ( nvram_rd_addr ), + .read_data ( nvram_din ) + ); + +endmodule diff --git a/platform/pocket/video/rgb2grayscale.sv b/platform/pocket/video/rgb2grayscale.sv new file mode 100644 index 0000000..529fcf3 --- /dev/null +++ b/platform/pocket/video/rgb2grayscale.sv @@ -0,0 +1,119 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2024, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Multiplier-based RGB to Grayscale Converter using ITU-R 601-2 Luma Transform +// +// Copyright (c) 2024, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// For RGB to Grayscale conversion, ITU-R 601-2 luma transform is performed +// which is Y = R * 0.2989 + G * 0.5870 + B * 0.1140 +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +(* altera_attribute = "-name AUTO_SHIFT_REGISTER_RECOGNITION OFF" *) +module rgb2grayscale + #( + parameter DW = 8 + )( + input logic clk, //! System clock + input logic enable, //! Enable to activate Grayscale Image + + input logic [DW-1:0] r_in, //! Red + input logic [DW-1:0] g_in, //! Green + input logic [DW-1:0] b_in, //! Blue + input logic hs_in, //! Horizontal Sync + input logic vs_in, //! Vertical Sync + input logic de_in, //! Horizontal Blank + input logic hb_in, //! Horizontal Blank + input logic vb_in, //! Vertical Blank + + output logic [DW-1:0] r_out, //! Red + output logic [DW-1:0] g_out, //! Green + output logic [DW-1:0] b_out, //! Blue + output logic hs_out, //! Horizontal Sync + output logic vs_out, //! Vertical Sync + output logic de_out, //! Horizontal Blank + output logic hb_out, //! Horizontal Blank + output logic vb_out //! Vertical Blank + ); + + logic [8+DW-1:0] r_y, g_y, b_y; // Y Carries Luma + logic [8+DW-1:0] r, y, b; + logic hs_d, vs_d; + logic hb_d, vb_d, de_d; + + //!------------------------------------------------------------------------- + //! 1st Stage + //!------------------------------------------------------------------------- + always_ff @(posedge clk) begin : multiplyStage + hs_d <= hs_in; + vs_d <= vs_in; + hb_d <= hb_in; + vb_d <= vb_in; + de_d <= de_in; + if(enable) begin + // Perform the ITU-R 601-2 luma transform + // The weights 0.299, 0.587, and 0.114 are approximated by the fractions 76/256, 150/256, and 29/256, respectively. + // These fractions are chosen based on their closeness to the original weights when scaled to 256 allowing + // the use of shift operations instead of division for efficiency. + r_y <= r_in * 8'd76; + g_y <= g_in * 8'd150; + b_y <= b_in * 8'd29; + end + else begin + // Passthrough + r_y[8+DW-1:8] <= r_in; + g_y[8+DW-1:8] <= g_in; + b_y[8+DW-1:8] <= b_in; + end + end + + //!------------------------------------------------------------------------- + //! 2nd Stage + //!------------------------------------------------------------------------- + always_ff @(posedge clk) begin : addStage + hs_out <= hs_d; + vs_out <= vs_d; + hb_out <= hb_d; + vb_out <= vb_d; + de_out <= de_d; + if(enable) begin + y <= r_y + g_y + b_y; + end + else begin + // Passthrough + r <= r_y; + y <= g_y; + b <= b_y; + end + end + + // Extract the 8-bit grayscale value from the shifted result + // and output on all RGB channels to create a BW image + assign {r_out, g_out, b_out} = (enable) ? {3{y[8+DW-1:8]}} : {r[8+DW-1:8], y[8+DW-1:8], b[8+DW-1:8]}; + +endmodule diff --git a/platform/pocket/video/scanlines.sv b/platform/pocket/video/scanlines.sv new file mode 100644 index 0000000..a1f73a4 --- /dev/null +++ b/platform/pocket/video/scanlines.sv @@ -0,0 +1,112 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Video Scanlines Generator +// +// Copyright (c) 2023, Marcus Andrade +// +// 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, version 3. +// +// 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 . +// +//------------------------------------------------------------------------------ +// | Horizontal Lines | +// | Soft | 25% | 4'b0001 | 4'd1 | +// | Medium | 50% | 4'b0010 | 4'd2 | +// | Hard | 75% | 4'b0011 | 4'd3 | +// +// | Vertical Lines | +// | Soft | 25% | 4'b0100 | 4'd4 | +// | Medium | 50% | 4'b1000 | 4'd8 | +// | Hard | 75% | 4'b1100 | 4'd12 | +// +// | Horizontal and Vertical Lines | +// | Soft | 25% | 4'b0101 | 4'd5 | +// | Medium | 50% | 4'b1010 | 4'd10 | +// | Hard | 75% | 4'b1111 | 4'd15 | +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module scanlines + ( + // Clock + input clk_vid, //! Pixel Clock + // Scanline Control + input [3:0] scnl_sw, //! Scanlines + // Video Input + input [23:0] core_rgb, //! Core: RGB Video + input core_hs, //! Core: Hsync + input core_vs, //! Core: Vsync + input core_de, //! Core: Data Enable + // Video Output + output reg [23:0] scnl_rgb, //! Ouput: RGB Video + output reg scnl_hs, //! Ouput: Hsync + output reg scnl_vs, //! Ouput: Vsync + output reg scnl_de //! Ouput: Data Enable + ); + + //!------------------------------------------------------------------------- + //! Horizontal Scanlines + //!------------------------------------------------------------------------- + wire [23:0] h_video_rgb; + wire h_video_hs, h_video_vs, h_video_de; + + scanlines_generator #(.ORIENTATION(0)) scanlines_horizontal + ( + .clk_vid ( clk_vid ), + .scanlines ( scnl_sw[1:0] ), + .core_rgb ( core_rgb ), + .core_hs ( core_hs ), + .core_vs ( core_vs ), + .core_de ( core_de ), + .scnl_rgb ( h_video_rgb ), + .scnl_hs ( h_video_hs ), + .scnl_vs ( h_video_vs ), + .scnl_de ( h_video_de ) + ); + + //!------------------------------------------------------------------------- + //! Vertical Scanlines + //!------------------------------------------------------------------------- + wire [23:0] v_video_rgb; + wire v_video_hs, v_video_vs, v_video_de; + + scanlines_generator #(.ORIENTATION(1)) scanlines_vertical + ( + .clk_vid ( clk_vid ), + .scanlines ( scnl_sw[3:2] ), + .core_rgb ( h_video_rgb ), + .core_hs ( h_video_hs ), + .core_vs ( h_video_vs ), + .core_de ( h_video_de ), + .scnl_rgb ( v_video_rgb ), + .scnl_hs ( v_video_hs ), + .scnl_vs ( v_video_vs ), + .scnl_de ( v_video_de ) + ); + + //!------------------------------------------------------------------------- + //! Video Output + //!------------------------------------------------------------------------- + always_ff @(posedge clk_vid) begin + scnl_rgb <= v_video_rgb; + scnl_hs <= v_video_hs; + scnl_vs <= v_video_vs; + scnl_de <= v_video_de; + end + +endmodule diff --git a/platform/pocket/video/scanlines_generator.sv b/platform/pocket/video/scanlines_generator.sv new file mode 100644 index 0000000..4b77b91 --- /dev/null +++ b/platform/pocket/video/scanlines_generator.sv @@ -0,0 +1,122 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Generic Video Scanlines +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2017, Alexey Melnikov +// Copyright (c) 2015, Till Harbaum +// +// 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, version 3. +// +// 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 . +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module scanlines_generator + #( + parameter ORIENTATION = 0 //! Scanline Orientation [0]: Horizontal | [1] Vertical + ) ( + // Clock + input logic clk_vid, //! Pixel Clock + // Scanline Control + input logic [1:0] scanlines, //! Scanlines - [00]: None | [01]: 25% | [10]: 50% | [11]: 75% + // Video Input + input logic [23:0] core_rgb, //! Core: RGB Video + input logic core_hs, //! Core: Vsync + input logic core_vs, //! Core: Hsync + input logic core_de, //! Core: Data Enable + // Video Output + output logic [23:0] scnl_rgb, //! Ouput: RGB Video + output logic scnl_hs, //! Ouput: Vsync + output logic scnl_vs, //! Ouput: Hsync + output logic scnl_de //! Ouput: Data Enable + ); + + wire [7:0] r, g, b; //! RGB Signals + assign {r, g, b} = core_rgb; //! Concatenation the RGB Signals + + reg [1:0] scanline_r; //! Scanline Register + reg [23:0] rgb_r; //! RGB Data + + //!------------------------------------------------------------------------- + //! Generate vertical or horizontal scanline based on ORIENTATION parameter + //!------------------------------------------------------------------------- + generate + if (ORIENTATION) begin : generateVerticalScanlines + always_ff @(posedge clk_vid) begin + reg rOLD_VS; + rOLD_VS <= core_vs; + // XOR scanline value with scanlines + scanline_r <= scanline_r ^ scanlines; + // Detect end of frame (Vsync falling edge) and reset scanline counter to 0 + if(rOLD_VS && ~core_vs) begin scanline_r <= 0; end + end + end + else begin : generateHorizontalScanlines + always_ff @(posedge clk_vid) begin + reg rOLD_HS, rOLD_VS; + rOLD_HS <= core_hs; + rOLD_VS <= core_vs; + // Detect end of line (Hsync falling edge) and XOR scanline value with scanlines + if(rOLD_HS && ~core_hs) begin scanline_r <= scanline_r ^ scanlines; end + // Detect end of frame (Vsync falling edge) and reset scanline counter to 0 + if(rOLD_VS && ~core_vs) begin scanline_r <= 0; end + end + end + endgenerate + + //!------------------------------------------------------------------------- + //! Generate scanline effect on RGB data + //!------------------------------------------------------------------------- + // 00: 00% - Set the output RGB data to be the same as the input RGB data. + // 01: 25% [1/2 + 1/4] - Concatenate the second and third bit of each color channel and add them to the first bit shifted left by one position, with an additional 0 in the least significant position. + // 10: 50% [1/2] - Keep only the first bit of each color channel. + // 11: 75% [1/4] - Keep only the second and third bits of each color channel, with an additional 0 in the most significant position. + always_comb begin + case(scanline_r) + 2'b00: begin rgb_r = {r, g, b}; end + 2'b01: begin rgb_r = {{1'b0, r[7:1]} + {2'b0, r[7:2]}, {1'b0, g[7:1]} + {2'b0, g[7:2]}, {1'b0, b[7:1]} + {2'b0, b[7:2]}}; end + 2'b10: begin rgb_r = {{1'b0, r[7:1]}, {1'b0, g[7:1]}, {1'b0, b[7:1]}}; end + 2'b11: begin rgb_r = {{2'b0, r[7:2]}, {2'b0, g[7:2]}, {2'b0, b[7:2]}}; end + endcase + end + + //!------------------------------------------------------------------------- + //! Video Output + //!------------------------------------------------------------------------- + always_ff @(posedge clk_vid) begin + // Declare registers to hold the previous and current values of the input signals + reg [23:0] rgb1, rgb2; // 24-bit RGB color values for current and previous cycles + reg hs1, hs2; // Horizontal Sync (HS) signal for current and previous cycles + reg vs1, vs2; // Vertical Sync (VS) signal for current and previous cycles + reg de1, de2; // Display Enable (DE) signal for current and previous cycles + + // Assign output signals to the values of the previous cycle + scnl_rgb <= rgb2; // Output RGB color value from two cycles ago + scnl_vs <= vs2; // Output VS signal from two cycles ago + scnl_hs <= hs2; // Output HS signal from two cycles ago + scnl_de <= de2; // Output DE signal from two cycles ago + + // Update the values of the registers with the current cycle's input signals + rgb2 <= rgb1; rgb1 <= rgb_r; // Shift the RGB values by one cycle and assign the current value + vs2 <= vs1; vs1 <= core_vs; // Shift the VS signal by one cycle and assign the current value + hs2 <= hs1; hs1 <= core_hs; // Shift the HS signal by one cycle and assign the current value + de2 <= de1; de1 <= core_de; // Shift the DE signal by one cycle and assign the current value + end + +endmodule diff --git a/platform/pocket/video/shadowmask.sv b/platform/pocket/video/shadowmask.sv new file mode 100644 index 0000000..0e65dc4 --- /dev/null +++ b/platform/pocket/video/shadowmask.sv @@ -0,0 +1,187 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Video Shadow Mask +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2020, Alexey Melnikov +// +// 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, version 3. +// +// 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 . +// +//------------------------------------------------------------------------------ +// altera message_off 10230 + +`default_nettype none +`timescale 1ns/1ps + +module shadowmask + ( + // Clocks + input wire clk_vid, + input wire clk_sys, + // ShadowMask Config + input wire mask_wr, + input wire [15:0] mask_data, + // Input Controls + input wire mask_enable, + input wire mask_rotate, + input wire mask_2x, + input wire brd_in, + // Input Video + input wire [23:0] din, + input wire hs_in, + input wire vs_in, + input wire de_in, + // Output Video + output reg [23:0] dout, + output reg hs_out, + output reg vs_out, + output reg de_out + ); + + reg [3:0] vmax; + reg [3:0] hmax; + reg [7:0] mask_idx; + reg [10:0] mask_lut[256]; + + initial begin + vmax = 1; + hmax = 1; + mask_lut[0] = 11'h70f; + mask_lut[1] = 11'h00c; + mask_lut[2] = 11'h00c; + mask_lut[3] = 11'h70f; + end + + always_ff @(posedge clk_sys) begin + reg [7:0] idx; + + if (mask_wr) begin + case(mask_data[15:13]) + 3'b000: begin idx <= 0; end + 3'b001: begin vmax <= mask_data[3:0]; end + 3'b010: begin hmax <= mask_data[3:0]; end + 3'b011: begin mask_lut[idx] <= mask_data[10:0]; idx <= idx + 1; end + default: begin /* DO NOTHING */ end + endcase + end + end + + always_ff @(posedge clk_vid) begin + reg [4:0] hcount; + reg [4:0] vcount; + reg [3:0] hindex; + reg [3:0] vindex; + reg [4:0] hmax2; + reg [4:0] vmax2; + reg [11:0] pcnt,pde; + reg old_hs, old_vs, old_brd; + reg next_v; + + old_hs <= hs_in; + old_vs <= vs_in; + old_brd <= brd_in; + + // hcount and vcount counts pixel rows and columns + // hindex and vindex half the value of the counters for double size patterns + // hindex2, vindex2 swap the h and v counters for drawing rotated masks + hindex <= mask_2x ? hcount[4:1] : hcount[3:0]; + vindex <= mask_2x ? vcount[4:1] : vcount[3:0]; + mask_idx <= mask_rotate ? {hindex,vindex} : {vindex,hindex}; + + // hmax and vmax store these sizes + // hmax2 and vmax2 swap the values to handle rotation + hmax2 <= ((mask_rotate ? vmax : hmax) << mask_2x) | mask_2x; + vmax2 <= ((mask_rotate ? hmax : vmax) << mask_2x) | mask_2x; + + pcnt <= pcnt+1'd1; + if(old_brd && ~brd_in) begin + pde <= pcnt - 4'd3; + end + + hcount <= hcount+1'b1; + if(hcount == hmax2 || pde == pcnt) begin + hcount <= 0; + end + + if(~old_brd && brd_in) begin + next_v <= 1; + end + + if(old_vs && ~vs_in) begin + vcount <= 0; + end + + if(old_hs && ~hs_in) begin + vcount <= vcount + next_v; + next_v <= 0; + pcnt <= 0; + if (vcount == vmax2) begin + vcount <= 0; + end + end + end + + reg [4:0] r_mul, g_mul, b_mul; // 1.4 fixed point multipliers + always_ff @(posedge clk_vid) begin + reg [10:0] lut; + + lut <= mask_lut[mask_idx]; + + r_mul <= 5'b10000; + g_mul <= 5'b10000; + b_mul <= 5'b10000; // default 100% to all channels + if (mask_enable) begin + r_mul <= lut[10] ? { 1'b1, lut[7:4] } : { 1'b0, lut[3:0] }; + g_mul <= lut[9] ? { 1'b1, lut[7:4] } : { 1'b0, lut[3:0] }; + b_mul <= lut[8] ? { 1'b1, lut[7:4] } : { 1'b0, lut[3:0] }; + end + end + + always_ff @(posedge clk_vid) begin + reg [11:0] vid; + reg [7:0] r1, g1, b1; + reg [7:0] r2, g2, b2; + reg [7:0] r3_x, g3_x, b3_x; // 6.25% + 12.5% + reg [8:0] r3_y, g3_y, b3_y; // 25% + 50% + 100% + reg [8:0] r4, g4, b4; + + // C1 - data input + {r1, g1, b1} <= din; + vid <= { vid[8:0], vs_in, hs_in, de_in }; + + // C2 - relax timings + {r2, g2, b2} <= {r1, g1, b1}; + + // C3 - perform multiplications + r3_x <= ( {4{r_mul[0]}} & r2[7:4] ) + ( {8{r_mul[1]}} & r2[7:3] ); + r3_y <= ( {6{r_mul[2]}} & r2[7:2] ) + ( {7{r_mul[3]}} & r2[7:1] ) + ( {9{r_mul[4]}} & r2[7:0] ); + g3_x <= ( {4{g_mul[0]}} & g2[7:4] ) + ( {8{g_mul[1]}} & g2[7:3] ); + g3_y <= ( {6{g_mul[2]}} & g2[7:2] ) + ( {7{g_mul[3]}} & g2[7:1] ) + ( {9{g_mul[4]}} & g2[7:0] ); + b3_x <= ( {4{b_mul[0]}} & b2[7:4] ) + ( {8{b_mul[1]}} & b2[7:3] ); + b3_y <= ( {6{b_mul[2]}} & b2[7:2] ) + ( {7{b_mul[3]}} & b2[7:1] ) + ( {9{b_mul[4]}} & b2[7:0] ); + + // C4 - combine results + r4 <= r3_x + r3_y; + g4 <= g3_x + g3_y; + b4 <= b3_x + b3_y; + + // C5 - clamp and output + dout <= { {8{r4[8]}} | r4[7:0], {8{g4[8]}} | g4[7:0], {8{b4[8]}} | b4[7:0] }; + {vs_out, hs_out, de_out} <= vid[11:9]; + end + +endmodule diff --git a/platform/pocket/video/sync_fix.sv b/platform/pocket/video/sync_fix.sv new file mode 100644 index 0000000..7c38884 --- /dev/null +++ b/platform/pocket/video/sync_fix.sv @@ -0,0 +1,68 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, Open Gateware authors and contributors +//------------------------------------------------------------------------------ +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2017, Alexey Melnikov +// +// This source file 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 source file 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 . +// +//------------------------------------------------------------------------------ +// Automatically calculate the polarity signal and synchronize the output signal +// to the input signal based on the clock signal. +// +// This module implements a synchronized output signal based on an input signal and a clock. +// The output signal is the XOR of the input signal and a polarity signal (polarity). +// The polarity signal is calculated based on the number of positive and negative edges detected +// in the input signal, and is updated on each positive edge of the clock. +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module sync_fix + ( + input logic clk, //! Clock + input logic sync_in, //! Input Sync (Horizontal or Vertical) + output logic sync_out //! Output Sync (Horizontal or Vertical) + ); + + // Assign the synchronized output signal by XORing input with polarity + assign sync_out = sync_in ^ polarity; + + // Register for polarity + logic polarity; + + // Create an always block triggered on positive edge of clock + always_ff @(posedge clk) begin + // Declare local integer variables for positive edge, negative edge, and counter + integer pos, neg, cnt; + // Declare registers for two synchronized signals s1 and s2 + logic s1, s2; + // Assign s1 and s2 to current and previous values of sync_in + s1 <= sync_in; + s2 <= s1; + // Update the positive and negative edge counts + if(~s2 & s1) begin neg <= cnt; end + if( s2 & ~s1) begin pos <= cnt; end + // Increment the counter and reset if the synchronized signal changes state + cnt <= cnt + 1; + if(s2 != s1) begin cnt <= 0; end + // Update the polarity based on the difference between positive and negative edge counts + polarity <= pos > neg; + end + +endmodule diff --git a/platform/pocket/video/video_cleaner.sv b/platform/pocket/video/video_cleaner.sv new file mode 100644 index 0000000..0997c32 --- /dev/null +++ b/platform/pocket/video/video_cleaner.sv @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, Open Gateware authors and contributors +//------------------------------------------------------------------------------ +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2017, Alexey Melnikov +// +// This source file 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 source file 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 . +// +//------------------------------------------------------------------------------ +// Align vb_in/vs_in to hb_in/hs_in edges. +// Warning! Breaks interlaced vs_in. +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module video_cleaner + #( + parameter DW = 8 //! Color Depth + )( + input logic clk, //! System clock + input logic enable, //! Enable Video Cleaner + + input logic [DW-1:0] r_in, //! Red + input logic [DW-1:0] g_in, //! Green + input logic [DW-1:0] b_in, //! Blue + input logic hs_in, //! Horizontal Sync + input logic vs_in, //! Vertical Sync + input logic hb_in, //! Horizontal Blank + input logic vb_in, //! Vertical Blank + // Video output signals + output logic [DW-1:0] r_out, //! Red + output logic [DW-1:0] g_out, //! Green + output logic [DW-1:0] b_out, //! Blue + output logic vs_out, //! Horizontal Sync + output logic hs_out, //! Vertical Sync + // Optional aligned blank + output logic hb_out, //! Horizontal Blank + output logic vb_out //! Vertical Blank + ); + + wire hs, vs; + + sync_fix sync_hs(clk, hs_in, hs); + sync_fix sync_vs(clk, vs_in, vs); + + logic hbl = hs | hb_in; + logic vbl = vs | vb_in; + + always_ff @(posedge clk) begin + if(enable) begin + r_out <= r_in; + g_out <= g_in; + b_out <= b_in; + hs_out <= hs; + if(~hs_out & hs) begin + vs_out <= vs; + end + hb_out <= hbl; + if(hb_out & ~hbl) begin + vb_out <= vbl; + end + end + else begin + // Passthrough + r_out <= r_in; + g_out <= g_in; + b_out <= b_in; + hs_out <= hs_in; + vs_out <= vs_in; + hb_out <= hb_in; + vb_out <= vb_in; + end + end + +endmodule diff --git a/platform/pocket/video/video_mixer.sv b/platform/pocket/video/video_mixer.sv new file mode 100644 index 0000000..de3767f --- /dev/null +++ b/platform/pocket/video/video_mixer.sv @@ -0,0 +1,209 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Copyright (c) 2023, Marcus Andrade +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// Generic Video Interface for the Analogue Pocket Display +// +// Note: APF scaler requires HSync and VSync to last for a single clock, and +// video_rgb to be 0 when video_de is low +// +// RGB palettes +// +// | RGB Format | Bit Depth | Number of Colors | +// | ---------- | --------- | ---------------- | +// | RGB111 | 3 bits | 8 | +// | RGB222 | 6 bits | 64 | +// | RGB233 | 8 bits | 256 | +// | RGB332 | 8 bits | 256 | +// | RGB333 | 9 bits | 512 | +// | RGB444 | 12 bits | 4,096 | +// | RGB555 | 15 bits | 32,768 | +// | RGB565 | 16 bits | 65,536 | +// | RGB666 | 18 bits | 262,144 | +// | RGB888 | 24 bits | 16,777,216 | +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module video_mixer + #( + parameter RW = 8, //! Bits Per Pixel Red + parameter GW = 8, //! Bits Per Pixel Green + parameter BW = 8, //! Bits Per Pixel Blue + parameter ENABLE_INTERLACED = 0, //! Enable Interlaced Video Support + parameter USE_VBL = 0 //! Capture and Use VBlank value at HSync + ) ( + // Clocks + input wire clk_74a, //! APF: Main Clock + input wire clk_sys, //! Core: System Clock + input wire clk_vid, //! Core: Pixel Clock + input wire clk_vid_90deg, //! Core: Pixel Clock 90º Phase Shift + input wire reset, //! System Reset + // Input Controls + input wire grayscale_en, //! Enable Grayscale video output + input wire [2:0] video_preset, //! Video preset configurations (up to 8) + input wire [3:0] scnl_sw, //! Scanlines Switches + input wire [3:0] smask_sw, //! Shadow Mask Switches + // Interlaced Video Controls + input wire field, //! [0] Even | [1] Odd + input wire interlaced, //! [0] Progressive | [1] Interlaced + // Input Video from Core + input wire [RW-1:0] core_r, //! Core: Video Red + input wire [GW-1:0] core_g, //! Core: Video Green + input wire [BW-1:0] core_b, //! Core: Video Blue + input wire core_hs, //! Core: Horizontal Sync + input wire core_vs, //! Core: Vertical Sync + input wire core_hb, //! Core: Horizontal Blank + input wire core_vb, //! Core: Vertical Blank + // Output to Display Connection + output logic [23:0] video_rgb, //! Display: RGB Color: Red[23:16] Green[15:8] Blue[7:0] + output logic video_hs, //! Display: Horizontal Sync + output logic video_vs, //! Display: Vertical Sync + output logic video_de, //! Display: Data Enable + output wire video_skip, //! Display: Pixel Skip + output wire video_rgb_clock, //! Display: Pixel Clock + output wire video_rgb_clock_90, //! Display: Pixel Clock with 90º Phase Shift + // Output Video from Core + output wire [5:0] vga_r, //! VGA: Video Red + output wire [5:0] vga_g, //! VGA: Video Green + output wire [5:0] vga_b, //! VGA: Video Blue + output wire vga_hs, //! VGA: Hsync + output wire vga_vs, //! VGA: Vsync + output wire vga_de, //! VGA: Data Enable + output wire vga_clk, //! VGA: Pixel Clock + // Pocket Bridge Slots + input wire dataslot_requestwrite, //! + input wire [15:0] dataslot_requestwrite_id, //! + input wire dataslot_allcomplete, //! + // Pocket Bridge + input wire bridge_endian_little, //! + input wire [31:0] bridge_addr, //! + input wire bridge_wr, //! + input wire [31:0] bridge_wr_data //! + ); + + //! ------------------------------------------------------------------------ + //! Combine Colors to Create a Full RGB888 Color Space + //! ------------------------------------------------------------------------ + wire [7:0] R = RW == 8 ? core_r : {core_r, {8-RW{1'b0}}}; + wire [7:0] G = GW == 8 ? core_g : {core_g, {8-GW{1'b0}}}; + wire [7:0] B = BW == 8 ? core_b : {core_b, {8-BW{1'b0}}}; + + //! ------------------------------------------------------------------------ + //! VGA Output + //! ------------------------------------------------------------------------ + assign vga_r = R[7:2]; + assign vga_g = G[7:2]; + assign vga_b = B[7:2]; + assign vga_vs = core_vs; + assign vga_hs = core_hs; + assign vga_de = ~(core_vb | core_hb); + assign vga_clk = video_rgb_clock; + + + //!------------------------------------------------------------------------- + //! Convert RGB to Grayscale + //!------------------------------------------------------------------------- + wire [7:0] bw_r, bw_g, bw_b; + wire bw_hs, bw_vs; + wire bw_hb, bw_vb; + + rgb2grayscale u_rgb2grayscale + ( + .clk ( clk_vid ), + .enable ( grayscale_en ), + + .r_in ( R ), + .g_in ( G ), + .b_in ( B ), + .hs_in ( core_hs ), + .vs_in ( core_vs ), + .hb_in ( core_hb ), + .vb_in ( core_vb ), + + .r_out ( bw_r ), + .g_out ( bw_g ), + .b_out ( bw_b ), + .hs_out ( bw_hs ), + .vs_out ( bw_vs ), + .hb_out ( bw_hb ), + .vb_out ( bw_vb ) + ); + + //! ------------------------------------------------------------------------ + //! Sync Video Output + //! ------------------------------------------------------------------------ + reg [7:0] r_out, g_out, b_out; + reg hs_out, vs_out; + reg hb_out, vb_out, vbl_out; + reg field_out, interlaced_out, preset_out; + + // Latch signals so they're delayed the same amount as the incoming video + always_ff @(posedge clk_vid) begin : syncVideo + r_out <= bw_r; + g_out <= bw_g; + b_out <= bw_b; + hs_out <= bw_hs; + vs_out <= bw_vs; + hb_out <= bw_hb; + vb_out <= bw_vb; + if (~hs_out && bw_hs) begin + vbl_out <= bw_vb; + end + field_out <= field; + interlaced_out <= interlaced; + preset_out <= video_preset; + end + + //! ------------------------------------------------------------------------ + //! APF Video Output + //! ------------------------------------------------------------------------ + always_ff @(posedge clk_vid) begin : apfVideoOutput + video_de <= 1'b0; + video_rgb <= { 8'h0, preset_out, 13'h0 }; + if (ENABLE_INTERLACED && vs_out) begin + video_rgb <= { 20'h0, ~field_out, field_out, interlaced_out, 1'b0 }; + end + else if ((USE_VBL && ~(hb_out | vbl_out)) || (!USE_VBL && ~(hb_out | vb_out))) begin + video_de <= 1'b1; + video_rgb <= { r_out, g_out, b_out }; + end + // Set HSync and VSync to be high for a single cycle on the rising edge + // of the HSync and VSync coming out of the core + video_hs <= ~hs_out && bw_hs; + video_vs <= ~vs_out && bw_vs; + end + + //! ------------------------------------------------------------------------ + //! Clock Output + //! ------------------------------------------------------------------------ + assign video_rgb_clock = clk_vid; + assign video_rgb_clock_90 = clk_vid_90deg; + assign video_skip = 1'b0; + +endmodule diff --git a/projects/irem_m92_pocket.qip b/projects/irem_m92_pocket.qip new file mode 100644 index 0000000..e349a64 --- /dev/null +++ b/projects/irem_m92_pocket.qip @@ -0,0 +1,8 @@ +# ============================================================================== +# Quartus Prime Platform Specific Modules File +# Generated by OpenGateware - Gateman CLI v0.1.0 +# ============================================================================== +# A single file that contains paths to platform specific third-party modules. +# Quartus will use this file but won't edit it. +# You need to edit it manually to add/remove files here. +# ============================================================================== diff --git a/projects/irem_m92_pocket.qpf b/projects/irem_m92_pocket.qpf new file mode 100644 index 0000000..564eceb --- /dev/null +++ b/projects/irem_m92_pocket.qpf @@ -0,0 +1,11 @@ +# ============================================================================== +# Quartus Prime Project File +# Generated by OpenGateware - Gateman CLI v0.1.0 +# ============================================================================== + +QUARTUS_VERSION = "18.1" +DATE = "13:25:30 February 08, 2023" + +# Revisions + +PROJECT_REVISION = "irem_m92_pocket" diff --git a/projects/irem_m92_pocket.qsf b/projects/irem_m92_pocket.qsf new file mode 100644 index 0000000..f6bf6ba --- /dev/null +++ b/projects/irem_m92_pocket.qsf @@ -0,0 +1,93 @@ +# ============================================================================== +# Quartus Prime Settings File +# Generated by OpenGateware - Gateman CLI v0.1.0 +# ============================================================================== +# WARNING: DO NOT ADD FILES TO THE PROJECT VIA THE QUARTUS IDE! +# Add them manually to irem_m92_pocket.qip or Quartus will overwrite this file. +# ============================================================================== + +# ============================================================================== +# Project-Wide Assignments +# ============================================================================== +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 17.0.0 +set_global_assignment -name LAST_QUARTUS_VERSION "17.1.0 Standard Edition" +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name TOP_LEVEL_ENTITY apf_top + +# ============================================================================== +# Compiler Assignments +# ============================================================================== +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name SEED 1 + +# ============================================================================== +# Analysis & Synthesis Assignments +# ============================================================================== +set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +#set_global_assignment -name MUX_RESTRUCTURE OFF +set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON +set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON +set_global_assignment -name SAFE_STATE_MACHINE ON +set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION ON +set_global_assignment -name SYNTH_PROTECT_SDC_CONSTRAINT ON + +# ============================================================================== +# Fitter Assignments +# ============================================================================== +set_global_assignment -name CRC_ERROR_OPEN_DRAIN ON +set_global_assignment -name ECO_OPTIMIZE_TIMING ON +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256 +set_global_assignment -name FITTER_EFFORT "AUTO FIT" +set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING OFF +set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON +set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON + +# ============================================================================== +# Pin & Location Assignments +# ============================================================================== +set_global_assignment -name SOURCE_TCL_SCRIPT_FILE ../platform/pocket/bsp/pocket/sys_assign.tcl + +# ============================================================================== +# Platform Modules, Constrains and Chain Description File +# ============================================================================== +set_global_assignment -name QIP_FILE irem_m92_pocket.qip +set_global_assignment -name SDC_FILE irem_m92_pocket.sdc +set_global_assignment -name CDF_FILE irem_m92_pocket.cdf + +# ============================================================================== +# Core RTL Assignments +# ============================================================================== +set_global_assignment -name QIP_FILE ../rtl/index.qip + +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name ALLOW_SYNCH_CTRL_USAGE ON +set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008 +set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name DSP_BLOCK_BALANCING "DSP BLOCKS" +set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION AUTO +set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name AUTO_RESOURCE_SHARING ON + +set_global_assignment -name ALM_REGISTER_PACKING_EFFORT MEDIUM +set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION NEVER +#set_global_assignment -name FITTER_EFFORT "FAST FIT" +set_global_assignment -name AUTO_DELAY_CHAINS_FOR_HIGH_FANOUT_INPUT_PINS ON +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON +set_global_assignment -name MUX_RESTRUCTURE ON +# ============================================================================== +# Incremental Compilation Assignments +# ============================================================================== +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/projects/irem_m92_pocket.sdc b/projects/irem_m92_pocket.sdc new file mode 100644 index 0000000..15ce3c9 --- /dev/null +++ b/projects/irem_m92_pocket.sdc @@ -0,0 +1,83 @@ +# ============================================================================== +# Quartus Prime Synopsys Design Constraint File +# Generated by OpenGateware - Gateman CLI v0.1.0 +# ============================================================================== +# Analogue Pocket SDC settings +# Users are recommended to modify this file to match users logic. +# Put your clock groups in here as well as any net assignments. +# ============================================================================== + +# ============================================================================== +# Time Information +# ============================================================================== + +# ============================================================================== +# Create Clock +# ============================================================================== + +# ============================================================================== +# Create Generated Clock +# ============================================================================== + +# ============================================================================== +# Set Clock Latency +# ============================================================================== + +# ============================================================================== +# Set Clock Uncertainty +# ============================================================================== + +# ============================================================================== +# Set Input Delay +# ============================================================================== +set_input_delay -clock { ic|core_pll|core_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk } -max 6.4 [get_ports dram_dq[*]] +set_input_delay -clock { ic|core_pll|core_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk } -min 3.1 [get_ports dram_dq[*]] +# set_input_delay -clock dram_clk -reference_pin [get_ports {dram_clk}] -max 6.4 [get_ports dram_dq[*]] +# set_input_delay -clock dram_clk -reference_pin [get_ports {dram_clk}] -min 3.2 [get_ports dram_dq[*]] + +# ============================================================================== +# Set Output Delay +# ============================================================================== +set_output_delay -clock { ic|core_pll|core_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk } -min -0.8 [get_ports {dram_a[*] dram_ba[*] dram_cke dram_dqm[*] dram_dq[*] dram_ras_n dram_cas_n dram_we_n}] +set_output_delay -clock { ic|core_pll|core_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk } -max 1.5 [get_ports {dram_a[*] dram_ba[*] dram_cke dram_dqm[*] dram_dq[*] dram_ras_n dram_cas_n dram_we_n}] +# tDH, hold time, spec is 0.8ns +# set_output_delay -clock dram_clk -min -0.8 [get_ports {dram_a[*] dram_ba[*] dram_cke dram_dqm[*] dram_dq[*] dram_ras_n dram_cas_n dram_we_n}] +# tDS, setup time, spec is 1.5ns +# set_output_delay -clock dram_clk -max 1.5 [get_ports {dram_a[*] dram_ba[*] dram_cke dram_dqm[*] dram_dq[*] dram_ras_n dram_cas_n dram_we_n}] + +# ============================================================================== +# Set Clock Groups +# ============================================================================== + +# ============================================================================== +# Set False Path +# ============================================================================== + +# ============================================================================== +# Set Multicycle Path +# ============================================================================== +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|regs.*} -setup 2 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|regs.*} -hold 1 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|bus_datawrite[*]} -setup 2 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|bus_datawrite[*]} -hold 1 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|bus_addr[*]} -setup 2 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|v30:v30|bus_addr[*]} -hold 1 + +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|regs.*} -setup 2 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|regs.*} -hold 1 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|bus_datawrite[*]} -setup 2 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|bus_datawrite[*]} -hold 1 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|bus_addr[*]} -setup 2 +set_multicycle_path -from {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|*} -to {core_top:ic|irem_m92:u_irem_m92_top|m92:m92|sound:sound|v35:v35|v30:core|bus_addr[*]} -hold 1 +# ============================================================================== +# Set Maximum Delay +# ============================================================================== + +# ============================================================================== +# Set Minimum Delay +# ============================================================================== + +# ============================================================================== +# Set Input Transition +# ============================================================================== + diff --git a/rtl/dpramv.sv b/rtl/dpramv.sv new file mode 100644 index 0000000..1dd3d2f --- /dev/null +++ b/rtl/dpramv.sv @@ -0,0 +1,175 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +`timescale 1ns / 1ps + +module dualport_ram #( + parameter width = 8, + parameter widthad = 10 +) ( + // Port A + input wire clock_a, + input wire wren_a, + input wire [widthad-1:0] address_a, + input wire [width-1:0] data_a, + output reg [width-1:0] q_a, + + // Port B + input wire clock_b, + input wire wren_b, + input wire [widthad-1:0] address_b, + input wire [width-1:0] data_b, + output reg [width-1:0] q_b +); + +// Shared ramory +reg [width-1:0] ram[(2**widthad)-1:0]; + +// Port A +always @(posedge clock_a) begin + if (wren_a) begin + ram[address_a] <= data_a; + q_a <= data_a; + end else begin + q_a <= ram[address_a]; + end +end + +// Port B +always @(posedge clock_b) begin + if(wren_b) begin + q_b <= data_b; + ram[address_b] <= data_b; + end else begin + q_b <= ram[address_b]; + end +end + +endmodule + +module singleport_ram #( + parameter width = 8, + parameter widthad = 10, + parameter name = "NONE" +) ( + input wire clock, + input wire wren, + input wire [widthad-1:0] address, + input wire [width-1:0] data, + output reg [width-1:0] q + +); + +altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .q_a (q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); +defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 2**widthad, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.ram_block_type = "M10K", + altsyncram_component.read_during_write_mode_port_a = "DONT_CARE", + altsyncram_component.widthad_a = widthad, + altsyncram_component.width_a = width, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +module singleport_unreg_ram #( + parameter width = 8, + parameter widthad = 10, + parameter name = "NONE" +) ( + input wire clock, + input wire wren, + input wire [widthad-1:0] address, + input wire [width-1:0] data, + output wire [width-1:0] q +); + +altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .q_a (q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); +defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 2**widthad, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.ram_block_type = "M10K", + altsyncram_component.read_during_write_mode_port_a = "DONT_CARE", + altsyncram_component.widthad_a = widthad, + altsyncram_component.width_a = width, + altsyncram_component.width_byteena_a = 1; + +endmodule \ No newline at end of file diff --git a/rtl/eeprom.sv b/rtl/eeprom.sv new file mode 100644 index 0000000..bd86fd8 --- /dev/null +++ b/rtl/eeprom.sv @@ -0,0 +1,169 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module eeprom_28C64 #(parameter WRITE_CYCLES=0) ( + // Hardware ports + input clk, + input reset, + + input ce, + input wr, + input rd, + + input [12:0] addr, + input [7:0] data, + output [7:0] q, + + output ready, + + + // MiSTer support + output reg modified, + input ioctl_download, + input ioctl_wr, + input [12:0] ioctl_addr, + input [7:0] ioctl_dout, + + input ioctl_upload, + output [7:0] ioctl_din, + input ioctl_rd +); + +wire [7:0] q0; + +dualport_ram #(8, 13) mem( + .clock_a(clk), + .wren_a(wr), + .address_a(addr), + .data_a(data), + .q_a(q0), + + .clock_b(clk), + .wren_b(ioctl_download & ioctl_wr), + .address_b(ioctl_addr), + .data_b(ioctl_dout), + .q_b(ioctl_din) +); + +wire busy; +reg [31:0] write_timer; +reg prev_upload; + +assign ready = write_timer == 32'd0; +assign busy = ~ready; +assign q = ready ? q0 : ( ~q0 ); + +always_ff @(posedge clk) begin + if (reset) begin + write_timer <= 32'd0; + modified <= 0; + end else if (ce) begin + if (ioctl_upload & ~prev_upload) modified <= 0; + prev_upload <= ioctl_upload; + + if (wr) modified <= 1; + if (busy) begin + write_timer <= write_timer - 32'd1; + end else if (wr) begin + write_timer <= WRITE_CYCLES; + end + end +end + +endmodule + + +// This is completely untested. I wrote it and then realized it was not the eeprom that the M92 uses. +// Keeping it here in case it comes in useful at some point. It is an Atmel 28 series eeprom with 64 +// byte pages. +module eeprom_28xx_paged( + input clk, + + input reset, + + input ce, + input wr, + input rd, + + input [13:0] addr, + input [7:0] data, + output reg [7:0] q +); + +reg [7:0] mem[16384]; + +reg [7:0] write_page; +reg [5:0] write_addrs[64]; +reg [7:0] write_bytes[64]; +reg [6:0] write_index; +reg [6:0] store_index; +reg write_queuing; +reg store_pending; +reg [31:0] write_timer; +reg [7:0] last_byte; + +always @(posedge clk) begin + if (reset) begin + store_pending <= 0; + write_queuing <= 0; + write_index <= 7'd0; + store_index <= 7'd0; + + end else if (ce) begin + if (store_pending) begin + if (store_index == write_index) begin + store_pending <= 0; + end else begin + mem[{write_page, write_addrs[store_index]}] <= write_bytes[store_index]; + store_index <= store_index + 7'd1; + end + end else if (wr) begin + write_timer <= 32'd0; + write_queuing <= 1; + write_addrs[write_index] <= addr[5:0]; + write_bytes[write_index] <= data; + write_index <= write_index + 7'd1; + write_page <= addr[13:6]; + last_byte <= data; + + if (write_index == 7'd63) begin + store_pending <= 1; + store_index <= 7'd0; + write_queuing <= 0; + end + end else if (write_queuing) begin + write_timer <= write_timer + 32'd1; + if (write_timer == 32'd100_000) begin + store_pending <= 1; + store_index <= 7'd0; + write_queuing <= 0; + end + end + + if (rd) begin + if (write_queuing | store_pending) begin + q <= { ~last_byte[7], last_byte[6:0] }; + last_byte[6] <= ~last_byte[6]; + end else begin + q <= mem[addr]; + end + end + end +end + +endmodule diff --git a/rtl/ga20.sv b/rtl/ga20.sv new file mode 100644 index 0000000..04f8558 --- /dev/null +++ b/rtl/ga20.sv @@ -0,0 +1,306 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module ga20_channel( + input clk, + input reset, + + input ce, + + input cs, + input rd, + input wr, + input [2:0] addr, + input [7:0] din, + output reg [7:0] dout, + + output [19:0] sample_addr, + output reg sample_req, + input sample_ack, + input [63:0] sample_din, + + output [15:0] sample_out +); + +reg step; +reg [5:0] volume; +reg [7:0] rate; +reg [19:0] start_addr, end_addr, cur_addr; +reg [1:0] play; +reg [8:0] rate_cnt; + +reg [7:0] sample_s8; + +reg play_set; +wire [7:0] sample_data; + +assign sample_addr = cur_addr; + +always @(*) begin + case(cur_addr[2:0]) + 3'd0: sample_data = sample_din[ 7: 0]; + 3'd1: sample_data = sample_din[15: 8]; + 3'd2: sample_data = sample_din[23:16]; + 3'd3: sample_data = sample_din[31:24]; + 3'd4: sample_data = sample_din[39:32]; + 3'd5: sample_data = sample_din[47:40]; + 3'd6: sample_data = sample_din[55:48]; + default: sample_data = sample_din[63:56]; + endcase; +end +always_ff @(posedge clk, posedge reset) begin + if (reset) begin + volume <= 6'd00; + play <= 2'd0; + step <= 0; + play_set <= 0; + sample_s8 <= 8'h00; + end else begin + if (cs & rd) begin + if (addr == 3'd7) dout <= { 7'd0, play[1] }; + end else if (cs & wr) begin + case (addr) + 3'd0: start_addr[11:0] <= { din, 4'b0000 }; + 3'd1: start_addr[19:12] <= din; + 3'd2: end_addr[11:0] <= { din, 4'b0000 }; + 3'd3: end_addr[19:12] <= din; + 3'd4: rate <= din; + 3'd5: volume <= din[5:0]; + 3'd6: begin + play <= din[1:0]; + play_set <= din[1]; + end + endcase + end + + if (ce && sample_req == sample_ack) begin + step <= ~step; + + if (~step) begin + // first cycle + + if (play_set) begin + cur_addr <= start_addr; + sample_req <= ~sample_req; + play_set <= 0; + rate_cnt <= rate + 9'd2; + end else begin + rate_cnt <= rate_cnt + 9'd2; + end + end else begin + // second cycle + if (~play_set & play[1]) begin + if (sample_data == 8'd0) begin + play[1] <= 0; + sample_s8 <= 8'h00; + end else begin + sample_s8 <= { ~sample_data[7], sample_data[6:0] }; + + if (rate_cnt[8]) begin + cur_addr <= cur_addr + 20'd1; + if (cur_addr[2:0] == 3'b111) begin + sample_req <= ~sample_req; + end + rate_cnt <= rate_cnt + { 1'b1, rate }; + + if (cur_addr == end_addr) begin + if (play[0]) begin + cur_addr <= start_addr; + sample_req <= ~sample_req; + end else begin + sample_s8 <= 8'h00; + play[1] <= 0; + end + end + end + end + end + end + end + end +end + +// apply attenuation after filtering +always_ff @(posedge clk) begin + bit [7:0] vol_one; + + vol_one = { 2'd0, volume } + 8'd1; + + sample_out <= $signed(sample_s8) * $signed(vol_one); +end + + +endmodule + + +module ga20( + input clk, + input reset, + input filter_en, + + input ce, + + input cs, + input rd, + input wr, + input [4:0] addr, + input [7:0] din, + output [7:0] dout, + + + output reg sample_rom_req, + output reg [19:0] sample_rom_addr, + input sample_rom_ack, + input [63:0] sample_rom_din, + + output [15:0] sample_out +); + +reg [2:0] step; + +wire ce0 = step[2:1] == 2'd0; +wire ce1 = step[2:1] == 2'd1; +wire ce2 = step[2:1] == 2'd2; +wire ce3 = step[2:1] == 2'd3; + +wire cs0 = cs && addr[4:3] == 2'd0; +wire cs1 = cs && addr[4:3] == 2'd1; +wire cs2 = cs && addr[4:3] == 2'd2; +wire cs3 = cs && addr[4:3] == 2'd3; + +wire [7:0] dout0, dout1, dout2, dout3; + +assign dout = cs0 ? dout0 : cs1 ? dout1 : cs2 ? dout2 : dout3; + +wire [19:0] sample_addr[4]; +wire [15:0] sample_out0, sample_out1, sample_out2, sample_out3; +wire [3:0] sample_req; +reg [3:0] sample_ack; +reg [63:0] sample_data[4]; +reg [3:0] req_pending; + +ga20_channel ch0( .clk(clk), .reset(reset), .ce(ce & ce0), .cs(cs0), .rd(rd), .wr(wr), .addr(addr[2:0]), .din(din), .dout(dout0), .sample_addr(sample_addr[0]), .sample_req(sample_req[0]), .sample_ack(sample_ack[0]), .sample_din(sample_data[0]), .sample_out(sample_out0)); +ga20_channel ch1( .clk(clk), .reset(reset), .ce(ce & ce1), .cs(cs1), .rd(rd), .wr(wr), .addr(addr[2:0]), .din(din), .dout(dout1), .sample_addr(sample_addr[1]), .sample_req(sample_req[1]), .sample_ack(sample_ack[1]), .sample_din(sample_data[1]), .sample_out(sample_out1)); +ga20_channel ch2( .clk(clk), .reset(reset), .ce(ce & ce2), .cs(cs2), .rd(rd), .wr(wr), .addr(addr[2:0]), .din(din), .dout(dout2), .sample_addr(sample_addr[2]), .sample_req(sample_req[2]), .sample_ack(sample_ack[2]), .sample_din(sample_data[2]), .sample_out(sample_out2)); +ga20_channel ch3( .clk(clk), .reset(reset), .ce(ce & ce3), .cs(cs3), .rd(rd), .wr(wr), .addr(addr[2:0]), .din(din), .dout(dout3), .sample_addr(sample_addr[3]), .sample_req(sample_req[3]), .sample_ack(sample_ack[3]), .sample_din(sample_data[3]), .sample_out(sample_out3)); + +always_ff @(posedge clk, posedge reset) begin + if (reset) begin + sample_data[0] <= 0; + sample_data[1] <= 0; + sample_data[2] <= 0; + sample_data[3] <= 0; + req_pending <= 0; + end else begin + if (req_pending[0]) begin + if (sample_rom_req == sample_rom_ack) begin + req_pending[0] <= 0; + sample_ack[0] <= sample_req[0]; + sample_data[0] <= sample_rom_din; + end + end else if (req_pending[1]) begin + if (sample_rom_req == sample_rom_ack) begin + req_pending[1] <= 0; + sample_ack[1] <= sample_req[1]; + sample_data[1] <= sample_rom_din; + end + end else if (req_pending[2]) begin + if (sample_rom_req == sample_rom_ack) begin + req_pending[2] <= 0; + sample_ack[2] <= sample_req[2]; + sample_data[2] <= sample_rom_din; + end + end else if (req_pending[3]) begin + if (sample_rom_req == sample_rom_ack) begin + req_pending[3] <= 0; + sample_ack[3] <= sample_req[3]; + sample_data[3] <= sample_rom_din; + end + end else if (sample_req[0] != sample_ack[0]) begin + sample_rom_addr <= sample_addr[0]; + sample_rom_req <= ~sample_rom_req; + req_pending[0] <= 1; + end else if (sample_req[1] != sample_ack[1]) begin + sample_rom_addr <= sample_addr[1]; + sample_rom_req <= ~sample_rom_req; + req_pending[1] <= 1; + end else if (sample_req[2] != sample_ack[2]) begin + sample_rom_addr <= sample_addr[2]; + sample_rom_req <= ~sample_rom_req; + req_pending[2] <= 1; + end else if (sample_req[3] != sample_ack[3]) begin + sample_rom_addr <= sample_addr[3]; + sample_rom_req <= ~sample_rom_req; + req_pending[3] <= 1; + end + end +end + +always_ff @(posedge clk, posedge reset) begin + if (reset) begin + step <= 3'd0; + end else begin + reg prev_ce = 0; + prev_ce <= ce; + if (~ce & prev_ce) begin + step <= step + 3'd1; + end + end +end + +reg [15:0] sample_combined; + +// 9685hz 2nd order 10749hz 1st order +localparam CX = 0.00000741947949554119; +localparam CY0 = -2.95726738834813529522; +localparam CY1 = 2.91526970775390958934; +localparam CY2 = -0.95799698165074131939; +reg [15:0] sample_filtered; + +iir_filter #( + .use_params(1), + .stereo(0), + .coeff_x(CX), + .coeff_x0(3), + .coeff_x1(3), + .coeff_x2(1), + .coeff_y0(CY0), + .coeff_y1(CY1), + .coeff_y2(CY2)) lpf_sample ( + .clk(clk), + .reset(reset), + + .ce(ce), + .sample_ce(ce), + + .cx(), .cx0(), .cx1(), .cx2(), .cy0(), .cy1(), .cy2(), + + .input_l(sample_combined), + .output_l(sample_filtered), + + .input_r(), + .output_r() +); + +always_ff @(posedge clk) begin + sample_combined <= sample_out0 + sample_out1 + sample_out2 + sample_out3; +end + +assign sample_out = filter_en ? sample_filtered : sample_combined; + +endmodule diff --git a/rtl/ga21.sv b/rtl/ga21.sv new file mode 100644 index 0000000..5446914 --- /dev/null +++ b/rtl/ga21.sv @@ -0,0 +1,238 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module GA21( + input clk, + input ce, + + input reset, + + input [15:0] din, + output [15:0] dout, + + input [10:0] addr, + + input reg_cs, + input buf_cs, + input wr, + + output busy, + + output [15:0] obj_dout, + input [15:0] obj_din, + output [10:0] obj_addr, + output obj_we, + + output buffer_we, + output [10:0] buffer_addr, + output [15:0] buffer_dout, + input [15:0] buffer_din, + + input [9:0] count, + + output [12:0] pal_addr, + output [15:0] pal_dout, + input [15:0] pal_din, + output pal_we, + output pal_cs + + // TODO pal latching and OE signals? + +); + +reg [7:0] reg_direct_access; +reg [7:0] reg_obj_ptr; +reg [15:0] reg_copy_mode; + +wire [2:0] pal_addr_high = reg_copy_mode[10:8]; +wire layer_ordered_copy = reg_copy_mode[0]; +wire full_copy = reg_copy_mode[7] & ~reg_copy_mode[0]; + +reg obj_addr_high = 0; + +enum { + IDLE, + IDLE_DELAY, + INIT_COPY_PAL, + COPY_PAL, + INIT_CLEAR_OBJ, + CLEAR_OBJ, + INIT_COPY_OBJ, + COPY_OBJ +} copy_state = IDLE; + + +reg [10:0] copy_counter; +reg [15:0] copy_dout; +reg [10:0] copy_obj_addr; +reg [9:0] copy_pal_addr; +reg [2:0] copy_obj_word; +reg [8:0] copy_obj_idx; +reg [10:0] buffer_src_addr; +reg [10:0] next_buffer_src_addr; +reg [2:0] copy_layer; +reg copy_this_obj; + +reg copy_obj_we, copy_pal_we; + +wire direct_access_pal = reg_direct_access[1]; +wire direct_access_obj = reg_direct_access[0]; + +always_ff @(posedge clk or posedge reset) begin + bit [8:0] obj_y; + bit [1:0] obj_height; + bit [1:0] obj_log2_cols; + bit [2:0] obj_layer; + bit [3:0] obj_cols; + bit [8:0] next_obj_idx; + + if (reset) begin + copy_state <= IDLE; + reg_direct_access <= 0; + reg_obj_ptr <= 0; + reg_copy_mode <= 0; + + copy_obj_we <= 0; + copy_pal_we <= 0; + end else begin + if (reg_cs & wr) begin + if (addr == 11'h0) reg_obj_ptr <= din[7:0]; + if (addr == 11'h1) reg_direct_access <= din[7:0]; + if (addr == 11'h2) reg_copy_mode <= din[15:0]; + if (addr == 11'h4) begin + copy_state <= INIT_COPY_PAL; + end + end + + if (ce) begin + copy_obj_we <= 0; + copy_pal_we <= 0; + + case(copy_state) + IDLE_DELAY: copy_state <= IDLE; + IDLE: begin + end + INIT_COPY_PAL: begin + buffer_src_addr <= 11'h400; + copy_pal_addr <= ~10'd0; + copy_state <= COPY_PAL; + end + COPY_PAL: begin + if (buffer_src_addr == 11'h000) begin + copy_state <= INIT_CLEAR_OBJ; + end else begin + buffer_src_addr <= buffer_src_addr + 11'd1; + copy_pal_addr <= copy_pal_addr + 10'd1; + copy_dout <= buffer_din; + copy_pal_we <= 1; + end + end + INIT_CLEAR_OBJ: begin + copy_dout <= 16'd0; + copy_obj_addr <= 11'd0; + copy_obj_we <= 1; + copy_state <= CLEAR_OBJ; + end + CLEAR_OBJ: begin + copy_obj_addr <= copy_obj_addr + 11'd1; + copy_obj_we <= 1; + if (©_obj_addr) begin + copy_state <= INIT_COPY_OBJ; + end + end + INIT_COPY_OBJ: begin + copy_state <= COPY_OBJ; + copy_this_obj <= 0; + buffer_src_addr <= 11'd0; + copy_obj_word <= 2'd0; + copy_layer <= 3'd0; + copy_obj_idx <= 9'h100 - {1'b0, reg_obj_ptr}; + end + COPY_OBJ: begin + copy_dout <= buffer_din; + buffer_src_addr <= buffer_src_addr + 11'd1; + copy_obj_word <= copy_obj_word + 2'd1; + copy_obj_addr <= {1'b0, copy_obj_idx[7:0], copy_obj_word[1:0]}; + copy_obj_we <= copy_this_obj; + + if (buffer_src_addr[1:0] == 2'b00) begin + if (copy_obj_idx == 9'd0) begin + copy_state <= IDLE; + copy_obj_we <= 0; + end else begin + obj_y = buffer_din[8:0]; + obj_height = buffer_din[10:9]; + obj_log2_cols = buffer_din[12:11]; + obj_layer = buffer_din[15:13]; + obj_cols = 4'd1 << obj_log2_cols; + + if (full_copy || (layer_ordered_copy == 0 && obj_layer != 3'd7) || (obj_layer == copy_layer)) begin + copy_this_obj <= 1; + copy_obj_we <= 1; + + next_obj_idx = copy_obj_idx - obj_cols; + if (next_obj_idx[8]) begin // wrapped around + copy_state <= IDLE; + copy_obj_we <= 0; + end else begin + copy_obj_addr <= {1'b0, next_obj_idx, copy_obj_word[1:0]}; + copy_obj_idx <= next_obj_idx; + end + end else begin + copy_this_obj <= 0; + copy_obj_we <= 0; + end + + next_buffer_src_addr <= buffer_src_addr + { obj_cols, 2'b00 }; + end + end else if (buffer_src_addr[1:0] == 2'b11) begin + if (next_buffer_src_addr[10]) begin // end of input + if (layer_ordered_copy && (copy_layer != 3'd6)) begin + copy_layer <= copy_layer + 3'd1; + buffer_src_addr <= 11'd0; + end else begin + copy_state <= IDLE_DELAY; // delay for one cycle so final write can complete + end + end else begin + buffer_src_addr <= next_buffer_src_addr; + end + end + end + endcase + end + end +end + +assign dout = buf_cs ? (direct_access_obj ? obj_din : (direct_access_pal ? pal_din : buffer_din)) : 16'd0; +assign busy = copy_state != IDLE; + +assign buffer_we = ~busy & buf_cs & wr; +assign buffer_addr = busy ? buffer_src_addr : addr; + +assign buffer_dout = din; + +assign obj_dout = direct_access_obj ? din : copy_dout; +assign obj_addr = direct_access_obj ? addr : (busy ? copy_obj_addr : {obj_addr_high, count}); +assign obj_we = direct_access_obj ? (buf_cs & wr) : (busy ? copy_obj_we : 1'b0); + +assign pal_dout = direct_access_pal ? din : copy_dout; +assign pal_addr = {pal_addr_high, direct_access_pal ? addr[9:0] : (busy ? copy_pal_addr : 10'd0)}; +assign pal_we = direct_access_pal ? (buf_cs & wr) : (busy ? copy_pal_we : 1'b0); +assign pal_cs = direct_access_pal ? buf_cs : 1'b0; + +endmodule \ No newline at end of file diff --git a/rtl/ga21_tb.sv b/rtl/ga21_tb.sv new file mode 100644 index 0000000..f75494a --- /dev/null +++ b/rtl/ga21_tb.sv @@ -0,0 +1,39 @@ +module ga21_tb; + +reg clk; +reg buf_cs; +reg [10:0] addr; +reg reg_cs; +reg reset; +reg wr; + +GA21 ga21( .clk(clk), .ce(1), .reset(reset), .buf_cs(0), .wr(wr), .reg_cs(reg_cs), .addr(addr)); + +always begin + clk = 1'b1; + #1; + clk = 1'b0; + #1; +end + +initial begin + reset = 1; + buf_cs = 0; + reg_cs = 0; + wr = 0; + #5; + reset = 0; + #5; + + addr = 'h9008 >> 1; + reg_cs = 1; + wr = 1; + #2; + + reg_cs = 0; + wr = 0; + #1000000; + $stop; +end + +endmodule \ No newline at end of file diff --git a/rtl/ga22.sv b/rtl/ga22.sv new file mode 100644 index 0000000..7132b4b --- /dev/null +++ b/rtl/ga22.sv @@ -0,0 +1,173 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +import m92_pkg::*; + +module GA22 ( + input clk, + + input ce, // 13.33Mhz + + input ce_pix, // 6.66Mhz + + input reset, + + output reg [11:0] color, + + input NL, + input hpulse, + input vpulse, + + output reg [9:0] count, + + input [63:0] obj_in, + + input [63:0] sdr_data, + output reg [24:0] sdr_addr, + output reg sdr_req, + input sdr_ack, + output reg sdr_refresh, + + input dbg_solid_sprites +); + +reg [6:0] linebuf_color; +reg linebuf_prio; +reg [9:0] linebuf_x; +reg linebuf_write; +reg linebuf_flip; +reg scan_toggle = 0; +reg [9:0] scan_pos = 0; +wire [9:0] scan_pos_nl = scan_pos ^ {1'b0, {9{NL}}}; +wire [11:0] scan_out; + +double_linebuf line_buffer( + .clk(clk), + .ce_pix(ce_pix), + + .scan_pos(scan_pos_nl), + .scan_toggle(scan_toggle), + .scan_out(scan_out), + + .bitplanes(dbg_solid_sprites ? 64'hffff_ffff_ffff_ffff : sdr_data), + .flip(linebuf_flip), + .color(linebuf_color), + .prio(linebuf_prio), + .pos(linebuf_x), + .we(linebuf_write), + + .idle() +); + +reg [63:0] obj_data; + +wire [8:0] obj_org_y = obj_data[8:0]; +wire [1:0] obj_height = obj_data[10:9]; +wire [1:0] obj_width = obj_data[12:11]; +wire [2:0] obj_layer = obj_data[15:13]; +wire [15:0] obj_code = obj_data[31:16]; +wire [6:0] obj_color = obj_data[38:32]; +wire obj_pri = obj_data[39]; +wire obj_flipx = obj_data[40]; +wire obj_flipy = obj_data[41]; +wire [9:0] obj_org_x = obj_data[57:48]; + +reg [8:0] V; +wire [8:0] VE = V ^ {9{NL}}; + +always_ff @(posedge clk) begin + reg visible; + reg [3:0] span; + reg [3:0] end_span; + + reg [15:0] code; + reg [8:0] height_px; + reg [3:0] width; + reg [8:0] rel_y; + reg [8:0] row_y; + + linebuf_write <= 0; + + if (reset) begin + V <= 9'd0; + end else if (ce) begin + count <= count + 10'd1; + + sdr_refresh <= 0; + + if (ce_pix) begin + color <= scan_out[11:0]; + scan_pos <= scan_pos + 10'd1; + if (hpulse) begin + count <= 10'd0; + V <= V + 9'd1; + scan_pos <= 10'd44; + scan_toggle <= ~scan_toggle; + span <= 0; + end_span <= 0; + visible <= 0; + sdr_refresh <= 1; + end + end + + if (vpulse) begin + V <= 9'd126; + end + case(count[1:0]) + 0: begin + linebuf_flip <= obj_flipx; + linebuf_color <= obj_color; + linebuf_prio <= obj_pri; + linebuf_x <= obj_org_x + ( 10'd16 * span ); + linebuf_write <= visible; + if (span == end_span) begin + span <= 4'd0; + obj_data <= obj_in; + end else begin + span <= span + 4'd1; + end + end + 1: begin + end_span <= ( 4'd1 << obj_width ) - 1'd1; + height_px = 9'd16 << obj_height; + width = 4'd1 << obj_width; + rel_y = VE + obj_org_y + ( 9'd16 << obj_height ); + row_y = obj_flipy ? (height_px - rel_y - 9'd1) : rel_y; + + if (rel_y < height_px) begin + code = obj_code + row_y[8:4] + ( ( obj_flipx ? ( width - span - 16'd1 ) : span ) * 16'd8 ); + sdr_addr <= REGION_SPRITE.base_addr[24:0] + { code[15:0], row_y[3:0], 3'b000 }; + sdr_req <= ~sdr_req; + visible <= 1; + end else begin + visible <= 0; + sdr_refresh <= 1; + end + end + 2: begin + sdr_refresh <= 1; + end + 3: begin + sdr_refresh <= 0; + end + endcase + end + +end + +endmodule \ No newline at end of file diff --git a/rtl/ga22_linebuffer.sv b/rtl/ga22_linebuffer.sv new file mode 100644 index 0000000..7917db7 --- /dev/null +++ b/rtl/ga22_linebuffer.sv @@ -0,0 +1,191 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module linebuf( + input clk, + + input ce_pix, + + input [9:0] scan_pos, + input scan_active, + output [11:0] scan_out, + + input [11:0] color0, + input [11:0] color1, + input [9:0] draw_pos, + input draw_we +); + +wire [11:0] scan_odd, scan_even; +assign scan_out = scan_pos[0] ? scan_odd : scan_even; + +wire [11:0] odd_color = draw_pos[0] ? color0 : color1; +wire [11:0] even_color = draw_pos[0] ? color1 : color0; +wire [8:0] odd_addr = draw_pos[9:1]; +wire [8:0] even_addr = draw_pos[0] ? draw_pos[9:1] + 9'd1 : draw_pos[9:1]; + +dualport_ram #(.widthad(9), .width(12)) buffer_odd +( + .clock_a(clk), + .address_a(scan_pos[9:1]), + .q_a(scan_odd), + .wren_a(scan_active & ce_pix & scan_pos[0]), + .data_a(12'd0), + + .clock_b(clk), + .address_b(odd_addr), + .data_b(odd_color), + .wren_b((~scan_active) & draw_we & |odd_color[3:0]), + .q_b() +); + +dualport_ram #(.widthad(9), .width(12)) buffer_even +( + .clock_a(clk), + .address_a(scan_pos[9:1]), + .q_a(scan_even), + .wren_a(scan_active & ce_pix & ~scan_pos[0]), + .data_a(12'd0), + + .clock_b(clk), + .address_b(even_addr), + .data_b(even_color), + .wren_b((~scan_active) & draw_we & |even_color[3:0]), + .q_b() +); + +endmodule + + +module double_linebuf( + input clk, + + input ce_pix, + + input [9:0] scan_pos, + input scan_toggle, + output [11:0] scan_out, + + input [63:0] bitplanes, + input flip, + input [6:0] color, + input prio, + input [9:0] pos, + input we, + + output idle +); + +wire [11:0] scan_out_0, scan_out_1; +assign scan_out = scan_toggle ? scan_out_0 : scan_out_1; + +reg [11:0] color0; +reg [11:0] color1; +reg [9:0] draw_pos; +reg draw_we = 0; + +linebuf buf_0( + .clk(clk), + .ce_pix(ce_pix), + + .scan_active(scan_toggle), + .scan_out(scan_out_0), + .scan_pos(scan_pos), + + .color0(color0), + .color1(color1), + .draw_pos(draw_pos), + .draw_we(draw_we) +); + +linebuf buf_1( + .clk(clk), + .ce_pix(ce_pix), + + .scan_active(~scan_toggle), + .scan_out(scan_out_1), + .scan_pos(scan_pos), + + .color0(color0), + .color1(color1), + .draw_pos(draw_pos), + .draw_we(draw_we) +); + +// d is 16 pixels stored as 2 sets of 4 bitplanes +// d[31:0] is 8 pixels, made up from planes d[7:0], d[15:8], etc +// d[63:32] is 8 pixels made up from planes d[39:32], d[47:40], etc +// Returns 16 pixels stored as 4 bit planes d[15:0], d[31:16], etc +function [63:0] deswizzle(input [63:0] d, input rev); + begin + integer i; + bit [7:0] plane[8]; + bit [7:0] t; + for( i = 0; i < 8; i = i + 1 ) begin + t = d[(i*8) +: 8]; + plane[i] = rev ? { t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7] } : t; + end + + deswizzle[15:0] = rev ? { plane[4], plane[0] } : { plane[0], plane[4] }; + deswizzle[31:16] = rev ? { plane[5], plane[1] } : { plane[1], plane[5] }; + deswizzle[47:32] = rev ? { plane[6], plane[2] } : { plane[2], plane[6] }; + deswizzle[63:48] = rev ? { plane[7], plane[3] } : { plane[3], plane[7] }; + end +endfunction + +reg [3:0] count = 0; +assign idle = count == 4'd0; + +always_ff @(posedge clk) begin + reg [63:0] bits_r; + bit [63:0] bits; + reg [6:0] color_r; + reg prio_r; + + draw_we <= 0; + + if (count != 4'd0) begin + color0 <= { prio_r, color_r, bits_r[63], bits_r[47], bits_r[31], bits_r[15] }; + color1 <= { prio_r, color_r, bits_r[62], bits_r[46], bits_r[30], bits_r[14] }; + draw_pos <= draw_pos + 10'd2; + draw_we <= 1; + + bits_r <= { bits_r[61:0], 2'b00 }; + + count <= count - 4'd1; + end + + if (we) begin + bits = deswizzle(bitplanes, flip); + + color0 <= { prio, color, bits[63], bits[47], bits[31], bits[15] }; + color1 <= { prio, color, bits[62], bits[46], bits[30], bits[14] }; + draw_we <= 1; + draw_pos <= pos; + + bits_r <= { bits[61:0], 2'b00 }; + color_r <= color; + prio_r <= prio; + + count <= 4'd7; + end +end + +endmodule + + diff --git a/rtl/ga23.sv b/rtl/ga23.sv new file mode 100644 index 0000000..dd8fc59 --- /dev/null +++ b/rtl/ga23.sv @@ -0,0 +1,318 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module GA23( + input clk, + + input ce, + + input paused, + + input reset, + + input io_wr, + input [15:0] addr, + input [15:0] cpu_din, + + output reg [14:0] vram_addr, + output reg vram_req, + input [31:0] vram_din, + + input NL, + + input large_tileset, + + input [31:0] sdr_data_a, + output [24:0] sdr_addr_a, + output sdr_req_a, + input sdr_ack_a, + + input [31:0] sdr_data_b, + output [24:0] sdr_addr_b, + output sdr_req_b, + input sdr_ack_b, + + input [31:0] sdr_data_c, + output [24:0] sdr_addr_c, + output sdr_req_c, + input sdr_ack_c, + + output vblank, + output vsync, + output hblank, + output hsync, + + output hpulse, + output vpulse, + + output hint, + + output reg [10:0] color_out, + output reg prio_out, + + input [2:0] dbg_en_layers +); + + +//// VIDEO TIMING +reg [9:0] hcnt, vcnt; +reg [9:0] hint_line; + +assign hsync = hcnt < 10'd71 || hcnt > 10'd454; +assign hblank = hcnt < 10'd104 || hcnt > 10'd424; +assign vblank = vcnt > 10'd113 && vcnt < 10'd136; +assign vsync = vcnt > 10'd119 && vcnt < 10'd125; +assign hpulse = hcnt == 10'd48; +assign vpulse = (vcnt == 10'd124 && hcnt > 10'd260) || (vcnt == 10'd125 && hcnt < 10'd260); + +wire [9:0] VE = vcnt ^ {1'b0, {9{NL}}}; + +assign hint = VE == hint_line && hcnt > 10'd424 && ~paused; + + +always_ff @(posedge clk) begin + if (ce) begin + hcnt <= hcnt + 10'd1; + if (hcnt == 10'd471) begin + hcnt <= 10'd48; + vcnt <= vcnt + 10'd1; + if (vcnt == 10'd375) begin + vcnt <= 10'd114; + end + end + end +end + +wire [21:0] rom_addr[3]; +wire [31:0] rom_data[3]; +wire rom_req[3]; +wire rom_ack[3]; + +//// MEMORY ACCESS +reg [2:0] mem_cyc; +reg [3:0] rs_cyc; + +reg [9:0] x_ofs[3], y_ofs[3]; +reg [7:0] control[3]; +reg [9:0] rowscroll[3]; + +wire [14:0] layer_vram_addr[3]; +reg layer_load[3]; +wire layer_prio[3]; +wire [10:0] layer_color[3]; +reg [15:0] vram_latch; + +reg [37:0] control_save_0[512]; +reg [37:0] control_save_1[512]; +reg [37:0] control_save_2[512]; + +reg [37:0] control_restore[3]; + +reg rowscroll_active, rowscroll_pending; + +always_ff @(posedge clk, posedge reset) begin + bit [9:0] rs_y; + if (reset) begin + mem_cyc <= 0; + + // layer regs + x_ofs[0] <= 10'd0; x_ofs[1] <= 10'd0; x_ofs[2] <= 10'd0; + y_ofs[0] <= 10'd0; y_ofs[1] <= 10'd0; y_ofs[2] <= 10'd0; + control[0] <= 8'd0; control[1] <= 8'd0; control[2] <= 8'd0; + hint_line <= 10'd0; + + rowscroll_pending <= 0; + rowscroll_active <= 0; + + end else begin + + if (ce) begin + layer_load[0] <= 0; layer_load[1] <= 0; layer_load[2] <= 0; + mem_cyc <= mem_cyc + 3'd1; + + if (hpulse) begin + mem_cyc <= 3'd7; + rowscroll_pending <= 1; + end + + if (rowscroll_active) begin + rs_cyc <= rs_cyc + 4'd1; + case(rs_cyc) + 0: vram_addr <= 'h7800; + 4: begin + rs_y = y_ofs[0] + VE; + vram_addr <= 'h7a00 + rs_y[8:0]; + vram_req <= ~vram_req; + end + 7: rowscroll[0] <= vram_din[9:0]; + 8: begin + rs_y = y_ofs[1] + VE; + vram_addr <= 'h7c00 + rs_y[8:0]; + vram_req <= ~vram_req; + end + 10: rowscroll[1] <= vram_din[9:0]; + 12: begin + rs_y = y_ofs[2] + VE; + vram_addr <= 'h7e00 + rs_y[8:0]; + vram_req <= ~vram_req; + end + 14: rowscroll[2] <= vram_din[9:0]; + 15: rowscroll_active <= 0; + endcase + + end else begin + + case(mem_cyc) + 3'd0: begin + vram_addr <= layer_vram_addr[0]; + vram_req <= ~vram_req; + end + 3'd1: begin + layer_load[0] <= 1; // would be better a bit later + end + 3'd2: begin + vram_addr <= layer_vram_addr[1]; + vram_req <= ~vram_req; + end + 3'd4: begin + layer_load[1] <= 1; + end + 3'd5: begin + vram_addr <= layer_vram_addr[2]; + vram_req <= ~vram_req; + end + 3'd7: begin + layer_load[2] <= 1; + + if (rowscroll_pending) begin + rowscroll_pending <= 0; + rowscroll_active <= 1; + rs_cyc <= 4'd0; + end + end + endcase + end + + prio_out <= layer_prio[0] | layer_prio[1] | layer_prio[2]; + if (|layer_color[0][3:0]) begin + color_out <= layer_color[0]; + end else if (|layer_color[1][3:0]) begin + color_out <= layer_color[1]; + end else begin + color_out <= layer_color[2]; + end + end + + if (io_wr) begin + case(addr[7:0]) + 'h80: y_ofs[0][7:0] <= cpu_din[7:0]; + 'h81: y_ofs[0][9:8] <= cpu_din[1:0]; + 'h84: x_ofs[0][7:0] <= cpu_din[7:0]; + 'h85: x_ofs[0][9:8] <= cpu_din[1:0]; + + 'h88: y_ofs[1][7:0] <= cpu_din[7:0]; + 'h89: y_ofs[1][9:8] <= cpu_din[1:0]; + 'h8c: x_ofs[1][7:0] <= cpu_din[7:0]; + 'h8d: x_ofs[1][9:8] <= cpu_din[1:0]; + + 'h90: y_ofs[2][7:0] <= cpu_din[7:0]; + 'h91: y_ofs[2][9:8] <= cpu_din[1:0]; + 'h94: x_ofs[2][7:0] <= cpu_din[7:0]; + 'h95: x_ofs[2][9:8] <= cpu_din[1:0]; + + 'h98: control[0] <= cpu_din[7:0]; + 'h9a: control[1] <= cpu_din[7:0]; + 'h9c: control[2] <= cpu_din[7:0]; + + 'h9e: hint_line[7:0] <= cpu_din[7:0]; + 'h9f: hint_line[9:8] <= cpu_din[1:0]; + endcase + end +`ifdef CTRL_SAVE + if (hcnt == 10'd104 && ~paused) begin // end of hblank + control_save_0[vcnt] <= { y_ofs[0], x_ofs[0], control[0], rowscroll[0] }; + control_save_1[vcnt] <= { y_ofs[1], x_ofs[1], control[1], rowscroll[1] }; + control_save_2[vcnt] <= { y_ofs[2], x_ofs[2], control[2], rowscroll[2] }; + end else if (paused) begin + control_restore[0] <= control_save_0[vcnt]; + control_restore[1] <= control_save_1[vcnt]; + control_restore[2] <= control_save_2[vcnt]; + end +`endif + end +end + + +assign rom_data[0] = sdr_data_a; +assign sdr_addr_a = REGION_TILE.base_addr[24:0] | rom_addr[0]; +assign sdr_req_a = rom_req[0]; +assign rom_ack[0] = sdr_ack_a; + +assign rom_data[1] = sdr_data_b; +assign sdr_addr_b = REGION_TILE.base_addr[24:0] | rom_addr[1]; +assign sdr_req_b = rom_req[1]; +assign rom_ack[1] = sdr_ack_b; + +assign rom_data[2] = sdr_data_c; +assign sdr_addr_c = REGION_TILE.base_addr[24:0] | rom_addr[2]; +assign sdr_req_c = rom_req[2]; +assign rom_ack[2] = sdr_ack_c; + +//// LAYERS +generate + genvar i; + for(i = 0; i < 3; i = i + 1 ) begin : generate_layer + wire [9:0] _y_ofs = paused ? control_restore[i][37:28] : y_ofs[i]; + wire [9:0] _x_ofs = paused ? control_restore[i][27:18] : x_ofs[i]; + wire [7:0] _control = paused ? control_restore[i][17:10] : control[i]; + wire [9:0] _rowscroll = paused ? control_restore[i][9:0] : rowscroll[i]; + + ga23_layer layer( + .clk(clk), + .ce_pix(ce), + + .NL(NL), + .large_tileset(large_tileset), + + .x_ofs(_x_ofs), + .y_ofs(_y_ofs), + .control(_control), + + .x_base({hcnt[9:3] ^ {7{NL}}, 3'd0}), + .y(_y_ofs + VE), + .rowscroll(_rowscroll), + + .vram_addr(layer_vram_addr[i]), + + .load(layer_load[i]), + .attrib(vram_din[31:16]), + .index(vram_din[15:0]), + + .color_out(layer_color[i]), + .prio_out(layer_prio[i]), + + .sdr_addr(rom_addr[i]), + .sdr_data(rom_data[i]), + .sdr_req(rom_req[i]), + .sdr_ack(rom_ack[i]), + + .dbg_enabled(dbg_en_layers[i]) + ); + end +endgenerate +endmodule diff --git a/rtl/ga23_layer.sv b/rtl/ga23_layer.sv new file mode 100644 index 0000000..71f4a1e --- /dev/null +++ b/rtl/ga23_layer.sv @@ -0,0 +1,112 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module ga23_layer( + input clk, + input ce_pix, + + input NL, + + input large_tileset, + + // io registers + input [9:0] x_ofs, + input [9:0] y_ofs, + input [7:0] control, + + // position + input [9:0] x_base, + input [9:0] y, + input [9:0] rowscroll, + + // vram address for current tile + output [14:0] vram_addr, + + // + input load, + input [15:0] attrib, + input [15:0] index, + + output prio_out, + output [10:0] color_out, + + input [31:0] sdr_data, + output reg [21:0] sdr_addr, + output reg sdr_req, + input sdr_ack, + + input dbg_enabled +); + +wire [14:0] vram_base = { control[1:0], 13'd0 }; +wire wide = control[2]; +wire enabled = ~control[4] & dbg_enabled; +wire en_rowscroll = control[6]; +wire [9:0] x = x_base + ( en_rowscroll ? rowscroll : x_ofs ); +wire [6:0] tile_x = NL ? ( x[9:3] - ( wide ? 7'd32 : 7'd0) ) : ( x[9:3] + ( wide ? 7'd32 : 7'd0) ); +wire [5:0] tile_y = y[8:3]; + +assign vram_addr = wide ? {vram_base[14], tile_y, tile_x[6:0], 1'b0} : {vram_base[14:13], tile_y, tile_x[5:0], 1'b0}; + +reg [3:0] cnt; + +reg [1:0] prio; +reg [6:0] palette; +reg flip_x; +wire flip_y = attrib[10]; +reg [2:0] offset; + +always_ff @(posedge clk) begin + + if (ce_pix) begin + cnt <= cnt + 4'd1; + if (load & dbg_enabled) begin + cnt <= 4'd0; + sdr_addr <= { (large_tileset ? attrib[15] : 1'b0), index, flip_y ? ~y[2:0] : y[2:0], 2'b00 }; + sdr_req <= ~sdr_req; + palette <= attrib[6:0]; + prio <= attrib[8:7]; + flip_x <= attrib[9] ^ NL; + offset <= x[2:0] ^ {3{NL}}; + end + end +end + +wire [1:0] shift_prio_out; +wire [10:0] shift_color_out; + +ga23_shifter shifter( + .clk(clk), + .ce_pix(ce_pix), + + .offset(offset), + + .load(load), + .reverse(flip_x), + .row(sdr_data), + .palette(palette), + .prio(prio), + + .color_out(shift_color_out), + .prio_out(shift_prio_out) +); + +assign color_out = enabled ? shift_color_out : 11'd0; +assign prio_out = enabled ? ( ( shift_prio_out[0] & shift_color_out[3] ) | ( shift_prio_out[1] & |shift_color_out[3:0] ) ) : 1'b0; + +endmodule \ No newline at end of file diff --git a/rtl/ga23_shifter.sv b/rtl/ga23_shifter.sv new file mode 100644 index 0000000..b5910e5 --- /dev/null +++ b/rtl/ga23_shifter.sv @@ -0,0 +1,70 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module ga23_shifter( + input clk, + input ce_pix, + + input [2:0] offset, + + input load, + input reverse, + input [31:0] row, + input [6:0] palette, + input [1:0] prio, + + output [10:0] color_out, + output [1:0] prio_out +); + +reg [2:0] cnt; +reg [31:0] pix_next, pix_cur; +reg [6:0] pal_next, pal_cur; +reg [1:0] prio_next, prio_cur; +wire [2:0] flip_cnt = cnt + offset; + +always_ff @(posedge clk) begin + if (ce_pix) begin + pix_cur[27:0] <= pix_cur[31:4]; + cnt <= cnt + 3'd1; + + if (&flip_cnt) begin + pix_cur <= pix_next; + prio_cur <= prio_next; + pal_cur <= pal_next; + end + + if (load) begin + integer i; + for( i = 0; i < 8; i = i + 1 ) begin + pix_next[(i * 4) + 3] = reverse ? row[24 + i] : row[31 - i]; + pix_next[(i * 4) + 2] = reverse ? row[16 + i] : row[23 - i]; + pix_next[(i * 4) + 1] = reverse ? row[ 8 + i] : row[15 - i]; + pix_next[(i * 4) + 0] = reverse ? row[ 0 + i] : row[ 7 - i]; + end + pal_next <= palette; + prio_next <= prio; + cnt <= 0; + end + end +end + +assign prio_out = prio_cur; +assign color_out = { pal_cur, pix_cur[3:0] }; + +endmodule \ No newline at end of file diff --git a/rtl/index.qip b/rtl/index.qip new file mode 100644 index 0000000..5f255d4 --- /dev/null +++ b/rtl/index.qip @@ -0,0 +1,31 @@ +# ============================================================================== +# RTL +# ============================================================================== +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "irem_m92.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "eeprom.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "v35.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "sound.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "sdram_4w_cl3.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "rom.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "palram.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "pal.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "objram.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "m92_pkg.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "m92_pic.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "m92.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ga23_shifter.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ga23_layer.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ga23.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ga22_linebuffer.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ga22.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ga21.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ga20.sv"] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "dpramv.sv"] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "jtframe_frac_cen.v"] +#set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "iir_filter.v"] + +# ============================================================================== +# MODULES +# ============================================================================== +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "../modules/cpu-v30/index.qip"] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "../modules/sound-jt51/index.qip"] diff --git a/rtl/irem_m92.sv b/rtl/irem_m92.sv new file mode 100644 index 0000000..e426348 --- /dev/null +++ b/rtl/irem_m92.sv @@ -0,0 +1,405 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2024, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Irem M92 Compatible Gateware IP Core +// +// Copyright (c) 2024, Marcus Andrade +// Copyright (c) 2023, Martin Donlon +// +// 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, version 3. +// +// 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 . +// +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +import m92_pkg::*; + +module irem_m92 + ( + input wire clk_sys, //! System Clock ( 40 MHz) + input wire clk_ram, //! SDRAM Clock (120 MHz) + input wire pll_locked, //! PLL Locked + input wire reset, //! Reset + // Core Config + input wire pause, //! Pause CPU + input wire [7:0] mod_sw, //! DIP Switch 1 (Default: 8'h00) + input wire [7:0] dsw_1, //! DIP Switch 1 (Default: 8'h00) + input wire [7:0] dsw_2, //! DIP Switch 2 (Default: 8'h00) + input wire [7:0] dsw_3, //! DIP Switch 3 (Default: 8'h00) + // Input - Player 1 + input wire p1_coin, p1_start, //! Mode / Start + input wire p1_up, p1_left, //! Up / Left + input wire p1_down, p1_right, //! Down / Right + input wire p1_btn_y, p1_btn_x, //! Btn Y / X + input wire p1_btn_b, p1_btn_a, //! Btn B / A + input wire p1_btn_l, p1_btn_r, //! Btn L / R + // Input - Player 2 + input wire p2_coin, p2_start, //! Mode / Start + input wire p2_up, p2_left, //! Up / Left + input wire p2_down, p2_right, //! Down / Right + input wire p2_btn_y, p2_btn_x, //! Btn Y / X + input wire p2_btn_b, p2_btn_a, //! Btn B / A + input wire p2_btn_l, p2_btn_r, //! Btn L / R + // Input - Player 3 + input wire p3_coin, p3_start, //! Mode / Start + input wire p3_up, p3_left, //! Up / Left + input wire p3_down, p3_right, //! Down / Right + input wire p3_btn_y, p3_btn_x, //! Btn Y / X + input wire p3_btn_b, p3_btn_a, //! Btn B / A + input wire p3_btn_l, p3_btn_r, //! Btn L / R + // Input - Player 4 + input wire p4_coin, p4_start, //! Mode / Start + input wire p4_up, p4_left, //! Up / Left + input wire p4_down, p4_right, //! Down / Right + input wire p4_btn_y, p4_btn_x, //! Btn Y / X + input wire p4_btn_b, p4_btn_a, //! Btn B / A + input wire p4_btn_l, p4_btn_r, //! Btn L / R + // Audio + output wire [15:0] audio_l, //! Left Channel Output + output wire [15:0] audio_r, //! Right Channel Output + // Video Signals + output wire [7:0] video_r, //! Red + output wire [7:0] video_g, //! Green + output wire [7:0] video_b, //! Blue + output wire video_hs, //! Horizontal Sync + output wire video_vs, //! Vertical Sync + output wire video_hb, //! Horizontal Blank + output wire video_vb, //! Vertical Blank + output wire video_ce, //! Pixel Clock Enable (6.666 MHz) + output reg [2:0] video_preset, //! Video Preset [0] 320x240 | [1] 320x240 @ 270Deg + // I/O Controller + input wire [16:0] ioctl_index, //! Data Index + input wire ioctl_download, //! Download + input wire ioctl_wr, //! Write Enable + input wire [26:0] ioctl_addr, //! Data Address + input wire [15:0] ioctl_data, //! Data Input + // SDRAM Interface + output wire sdram_clk, //! Clock + output wire sdram_cke, //! Clock Enable + inout wire [15:0] sdram_dq, //! 16-bit Bidirectional Data Bus + output wire [12:0] sdram_a, //! 13-bit Multiplexed Address Bus + output wire sdram_dqml, //! Two Byte Masks + output wire sdram_dqmh, //! Two Byte Masks + output wire [1:0] sdram_ba, //! Two Banks + output wire sdram_we_n, //! Write Enable + output wire sdram_ras_n, //! Row Address Select + output wire sdram_cas_n //! Columns Address Select + ); + + //-------------------------------------------------------------------------- + // Settings + //-------------------------------------------------------------------------- + parameter [15:0] ROM_IDX = 16'd1, + HSDAT_IDX = 16'd2, + NVRAM_IDX = 16'd3; + + wire flipped; + wire [2:0] dbg_en_layers = 3'b111; + wire dbg_fm_en = 1'b1; + wire dbg_sprite_freeze = 1'b0; + wire filters = ~mod_sw[1]; + + assign video_preset = {2'b00, mod_sw[0]}; + //-------------------------------------------------------------------------- + // Inputs + //-------------------------------------------------------------------------- + wire [9:0] p1_input = { p1_btn_r, p1_btn_l, p1_btn_y, p1_btn_x, p1_btn_b, p1_btn_a, p1_up, p1_down, p1_left, p1_right }; + wire [9:0] p2_input = { p2_btn_r, p2_btn_l, p2_btn_y, p2_btn_x, p2_btn_b, p2_btn_a, p2_up, p2_down, p2_left, p2_right }; + wire [9:0] p3_input = { p3_btn_r, p3_btn_l, p3_btn_y, p3_btn_x, p3_btn_b, p3_btn_a, p3_up, p3_down, p3_left, p3_right }; + wire [9:0] p4_input = { p4_btn_r, p4_btn_l, p4_btn_y, p4_btn_x, p4_btn_b, p4_btn_a, p4_up, p4_down, p4_left, p4_right }; + + wire [3:0] coin_buttons = { p4_coin, p3_coin, p2_coin, p1_coin }; + wire [3:0] start_buttons = { p4_start, p3_start, p2_start, p1_start }; + wire [23:0] dip_sw = { dsw_3, dsw_2, dsw_1 }; + + //-------------------------------------------------------------------------- + // Core RTL + //-------------------------------------------------------------------------- + m92 #(.NVRAM_IDX(NVRAM_IDX)) m92 + ( + .clk_sys ( clk_sys ), // [i] + .reset_n ( ~reset ), // [i] + + .ce_pix ( video_ce ), // [o] + .flipped ( flipped ), // [o] + + .board_cfg ( board_cfg ), // [i] + + .R ( video_r ), // [o] + .G ( video_g ), // [o] + .B ( video_b ), // [o] + .HSync ( video_hs ), // [o] + .VSync ( video_vs ), // [o] + .HBlank ( video_hb ), // [o] + .VBlank ( video_vb ), // [o] + + .AUDIO_L ( audio_l ), // [o] + .AUDIO_R ( audio_r ), // [o] + + .coin ( coin_buttons ), // [i] + .start_buttons ( start_buttons ), // [i] + + .p1_input ( p1_input ), // [i] + .p2_input ( p2_input ), // [i] + .p3_input ( p3_input ), // [i] + .p4_input ( p4_input ), // [i] + + .dip_sw ( dip_sw ), // [i] + + .pause_rq ( pause ), // [i] + + .sdr_vram_addr ( sdr_vram_addr ), // [o] + .sdr_vram_data ( sdr_vram_data ), // [i] + .sdr_vram_req ( sdr_vram_req ), // [o] + + .sdr_sprite_addr ( sdr_sprite_addr ), // [o] + .sdr_sprite_dout ( sdr_sprite_dout ), // [i] + .sdr_sprite_req ( sdr_sprite_req ), // [o] + .sdr_sprite_ack ( sdr_sprite_ack ), // [i] + + .sdr_bg_addr_a ( sdr_bg_addr_a ), // [o] + .sdr_bg_data_a ( sdr_bg_data_a ), // [i] + .sdr_bg_req_a ( sdr_bg_req_a ), // [o] + .sdr_bg_ack_a ( sdr_bg_ack_a ), // [i] + + .sdr_bg_addr_b ( sdr_bg_addr_b ), // [o] + .sdr_bg_data_b ( sdr_bg_data_b ), // [i] + .sdr_bg_req_b ( sdr_bg_req_b ), // [o] + .sdr_bg_ack_b ( sdr_bg_ack_b ), // [i] + + .sdr_bg_addr_c ( sdr_bg_addr_c ), // [o] + .sdr_bg_data_c ( sdr_bg_data_c ), // [i] + .sdr_bg_req_c ( sdr_bg_req_c ), // [o] + .sdr_bg_ack_c ( sdr_bg_ack_c ), // [i] + + .sdr_cpu_addr ( sdr_cpu_addr ), // [o] + .sdr_cpu_dout ( sdr_cpu_dout ), // [i] + .sdr_cpu_din ( sdr_cpu_din ), // [o] + .sdr_cpu_req ( sdr_cpu_req ), // [o] + .sdr_cpu_ack ( sdr_cpu_ack ), // [i] + .sdr_cpu_wr_sel ( sdr_cpu_wr_sel ), // [o] + + .sdr_audio_cpu_addr ( sdr_audio_cpu_addr ), // [o] + .sdr_audio_cpu_dout ( sdr_audio_cpu_dout ), // [i] + .sdr_audio_cpu_din ( sdr_audio_cpu_din ), // [o] + .sdr_audio_cpu_req ( sdr_audio_cpu_req ), // [o] + .sdr_audio_cpu_ack ( sdr_audio_cpu_ack ), // [i] + .sdr_audio_cpu_wr_sel ( sdr_audio_cpu_wr_sel ), // [o] + + .sdr_audio_addr ( sample_rom_addr ), // [o] + .sdr_audio_dout ( sample_rom_dout ), // [i] + .sdr_audio_req ( sample_rom_req ), // [o] + .sdr_audio_ack ( sample_rom_ack ), // [i] + + .clk_bram ( clk_sys ), // [i] + .bram_wr ( bram_wr ), // [i] + .bram_data ( bram_data ), // [i] + .bram_addr ( bram_addr ), // [i] + .bram_cs ( bram_cs ), // [i] + + .ioctl_download ( ioctl_download ), // [i] + .ioctl_index ( ioctl_index ), // [i] + .ioctl_wr ( ioctl_wr ), // [i] + .ioctl_addr ( ioctl_addr ), // [i] + .ioctl_dout ( ioctl_data ), // [i] + + .ioctl_upload ( ), // [i] + .ioctl_upload_index ( ), // [o] + .ioctl_din ( ), // [o] + .ioctl_rd ( ), // [i] + .ioctl_upload_req ( ), // [o] + + .dbg_en_layers ( dbg_en_layers ), // [i] + .dbg_solid_sprites ( ), // [i] + .en_audio_filters ( filters ), // [i] + .dbg_fm_en ( dbg_fm_en ), // [i] + + .sprite_freeze ( dbg_sprite_freeze ) // [i] + ); + + //-------------------------------------------------------------------------- + // ROM download controller + //-------------------------------------------------------------------------- + board_cfg_t board_cfg; + wire rom_downl = ioctl_download && (ioctl_index == ROM_IDX); + + rom_loader rom_loader + ( + .sys_clk ( clk_sys ), // [i] + + .ioctl_downl ( rom_downl ), // [i] + .ioctl_wr ( ioctl_wr ), // [i] + .ioctl_data ( ioctl_data ), // [i] + + .ioctl_wait ( ), // [o] + + .sdr_addr ( sdr_rom_addr ), // [o] + .sdr_data ( sdr_rom_data ), // [o] + .sdr_be ( sdr_rom_be ), // [o] + .sdr_req ( sdr_rom_req ), // [o] + .sdr_ack ( sdr_rom_ack ), // [i] + + .bram_addr ( bram_addr ), // [o] + .bram_data ( bram_data ), // [o] + .bram_cs ( bram_cs ), // [o] + .bram_wr ( bram_wr ), // [o] + + .board_cfg ( board_cfg ) // [o] + ); + + //-------------------------------------------------------------------------- + // SDRAM + //-------------------------------------------------------------------------- + wire sdr_rom_write = ioctl_download && (ioctl_index == ROM_IDX); + + wire sdr_vram_req; + wire [24:0] sdr_vram_addr; + wire [31:0] sdr_vram_data; + + wire [63:0] sdr_sprite_dout; + wire [24:0] sdr_sprite_addr; + wire sdr_sprite_req, sdr_sprite_ack; + + wire [31:0] sdr_bg_data_a; + wire [24:0] sdr_bg_addr_a; + wire sdr_bg_req_a, sdr_bg_ack_a; + + wire [31:0] sdr_bg_data_b; + wire [24:0] sdr_bg_addr_b; + wire sdr_bg_req_b, sdr_bg_ack_b; + + wire [31:0] sdr_bg_data_c; + wire [24:0] sdr_bg_addr_c; + wire sdr_bg_req_c, sdr_bg_ack_c; + + wire [15:0] sdr_cpu_dout, sdr_cpu_din; + wire [24:0] sdr_cpu_addr; + wire sdr_cpu_req, sdr_cpu_ack; + wire [1:0] sdr_cpu_wr_sel; + + wire [15:0] sdr_audio_cpu_dout, sdr_audio_cpu_din; + wire [24:0] sdr_audio_cpu_addr; + wire sdr_audio_cpu_req, sdr_audio_cpu_ack; + wire [1:0] sdr_audio_cpu_wr_sel; + + wire [24:0] sdr_rom_addr; + wire [15:0] sdr_rom_data; + wire [1:0] sdr_rom_be; + wire sdr_rom_req; + wire sdr_rom_ack; + + wire [24:0] sample_rom_addr; + wire [63:0] sample_rom_dout; + wire sample_rom_req; + wire sample_rom_ack; + + wire [19:0] bram_addr; + wire [7:0] bram_data; + wire [3:0] bram_cs; + wire bram_wr; + + assign sdram_clk = clk_ram; + assign sdram_cke = 1'b1; + + sdram_4w_cl3 #(120) sdram + ( + .SDRAM_DQ ( sdram_dq ), + .SDRAM_A ( sdram_a ), + .SDRAM_DQML ( sdram_dqml ), + .SDRAM_DQMH ( sdram_dqmh ), + .SDRAM_BA ( sdram_ba ), + .SDRAM_nCS ( ), + .SDRAM_nWE ( sdram_we_n ), + .SDRAM_nRAS ( sdram_ras_n ), + .SDRAM_nCAS ( sdram_cas_n ), + .init_n ( pll_locked ), + .clk ( clk_ram ), + + // Bank 0-1 ops + .port1_a ( sdr_rom_addr[24:1] ), + .port1_req ( sdr_rom_req ), + .port1_ack ( sdr_rom_ack ), + .port1_we ( sdr_rom_write ), + .port1_ds ( sdr_rom_be ), + .port1_d ( sdr_rom_data ), + .port1_q ( sdr_rom_ack ), + + // Main CPU + .cpu1_rom_addr ( ), + .cpu1_rom_cs ( ), + .cpu1_rom_q ( ), + .cpu1_rom_valid( ), + + .cpu1_ram_req ( sdr_cpu_req ), + .cpu1_ram_ack ( sdr_cpu_ack ), + .cpu1_ram_addr ( sdr_cpu_addr[24:1] ), + .cpu1_ram_we ( |sdr_cpu_wr_sel ), + .cpu1_ram_d ( sdr_cpu_din ), + .cpu1_ram_q ( sdr_cpu_dout ), + .cpu1_ram_ds ( |sdr_cpu_wr_sel ? sdr_cpu_wr_sel : 2'b11 ), + + // Audio CPU + .cpu2_ram_req ( sdr_audio_cpu_req ), + .cpu2_ram_ack ( sdr_audio_cpu_ack ), + .cpu2_ram_addr ( sdr_audio_cpu_addr[24:1] ), + .cpu2_ram_we ( |sdr_audio_cpu_wr_sel ), + .cpu2_ram_d ( sdr_audio_cpu_din ), + .cpu2_ram_q ( sdr_audio_cpu_dout ), + .cpu2_ram_ds ( |sdr_audio_cpu_wr_sel ? sdr_audio_cpu_wr_sel : 2'b11 ), + + // VRAM + .vram_addr ( sdr_vram_addr[24:1] ), + .vram_req ( sdr_vram_req ), + .vram_q ( sdr_vram_data ), + .vram_ack ( ), + + // Bank 2-3 ops + .port2_a ( sdr_rom_addr[24:1] ), + .port2_req ( sdr_rom_req ), + .port2_ack ( sdr_rom_ack ), + .port2_we ( sdr_rom_write ), + .port2_ds ( sdr_rom_be ), + .port2_d ( sdr_rom_data ), + .port2_q ( sdr_rom_ack ), + + .gfx1_req ( sdr_bg_req_a ), + .gfx1_ack ( sdr_bg_ack_a ), + .gfx1_addr ( sdr_bg_addr_a[24:1] ), + .gfx1_q ( sdr_bg_data_a ), + + .gfx2_req ( sdr_bg_req_b ), + .gfx2_ack ( sdr_bg_ack_b ), + .gfx2_addr ( sdr_bg_addr_b[24:1] ), + .gfx2_q ( sdr_bg_data_b ), + + .gfx3_req ( sdr_bg_req_c ), + .gfx3_ack ( sdr_bg_ack_c ), + .gfx3_addr ( sdr_bg_addr_c[24:1] ), + .gfx3_q ( sdr_bg_data_c ), + + .sample_addr ( {sample_rom_addr[24:3], 2'b00} ), + .sample_q ( sample_rom_dout ), + .sample_req ( sample_rom_req ), + .sample_ack ( sample_rom_ack ), + + .sp_addr ( sdr_sprite_addr[24:1] ), + .sp_req ( sdr_sprite_req ), + .sp_ack ( sdr_sprite_ack ), + .sp_q ( sdr_sprite_dout ) + ); + +endmodule diff --git a/rtl/jtframe_frac_cen.v b/rtl/jtframe_frac_cen.v new file mode 100644 index 0000000..37b2780 --- /dev/null +++ b/rtl/jtframe_frac_cen.v @@ -0,0 +1,62 @@ +/////////////////////////////////////////////////////////////////////////// +// Fractional clock enable signal +// W refers to the number of divided down cen signals available +// each one is divided by 2 + +module jtframe_frac_cen #(parameter W=2)( + input clk, + input cen_in, + + input [9:0] n, // numerator + input [9:0] m, // denominator + output reg [W-1:0] cen, + output reg [W-1:0] cenb // 180 shifted +); + +wire [10:0] step={1'b0,n}; +wire [10:0] lim ={1'b0,m}; +wire [10:0] absmax = lim+step; + +reg [10:0] cencnt=11'd0; +reg [10:0] next; +reg [10:0] next2; + +always @(*) begin + next = cencnt+step; + next2 = next-lim; +end + +reg half = 1'b0; +wire over = next>=lim; +wire halfway = next >= (lim>>1) && !half; + +reg [W-1:0] edgecnt = {W{1'b0}}; +wire [W-1:0] next_edgecnt = edgecnt + 1'b1; +wire [W-1:0] toggle = next_edgecnt & ~edgecnt; + +always @(posedge clk) begin + cen <= {W{1'b0}}; + cenb <= {W{1'b0}}; + + if (cen_in) begin + if( cencnt >= absmax ) begin + // something went wrong: restart + cencnt <= 11'd0; + end else + if( halfway ) begin + half <= 1'b1; + cenb[0] <= 1'b1; + end + if( over ) begin + cencnt <= next2; + half <= 1'b0; + edgecnt <= next_edgecnt; + cen <= { toggle[W-2:0], 1'b1 }; + end else begin + cencnt <= next; + end + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/m92.sv b/rtl/m92.sv new file mode 100644 index 0000000..2a27c21 --- /dev/null +++ b/rtl/m92.sv @@ -0,0 +1,732 @@ +//============================================================================ +// Irem M92 for MiSTer FPGA - Main module +// +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +import m92_pkg::*; + +module m92 ( + input clk_sys, + + input reset_n, + output reg ce_pix, + output flipped, + + input board_cfg_t board_cfg, + + output [7:0] R, + output [7:0] G, + output [7:0] B, + + output HSync, + output VSync, + output HBlank, + output VBlank, + + output [15:0] AUDIO_L, + output [15:0] AUDIO_R, + + input [3:0] coin, + input [3:0] start_buttons, + + input [9:0] p1_input, + input [9:0] p2_input, + input [9:0] p3_input, + input [9:0] p4_input, + + input [23:0] dip_sw, + + input pause_rq, + output cpu_paused, + + output [24:0] sdr_vram_addr, + input [31:0] sdr_vram_data, + output sdr_vram_req, + + output [24:0] sdr_sprite_addr, + input [63:0] sdr_sprite_dout, + output sdr_sprite_req, + input sdr_sprite_ack, + output sdr_sprite_refresh, + + output [24:0] sdr_bg_addr_a, + input [31:0] sdr_bg_data_a, + output sdr_bg_req_a, + input sdr_bg_ack_a, + + output [24:0] sdr_bg_addr_b, + input [31:0] sdr_bg_data_b, + output sdr_bg_req_b, + input sdr_bg_ack_b, + + output [24:0] sdr_bg_addr_c, + input [31:0] sdr_bg_data_c, + output sdr_bg_req_c, + input sdr_bg_ack_c, + + output reg [24:0] sdr_cpu_addr, + input [15:0] sdr_cpu_dout, + output reg [15:0] sdr_cpu_din, + output reg sdr_cpu_req, + input sdr_cpu_ack, + output reg [1:0] sdr_cpu_wr_sel, + + output reg [24:0] sdr_audio_cpu_addr, + input [15:0] sdr_audio_cpu_dout, + output reg [15:0] sdr_audio_cpu_din, + output reg sdr_audio_cpu_req, + input sdr_audio_cpu_ack, + output reg [1:0] sdr_audio_cpu_wr_sel, + + output [24:0] sdr_audio_addr, + input [63:0] sdr_audio_dout, + output sdr_audio_req, + input sdr_audio_ack, + + input clk_bram, + input bram_wr, + input [7:0] bram_data, + input [19:0] bram_addr, + input [4:0] bram_cs, + + input ioctl_download, + input [15:0] ioctl_index, + input ioctl_wr, + input [26:0] ioctl_addr, + input [7:0] ioctl_dout, + + input ioctl_upload, + output [7:0] ioctl_upload_index, + output [7:0] ioctl_din, + input ioctl_rd, + output ioctl_upload_req, + + input [2:0] dbg_en_layers, + input dbg_solid_sprites, + input en_audio_filters, + input dbg_fm_en, + + input sprite_freeze, + + input dbg_io_write, + input [7:0] dbg_io_data, + output reg dbg_io_wait +); + +assign ioctl_upload_index = 8'd1; +assign flipped = NL; + +wire [15:0] rgb_color; +assign R = { rgb_color[4:0], rgb_color[4:2] }; +assign G = { rgb_color[9:5], rgb_color[9:7] }; +assign B = { rgb_color[14:10], rgb_color[14:12] }; + +reg paused = 0; +assign cpu_paused = paused; + +always @(posedge clk_sys) begin + if (pause_rq & ~paused) begin + if (~cpu_mem_read & ~cpu_mem_write & ~mem_rq_active & vpulse) begin + paused <= 1; + end + end else if (~pause_rq & paused) begin + paused <= ~vpulse; + end +end + + +wire ce_13m; +jtframe_frac_cen #(2) pixel_cen +( + .clk(clk_sys), + .cen_in(1), + .n(10'd1), + .m(10'd3), + .cen({ce_pix, ce_13m}) +); + +wire ce_9m, ce_18m; +jtframe_frac_cen #(2) cpu_cen +( + .clk(clk_sys), + .cen_in(1), + .n(10'd9), + .m(10'd20), + .cen({ce_9m, ce_18m}) +); + +wire dma_busy; + +wire [15:0] cpu_mem_out; +wire [19:0] cpu_mem_addr; +wire [1:0] cpu_mem_sel; + +// v30 bus read/write signals are only asserted for a single clock cycle, so latch them for an additional one +reg cpu_mem_read_lat, cpu_mem_write_lat; +wire cpu_mem_read_w, cpu_mem_write_w; +wire cpu_mem_read = cpu_mem_read_w | cpu_mem_read_lat; +wire cpu_mem_write = cpu_mem_write_w | cpu_mem_write_lat; + +wire cpu_io_read, cpu_io_write; +wire [7:0] cpu_io_in; +wire [7:0] cpu_io_out; +wire [7:0] cpu_io_addr; + +wire [15:0] cpu_mem_in; + +/* Global signals from schematics */ +wire IOWR = cpu_io_write; // IO Write +wire IORD = cpu_io_read; // IO Read +wire MWR = cpu_mem_write; // Mem Write +wire MRD = cpu_mem_read; // Mem Read + + +wire [15:0] cpu_word_out = cpu_mem_addr[0] ? { cpu_mem_out[7:0], 8'h00 } : cpu_mem_out; +wire [1:0] cpu_word_byte_sel = cpu_mem_addr[0] ? { cpu_mem_sel[0], 1'b0 } : cpu_mem_sel; +reg [15:0] cpu_ram_rom_data; +wire [24:0] cpu_region_addr; +wire cpu_region_writable; + +wire ram_rom_memrq; +wire buffer_memrq; +wire sprite_control_memrq; +wire video_control_memrq; +wire eeprom_memrq; +wire banked_memrq; + +wire [7:0] snd_latch_dout; +wire snd_latch_rdy; + +reg [1:0] ce_counter_cpu; +reg ce_cpu, ce_4x_cpu; +reg mem_rq_active = 0; + +always @(posedge clk_sys, negedge reset_n) begin + if (!reset_n) begin + ce_cpu <= 0; + ce_4x_cpu <= 0; + ce_counter_cpu <= 0; + end else begin + ce_cpu <= 0; + ce_4x_cpu <= 0; + + if (~paused) begin + if (~((ram_rom_memrq) & (cpu_mem_read | cpu_mem_write)) & ~mem_rq_active) begin // stall main cpu while fetching from sdram + ce_counter_cpu <= ce_counter_cpu + 2'd1; + ce_4x_cpu <= 1; + ce_cpu <= &ce_counter_cpu; + end + end + end +end + +function [15:0] word_shuffle(input [19:0] addr, input [15:0] data); + begin + word_shuffle = addr[0] ? { 8'h00, data[15:8] } : data; + end +endfunction + +always_ff @(posedge clk_sys or negedge reset_n) begin + if (!reset_n) begin + mem_rq_active <= 0; + end else begin + cpu_mem_read_lat <= cpu_mem_read_w; + cpu_mem_write_lat <= cpu_mem_write_w; + if (!mem_rq_active) begin + if (ram_rom_memrq & ((cpu_mem_read_w & ~cpu_mem_read_lat) | (cpu_mem_write_w & ~cpu_mem_write_lat))) begin // sdram request + sdr_cpu_wr_sel <= 2'b00; + sdr_cpu_addr <= cpu_region_addr; + if (cpu_mem_write & cpu_region_writable ) begin + sdr_cpu_wr_sel <= cpu_word_byte_sel; + sdr_cpu_din <= cpu_word_out; + end + sdr_cpu_req <= ~sdr_cpu_req; + mem_rq_active <= 1; + end + end else if (sdr_cpu_req == sdr_cpu_ack) begin + mem_rq_active <= 0; + cpu_ram_rom_data <= sdr_cpu_dout; + end + end +end + +wire rom0_ce, rom1_ce, ram_cs2; + +reg [7:0] dbg_io_latch; + +reg [3:0] bank_select = 4'd0; + + +wire [7:0] switches_p1 = board_cfg.kick_harness ? { p1_input[4], p1_input[5], p1_input[6], 1'b0, p1_input[3], p1_input[2], p1_input[1], p1_input[0] } + : { p1_input[4], p1_input[5], 1'b0, 1'b0, p1_input[3], p1_input[2], p1_input[1], p1_input[0] }; +wire [7:0] switches_p2 = board_cfg.kick_harness ? { p2_input[4], p2_input[5], p2_input[6], 1'b0, p2_input[3], p2_input[2], p2_input[1], p2_input[0] } + : { p2_input[4], p2_input[5], 1'b0, 1'b0, p2_input[3], p2_input[2], p2_input[1], p2_input[0] }; +wire [7:0] switches_p3 = board_cfg.kick_harness ? { 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0 } + : { p3_input[4], p3_input[5], coin[2], start_buttons[2], p3_input[3], p3_input[2], p3_input[1], p3_input[0] }; +wire [7:0] switches_p4 = board_cfg.kick_harness ? { p2_input[9], p2_input[8], p2_input[7], 1'b0, p1_input[9], p1_input[8], p1_input[7], 1'b0 } + : { p4_input[4], p4_input[5], coin[3], start_buttons[3], p4_input[3], p4_input[2], p4_input[1], p4_input[0] }; + +wire [15:0] switches_p1_p2 = { ~switches_p2, ~switches_p1 }; + +`ifdef M92_DEBUG_IO +wire [15:0] switches_p3_p4 = { dbg_io_latch, dbg_io_latch }; +`else +wire [15:0] switches_p3_p4 = { ~switches_p4, ~switches_p3 }; +`endif + +wire [15:0] flags = { ~dip_sw[23:16], ~dma_busy, 1'b1, 1'b1 /*TEST*/, 1'b1 /*R*/, ~coin[1:0], ~start_buttons[1:0] }; + +reg [7:0] sys_flags = 0; +wire COIN0 = sys_flags[0]; +wire COIN1 = sys_flags[1]; +wire SOFT_NL = ~sys_flags[2]; +wire CBLK = sys_flags[3]; +wire BRQ = ~sys_flags[4]; +wire BANK = sys_flags[5]; +wire NL = SOFT_NL ^ ~dip_sw[8]; + +// TODO BANK, CBLK, NL +always @(posedge clk_sys) begin + if (IOWR && cpu_io_addr == 8'h02) sys_flags <= cpu_io_out[7:0]; + if (IOWR && cpu_io_addr == 8'h20) bank_select <= cpu_io_out[3:0]; +end + +reg [15:0] vid_ctrl; +always @(posedge clk_sys or negedge reset_n) begin + if (~reset_n) begin + vid_ctrl <= 0; + end else if (video_control_memrq & MWR) begin + vid_ctrl <= cpu_word_out; + end +end + +`ifdef M92_DEBUG_IO +always @(posedge clk_sys or negedge reset_n) begin + if (~reset_n) begin + dbg_io_wait <= 0; + dbg_io_latch <= 8'hff; + end else begin + if (IORD && cpu_io_addr == 8'h06) begin + dbg_io_wait <= 0; + end + + if (dbg_io_write) begin + dbg_io_wait <= 1; + dbg_io_latch <= dbg_io_data; + end + end +end +`endif + +wire [15:0] ga21_dout; +wire [7:0] eeprom_dout; + +// mux io and memory reads +always_comb begin + bit [15:0] d16; + bit [15:0] io16; + + if (buffer_memrq) d16 = ga21_dout; + else if(eeprom_memrq) d16 = { eeprom_dout, eeprom_dout }; + else d16 = cpu_ram_rom_data; + cpu_mem_in = word_shuffle(cpu_mem_addr, d16); + + case ({cpu_io_addr[7:1], 1'b0}) + 8'h00: io16 = switches_p1_p2; + 8'h02: io16 = flags; + 8'h04: io16 = ~dip_sw[15:0]; + 8'h06: io16 = switches_p3_p4; + 8'h08: io16 = { snd_latch_dout, snd_latch_dout }; + default: io16 = 16'hffff; + endcase + + cpu_io_in = cpu_io_addr[0] ? io16[15:8] : io16[7:0]; +end + +wire int_req, int_ack; +wire [8:0] int_vector; + +v30 #(.INTACK_DELAY(0)) v30( + .clk(clk_sys), + .ce(ce_cpu), + .ce_4x(ce_4x_cpu), + .reset(~reset_n), + .turbo(1), + .SLOWTIMING(0), + + .cpu_idle(), + .cpu_halt(), + .cpu_irqrequest(), + .cpu_prefix(), + + .bus_read(cpu_mem_read_w), + .bus_write(cpu_mem_write_w), + .bus_be(cpu_mem_sel), + .bus_addr(cpu_mem_addr), + .bus_datawrite(cpu_mem_out), + .bus_dataread(cpu_mem_in), + + .irqrequest_in(int_req), + .irqvector_in(int_vector), + .irqrequest_ack(int_ack), + + // TODO + .cpu_done(), + + .RegBus_Din(cpu_io_out), + .RegBus_Adr(cpu_io_addr), + .RegBus_wren(cpu_io_write), + .RegBus_rden(cpu_io_read), + .RegBus_Dout(cpu_io_in) +); + +address_translator address_translator( + .A(cpu_mem_addr), + .board_cfg(board_cfg), + .ram_rom_memrq(ram_rom_memrq), + .sdr_addr(cpu_region_addr), + .writable(cpu_region_writable), + + .buffer_memrq(buffer_memrq), + .sprite_control_memrq(sprite_control_memrq), + .video_control_memrq(video_control_memrq), + .eeprom_memrq(eeprom_memrq), + + .bank_select(bank_select) +); + +wire vblank, hblank, vsync, hsync, vpulse, hpulse, hint; + +m92_pic m92_pic( + .clk(clk_sys), + .ce(ce_cpu), + .reset(~reset_n), + + .cs((IORD | IOWR) & ~cpu_io_addr[7] & cpu_io_addr[6] & ~cpu_io_addr[0]), // 0x40-0x43 + .wr(IOWR), + .rd(0), + .a0(cpu_io_addr[1]), + + .din(cpu_io_out), + + .int_req(int_req), + .int_vector(int_vector), + .int_ack(int_ack), + + .intp({4'd0, snd_latch_rdy, hint, ~dma_busy, vblank}) +); + +assign HSync = hsync; +assign HBlank = hblank; +assign VSync = vsync; +assign VBlank = vblank; + +wire objram_we; +wire [15:0] objram_data, objram_q; +wire [63:0] objram_q64; +wire [10:0] objram_addr; + +wire [11:0] ga22_color, ga23_color; +wire ga23_prio; + +objram objram( + .clk(clk_sys), + + .addr(objram_addr), + .we(objram_we), + + .data(objram_data), + + .q(objram_q), + .q64(objram_q64) +); + +wire bufram_we; +wire [15:0] bufram_data; +wire [15:0] bufram_q00, bufram_q01, bufram_q10, bufram_q11; +wire [10:0] bufram_addr; + +wire [1:0] bufram_cs = ( ~bufram_addr[10] & ~dma_busy ) ? { 1'b0, vid_ctrl[0] } : + ( bufram_addr[10] & ~dma_busy ) ? { vid_ctrl[2], vid_ctrl[1] } : + ( ~bufram_addr[10] & dma_busy ) ? { 1'b0, vid_ctrl[3] } : + ( bufram_addr[10] & dma_busy ) ? { vid_ctrl[5], vid_ctrl[4] } : 2'b00; + +wire [15:0] bufram_q; + +wire [12:0] ga21_palram_addr; +wire ga21_palram_we, ga21_palram_cs; +wire [15:0] ga21_palram_dout; +wire [15:0] palram_q; +wire [10:0] ga22_count; + + + +singleport_unreg_ram #(.widthad(13), .width(16), .name("BUFRAM")) bufram( + .clock(clk_sys), + .address({bufram_cs, bufram_addr}), + .q(bufram_q), + .wren(bufram_we), + .data(bufram_data) +); + +palram palram( + .clk(clk_sys), + + .ce_pix(ce_pix), + + .vid_ctrl(vid_ctrl), + .dma_busy(dma_busy), + + .cpu_addr(cpu_mem_addr[10:1]), + + .ga21_addr(ga21_palram_addr), + .ga21_we(ga21_palram_we), + .ga21_req(ga21_palram_cs), + + .obj_color(ga22_color[10:0]), + .obj_prio(ga22_color[11]), + .obj_active(|ga22_color[3:0]), + + .pf_color(ga23_color), + .pf_prio(~ga23_prio), + + .din(ga21_palram_dout), + .dout(palram_q), + + .rgb_out(rgb_color) +); + +GA21 ga21( + .clk(clk_sys), + .ce(ce_9m), + + .reset(), + + .din(cpu_word_out), + .dout(ga21_dout), + + .addr(cpu_mem_addr[11:1]), + + .reg_cs(sprite_control_memrq), + .buf_cs(buffer_memrq), + .wr(MWR), + + .busy(dma_busy), + + .obj_dout(objram_data), + .obj_din(objram_q), + .obj_addr(objram_addr), + .obj_we(objram_we), + + .buffer_dout(bufram_data), + .buffer_din(bufram_q), + .buffer_addr(bufram_addr), + .buffer_we(bufram_we), + + .count(ga22_count), + + .pal_addr(ga21_palram_addr), + .pal_dout(ga21_palram_dout), + .pal_din(palram_q), + .pal_we(ga21_palram_we), + .pal_cs(ga21_palram_cs) +); + +GA22 ga22( + .clk(clk_sys), + + .ce(ce_13m), // 13.33Mhz + + .ce_pix(ce_pix), // 6.66Mhz + + .reset(~reset_n), + + .color(ga22_color), + + .NL(NL), + .hpulse(hpulse), + .vpulse(vpulse), + + .count(ga22_count), + + .obj_in(objram_q64), + + .sdr_data(sdr_sprite_dout), + .sdr_addr(sdr_sprite_addr), + .sdr_req(sdr_sprite_req), + .sdr_ack(sdr_sprite_ack), + .sdr_refresh(sdr_sprite_refresh), + + .dbg_solid_sprites(dbg_solid_sprites) +); + +wire [14:0] vram_addr; +assign sdr_vram_addr = {REGION_VRAM.base_addr[24:16], vram_addr, 1'b0}; + +GA23 ga23( + .clk(clk_sys), + + .ce(ce_pix), + + .reset(~reset_n), + + .paused(paused), + + .io_wr(IOWR), + .addr(IOWR ? {8'd0, cpu_io_addr} : cpu_mem_addr), + .cpu_din(IOWR ? {8'd0, cpu_io_out} : cpu_mem_out), + + .vram_addr(vram_addr), + .vram_din(sdr_vram_data), + .vram_req(sdr_vram_req), + + .NL(NL), + .large_tileset(board_cfg.large_tileset), + + .sdr_data_a(sdr_bg_data_a), + .sdr_addr_a(sdr_bg_addr_a), + .sdr_req_a(sdr_bg_req_a), + .sdr_ack_a(sdr_bg_ack_a), + + .sdr_data_b(sdr_bg_data_b), + .sdr_addr_b(sdr_bg_addr_b), + .sdr_req_b(sdr_bg_req_b), + .sdr_ack_b(sdr_bg_ack_b), + + .sdr_data_c(sdr_bg_data_c), + .sdr_addr_c(sdr_bg_addr_c), + .sdr_req_c(sdr_bg_req_c), + .sdr_ack_c(sdr_bg_ack_c), + + .vblank(vblank), + .hblank(hblank), + .vsync(vsync), + .hsync(hsync), + .hpulse(hpulse), + .vpulse(vpulse), + + .hint(hint), + + .color_out(ga23_color), + .prio_out(ga23_prio), + + .dbg_en_layers(dbg_en_layers) +); + +/* +// Sound board test (select sound with P1 left/right) +reg [7:0] snd_id; +reg snd_wr; +reg left_last, right_last; +wire left = p1_input[1]; +wire right = p1_input[0]; + +always @(posedge clk_sys) begin + if (!reset_n) begin + snd_wr <= 0; + snd_id <= 0; + end else begin + snd_wr <= 0; + left_last <= left; + right_last <= right; + if (!left_last & left) begin + snd_id <= snd_id - 1'd1; + snd_wr <= 1; + end + if (!right_last & right) begin + snd_id <= snd_id + 1'd1; + snd_wr <= 1; + end + end + +end +*/ +wire [15:0] sound_sample; + +sound sound( + .clk_sys(clk_sys), + .reset(~reset_n), + .filter_en(en_audio_filters), + .dbg_fm_en(dbg_fm_en), + .paused(paused), + + .latch_wr(IOWR & cpu_io_addr == 8'h00), + //.latch_wr(snd_wr), + .latch_rd(IORD & cpu_io_addr == 8'h08), + .latch_din(cpu_io_out), + //.latch_din(snd_id), + .latch_dout(snd_latch_dout), + .latch_rdy(snd_latch_rdy), + + .rom_addr(bram_addr), + .rom_data(bram_data), + .rom_wr(bram_wr & bram_cs[1]), + + .secure_addr(bram_addr[7:0]), + .secure_data(bram_data), + .secure_wr(bram_wr & bram_cs[0]), + + .sample(sound_sample), + + .sdr_cpu_addr(sdr_audio_cpu_addr), + .sdr_cpu_dout(sdr_audio_cpu_dout), + .sdr_cpu_din(sdr_audio_cpu_din), + .sdr_cpu_req(sdr_audio_cpu_req), + .sdr_cpu_ack(sdr_audio_cpu_ack), + .sdr_cpu_wr_sel(sdr_audio_cpu_wr_sel), + + .sdr_addr(sdr_audio_addr), + .sdr_data(sdr_audio_dout), + .sdr_req(sdr_audio_req), + .sdr_ack(sdr_audio_ack) +); + +assign AUDIO_L = sound_sample; +assign AUDIO_R = sound_sample; + +parameter [15:0] NVRAM_IDX = 16'd3; +wire eeprom_downl = ioctl_download && (ioctl_index == NVRAM_IDX); + +`ifndef NO_EEPROM +eeprom_28C64 eeprom( + .clk(clk_sys), + .reset(~reset_n), + .ce(1), + + .rd(MRD & eeprom_memrq), + .wr(MWR & eeprom_memrq), + + .addr(cpu_mem_addr[13:1]), + .q(eeprom_dout), + .data(cpu_mem_out[7:0]), + + .ready(), + + .modified(ioctl_upload_req), + .ioctl_download(eeprom_downl | bram_cs[2]), + .ioctl_wr(bram_cs[2] ? bram_wr : ioctl_wr), + .ioctl_addr(bram_cs[2] ? bram_addr[12:0] : ioctl_addr[12:0]), + .ioctl_dout(ioctl_dout), + + .ioctl_upload(ioctl_upload), + .ioctl_din(ioctl_din), + .ioctl_rd(ioctl_rd) +); +`endif + +endmodule diff --git a/rtl/m92_pic.sv b/rtl/m92_pic.sv new file mode 100644 index 0000000..c0f2c89 --- /dev/null +++ b/rtl/m92_pic.sv @@ -0,0 +1,153 @@ +//============================================================================ +// Irem M92 for MiSTer FPGA - Programmable interrupt controller +// +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module m92_pic( + input clk, + input ce, + input reset, + + input cs, + input wr, + input rd, + input a0, + + input [7:0] din, + + output int_req, + output reg [8:0] int_vector, + input int_ack, + + input [7:0] intp +); + +enum { + UNINIT, + INIT_IW2, + INIT_IW3, + INIT_IW4, + INIT_DONE +} init_state = UNINIT; + +reg [7:0] IW1, IW2, IW3, IW4; +reg [7:0] IMW; +reg [7:0] PFCW; +reg [7:0] MCW; + +reg [7:0] IRR; +int ISR; + +wire [7:0] IRQ = ( IRR & ~IMW ); +assign int_req = IRQ != 8'd0; + +wire iw4_write = IW1[0]; +wire iw4_not_written = ~IW1[0]; +wire single_mode = IW1[1]; +wire extended_mode = ~IW1[1]; +wire address_gap_4 = IW1[2]; +wire address_gap_8 = ~IW1[2]; +wire level_triggered = IW1[3]; +wire edge_triggered = ~IW1[3]; + +reg [7:0] intp_latch = 0; + +always_ff @(posedge clk or posedge reset) begin + if (reset) begin + init_state <= UNINIT; + intp_latch <= 0; + IRR <= 8'd0; + ISR <= 8; + end else if (ce) begin + if (cs & wr) begin + if (~a0) begin + if (din[4]) begin + init_state <= INIT_IW2; + IW1 <= din; + PFCW <= 0; + MCW <= 0; + IMW <= 0; + IRR <= 0; + ISR <= 8; + end else if (~din[4] & ~din[3]) begin + PFCW <= din; + end else if (~din[4] & din[3]) begin + MCW <= din; + end + end + + if (a0) begin + case (init_state) + INIT_IW2: begin + IW2 <= din; + if (extended_mode) init_state <= INIT_IW3; + else if (iw4_write) init_state <= INIT_IW4; + else init_state <= INIT_DONE; + end + INIT_IW3: begin + IW3 <= din; + if (iw4_write) init_state <= INIT_IW4; + else init_state <= INIT_DONE; + end + INIT_IW4: begin + IW4 <= din; + init_state <= INIT_DONE; + end + INIT_DONE: begin + IMW <= din; + end + endcase + end + end + + if (init_state == INIT_DONE) begin + bit [7:0] trig; + int p; + + intp_latch <= intp; + + if (int_req) begin + if (int_ack) begin + if ( IRQ[0] ) begin int_vector <= {IW2[6:3], 3'd0, 2'b00}; IRR[0] <= 0; end + else if ( IRQ[1] ) begin int_vector <= {IW2[6:3], 3'd1, 2'b00}; IRR[1] <= 0; end + else if ( IRQ[2] ) begin int_vector <= {IW2[6:3], 3'd2, 2'b00}; IRR[2] <= 0; end + else if ( IRQ[3] ) begin int_vector <= {IW2[6:3], 3'd3, 2'b00}; IRR[3] <= 0; end + else if ( IRQ[4] ) begin int_vector <= {IW2[6:3], 3'd4, 2'b00}; IRR[4] <= 0; end + else if ( IRQ[5] ) begin int_vector <= {IW2[6:3], 3'd5, 2'b00}; IRR[5] <= 0; end + else if ( IRQ[6] ) begin int_vector <= {IW2[6:3], 3'd6, 2'b00}; IRR[6] <= 0; end + else if ( IRQ[7] ) begin int_vector <= {IW2[6:3], 3'd7, 2'b00}; IRR[7] <= 0; end + end + end + + if (edge_triggered) + trig = intp & ~intp_latch; + else + trig = intp; + + for( p = 0; p < 8; p = p + 1 ) begin + if (intp[p]) begin + if (trig[p]) begin + IRR[p] <= 1'b1; + end + end + end + end + end +end + +endmodule \ No newline at end of file diff --git a/rtl/m92_pkg.sv b/rtl/m92_pkg.sv new file mode 100644 index 0000000..79c8fb0 --- /dev/null +++ b/rtl/m92_pkg.sv @@ -0,0 +1,61 @@ +//============================================================================ +// Irem M92 for MiSTer FPGA - Common definitions +// +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +package m92_pkg; + + typedef struct packed { + bit [27:0] base_addr; + bit reorder_64; + bit [4:0] bram_cs; + } region_t; + + parameter region_t REGION_CPU_ROM = '{ 28'h000_0000, 0, 5'b00000 }; + parameter region_t REGION_CPU_RAM = '{ 28'h010_0000, 0, 5'b00000 }; + parameter region_t REGION_SOUND = '{ 28'h020_0000, 0, 5'b00000 }; + parameter region_t REGION_GA20 = '{ 28'h030_0000, 0, 5'b00000 }; + parameter region_t REGION_SPRITE = '{ 28'h040_0000, 1, 5'b00000 }; + parameter region_t REGION_TILE = '{ 28'h0c0_0000, 0, 5'b00000 }; + parameter region_t REGION_CRYPT = '{ 28'h000_0000, 0, 5'b00001 }; + parameter region_t REGION_WIDE_SPRITE = '{ 28'h040_0000, 0, 5'b00000 }; + parameter region_t REGION_EEPROM = '{ 28'h000_0000, 0, 5'b00100 }; + + parameter region_t REGION_VRAM = '{ 28'h070_0000, 0, 5'b00000 }; + parameter region_t REGION_SOUND_RAM = '{ 28'h078_0000, 0, 5'b00000 }; + + parameter region_t LOAD_REGIONS[8] = '{ + REGION_CPU_ROM, + REGION_TILE, + REGION_SPRITE, + REGION_SOUND, + REGION_CRYPT, + REGION_GA20, + REGION_WIDE_SPRITE, + REGION_EEPROM + }; + + + typedef struct packed { + bit large_tileset; + bit kick_harness; + bit wide_sprites; + bit alt_map; + bit [3:0] bank_mask; + } board_cfg_t; +endpackage \ No newline at end of file diff --git a/rtl/objram.sv b/rtl/objram.sv new file mode 100644 index 0000000..ddfd5d9 --- /dev/null +++ b/rtl/objram.sv @@ -0,0 +1,77 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module objram( + input clk, + + input [10:0] addr, + input we, + + input [15:0] data, + + output [15:0] q, + output [63:0] q64 +); + +wire [1:0] col = addr[1:0]; +wire [63:0] data64 = { col == 2'd3 ? data : 16'd0, col == 2'd2 ? data : 16'd0, col == 2'd1 ? data : 16'd0, col == 2'd0 ? data : 16'd0 }; +wire [7:0] byte_en = { col == 2'd3 ? 2'b11 : 2'b00, col == 2'd2 ? 2'b11 : 2'b00, col == 2'd1 ? 2'b11 : 2'b00, col == 2'd0 ? 2'b11 : 2'b00 }; +assign q = col == 2'd0 ? q64[15:0] : col == 2'd1 ? q64[31:16] : col == 2'd2 ? q64[47:32] : q64[63:48]; + +altsyncram altsyncram_component ( + .address_a (addr[10:2]), + .byteena_a (byte_en), + .clock0 (clk), + .data_a (data64), + .wren_a (we), + .q_a (q64), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); +defparam + altsyncram_component.byte_size = 8, + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 512, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "DONT_CARE", + altsyncram_component.widthad_a = 9, + altsyncram_component.width_a = 64, + altsyncram_component.width_byteena_a = 8; + +endmodule \ No newline at end of file diff --git a/rtl/pal.sv b/rtl/pal.sv new file mode 100644 index 0000000..2b9a8bd --- /dev/null +++ b/rtl/pal.sv @@ -0,0 +1,85 @@ +//============================================================================ +// Irem M92 for MiSTer FPGA - PAL address decoders +// +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + + +import m92_pkg::*; + +module address_translator +( + input logic [19:0] A, + + input logic [3:0] bank_select, + + input board_cfg_t board_cfg, + + output [24:0] sdr_addr, + output writable, + output ram_rom_memrq, + + output buffer_memrq, + output sprite_control_memrq, + output video_control_memrq, + output eeprom_memrq +); + +wire [3:0] bank_a19_16 = ( bank_select & board_cfg.bank_mask ) | ( A[19:16] & ~board_cfg.bank_mask ); + +always_comb begin + ram_rom_memrq = 0; + writable = 0; + sdr_addr = 0; + + buffer_memrq = 0; + sprite_control_memrq = 0; + video_control_memrq = 0; + eeprom_memrq = 0; + + casex (A[19:0]) + // 0xc0000-0xcffff + 20'b1100_xxxx_xxxx_xxxx_xxxx: begin ram_rom_memrq = 1; writable = 0; sdr_addr = { REGION_CPU_ROM.base_addr[24:16], A[15:0] }; end + // 0xd0000-0xdffff + 20'b1101_xxxx_xxxx_xxxx_xxxx: begin ram_rom_memrq = 1; writable = 1; sdr_addr = { REGION_VRAM.base_addr[24:16], A[15:0] }; end + // 0xe0000-0xeffff + 20'b1110_xxxx_xxxx_xxxx_xxxx: begin ram_rom_memrq = 1; writable = 1; sdr_addr = { REGION_CPU_RAM.base_addr[24:16], A[15:0] }; end + // 0xf0000-0xf3fff + 20'b1111_00xx_xxxx_xxxx_xxxx: eeprom_memrq = 1; + // 0xf8000-0xf87ff + 20'b1111_1000_xxxx_xxxx_xxxx: buffer_memrq = 1; + // 0xf9000-0xf900f + 20'b1111_1001_0000_0000_xxxx: sprite_control_memrq = 1; + // 0xf9800-0xf9801 + 20'b1111_1001_1000_0000_000x: video_control_memrq = 1; + // 0xffff0-0xfffff + 20'b1111_1111_1111_1111_xxxx: begin ram_rom_memrq = 1; writable = 0; sdr_addr = { REGION_CPU_ROM.base_addr[24:20], 16'h7fff, A[3:0] }; end + // 0x00000-0xbffff + default: begin + if (board_cfg.alt_map && A[19:16] == 4'h8) begin + ram_rom_memrq = 1; + writable = 1; + sdr_addr = { REGION_VRAM.base_addr[24:16], A[15:0] }; + end else begin + ram_rom_memrq = 1; + writable = 0; + sdr_addr = { REGION_CPU_ROM.base_addr[24:20], A[19:17] == 3'b101 ? bank_a19_16 : A[19:16], A[15:0] }; + end + end + endcase +end +endmodule diff --git a/rtl/palram.sv b/rtl/palram.sv new file mode 100644 index 0000000..0c72270 --- /dev/null +++ b/rtl/palram.sv @@ -0,0 +1,84 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module palram( + input clk, + + input ce_pix, + + input [15:0] vid_ctrl, + input dma_busy, + + input [9:0] cpu_addr, + + input [12:0] ga21_addr, + input ga21_we, + input ga21_req, + + input [10:0] obj_color, + input obj_prio, + input obj_active, + + input [10:0] pf_color, + input pf_prio, + + input [15:0] din, + output [15:0] dout, + + output reg [15:0] rgb_out +); + +wire obj_pal_bank = ~vid_ctrl[13] & obj_prio; +wire obj_avail = ~vid_ctrl[7] & obj_active; + +wire n_sela = ~dma_busy & ( + ( vid_ctrl[13] & obj_prio & obj_avail ) | + ( ~obj_prio & pf_prio & obj_avail ) | + ( ~vid_ctrl[13] & obj_prio & pf_prio & obj_avail ) | + ( vid_ctrl[12] ) | + ga21_req +); + +wire selb = ~dma_busy & ~ga21_req & ~vid_ctrl[12]; + +wire [1:0] sel = { selb, ~n_sela }; + +wire [12:0] full_cpu_addr = { vid_ctrl[10:8], cpu_addr[9:0] }; +wire [12:0] obj_addr = { vid_ctrl[15], obj_pal_bank, obj_color }; +wire [12:0] pf_addr = { vid_ctrl[15], vid_ctrl[14], pf_color }; + +wire we = sel == 0 ? ga21_we : sel == 1 ? ga21_we : 1'b0; +wire [12:0] selected_addr = sel == 0 ? full_cpu_addr : + sel == 1 ? ga21_addr : + sel == 2 ? obj_addr : + pf_addr; + +singleport_unreg_ram #(.widthad(13), .width(16), .name("PALRAM")) ram +( + .clock(clk), + .address(selected_addr), + .q(dout), + .wren(we), + .data(din) +); + +always_ff @(posedge clk) begin + if (ce_pix) rgb_out <= dout; +end + +endmodule \ No newline at end of file diff --git a/rtl/rom.sv b/rtl/rom.sv new file mode 100644 index 0000000..9171f7e --- /dev/null +++ b/rtl/rom.sv @@ -0,0 +1,142 @@ +//============================================================================ +// Irem M92 for MiSTer FPGA - ROM loading +// +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +import m92_pkg::*; + +module rom_loader + ( + input wire sys_clk, + + input wire ioctl_downl, + input wire ioctl_wr, + input wire [7:0] ioctl_data, + + output wire ioctl_wait, + + output wire [24:0] sdr_addr, + output wire [15:0] sdr_data, + output wire [1:0] sdr_be, + output reg sdr_req, + input wire sdr_ack, + + output wire [19:0] bram_addr, + output wire [7:0] bram_data, + output reg [4:0] bram_cs, + output wire bram_wr, + + output board_cfg_t board_cfg + ); + + reg [27:0] base_addr; + reg reorder_64; + reg [24:0] offset; + reg [23:0] size; + + enum { + BOARD_CFG, + REGION_IDX, + SIZE_0, + SIZE_1, + SIZE_2, + SDR_DATA, + BRAM_DATA + } stage = BOARD_CFG; + + integer region = 0; + reg ioctl_wr_last; + + always @(posedge sys_clk) begin + ioctl_wr_last <= ioctl_wr; + + if (!ioctl_downl) begin + stage <= BOARD_CFG; + region <= 0; + bram_cs <= 0; + end + if (sdr_ack == sdr_req) begin + ioctl_wait <= 0; + end + bram_wr <= 0; + + if (~ioctl_wr_last && ioctl_wr) begin + case (stage) + BOARD_CFG: begin + board_cfg <= board_cfg_t'(ioctl_data); + stage <= REGION_IDX; + end + REGION_IDX: begin + if (ioctl_data == 8'hff) region <= region + 4'd1; + else region <= ioctl_data[3:0]; + stage <= SIZE_0; + end + SIZE_0: begin + size[23:16] <= ioctl_data; + stage <= SIZE_1; + end + SIZE_1: begin + size[15:8] <= ioctl_data; + stage <= SIZE_2; + end + SIZE_2: begin + size[7:0] <= ioctl_data; + base_addr <= LOAD_REGIONS[region].base_addr; + reorder_64 <= LOAD_REGIONS[region].reorder_64; + bram_cs <= LOAD_REGIONS[region].bram_cs; + offset <= 25'd0; + if ({size[23:8], ioctl_data} == 24'd0) begin + stage <= REGION_IDX; + end + else if (LOAD_REGIONS[region].bram_cs != 0) begin + stage <= BRAM_DATA; + end + else begin + stage <= SDR_DATA; + end + end + SDR_DATA: begin + if (reorder_64) begin + sdr_addr <= base_addr[24:0] + {offset[24:7], offset[5:2], offset[6], offset[1:0]}; + end + else begin + sdr_addr <= base_addr[24:0] + offset[24:0]; + end + sdr_data <= { ioctl_data, ioctl_data }; + sdr_be <= { offset[0], ~offset[0] }; + offset <= offset + 25'd1; + sdr_req <= ~sdr_req; + ioctl_wait <= 1; + if (offset == ( size - 1)) begin + stage <= REGION_IDX; + end + end + BRAM_DATA: begin + bram_addr <= offset[19:0]; + bram_data <= ioctl_data; + bram_wr <= 1; + offset <= offset + 25'd1; + if (offset == ( size - 1)) begin + stage <= REGION_IDX; + end + end + endcase + end + end + +endmodule diff --git a/rtl/sdram_4w_cl3.sv b/rtl/sdram_4w_cl3.sv new file mode 100644 index 0000000..f1e5f18 --- /dev/null +++ b/rtl/sdram_4w_cl3.sv @@ -0,0 +1,499 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019-2022 Gyorgy Szombathelyi +// +// This source file 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 source file 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 . +// + +module sdram_4w_cl3 ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + + // 1st bank + input port1_req, + output reg port1_ack = 0, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output reg [15:0] port1_q, + + // cpu1 rom/ram + input [20:1] cpu1_rom_addr, + input cpu1_rom_cs, + output reg [15:0] cpu1_rom_q, + output reg cpu1_rom_valid, + + input cpu1_ram_req, + output reg cpu1_ram_ack = 0, + input [22:1] cpu1_ram_addr, + input cpu1_ram_we, + input [1:0] cpu1_ram_ds, + input [15:0] cpu1_ram_d, + output reg [15:0] cpu1_ram_q, + + // cpu2 rom/ram + input cpu2_ram_req, + output reg cpu2_ram_ack = 0, + input [22:1] cpu2_ram_addr, + input cpu2_ram_we, + input [1:0] cpu2_ram_ds, + input [15:0] cpu2_ram_d, + output reg [15:0] cpu2_ram_q, + + // cpu3 rom + input vram_req, + output reg vram_ack = 0, + input [22:1] vram_addr, + output reg [31:0] vram_q, + + // 2nd bank + input port2_req, + output reg port2_ack = 0, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output reg [31:0] port2_q, + + input gfx1_req, + output reg gfx1_ack = 0, + input [23:1] gfx1_addr, + output reg [31:0] gfx1_q, + + input gfx2_req, + output reg gfx2_ack = 0, + input [23:1] gfx2_addr, + output reg [31:0] gfx2_q, + + input gfx3_req, + output reg gfx3_ack = 0, + input [23:1] gfx3_addr, + output reg [31:0] gfx3_q, + + input sample_req, + output reg sample_ack = 0, + input [23:1] sample_addr, + output reg [63:0] sample_q, + + input sp_req, + output reg sp_ack = 0, + input [23:1] sp_addr, + output reg [63:0] sp_q +); + +parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate + +localparam RASCAS_DELAY = 3'd3; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b010; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd3; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us +localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 4 words burst, CL3 +cmd issued registered + 0 RAS0 data1 returned + 1 ras0, data1 returned + 2 data1 returned + 3 CAS0 + 4 RAS1 cas0 + 5 ras1 + 6 + 7 CAS1 data0 returned + 8 cas1 - data0 masked if cas1 write + 9 data0 returned (but masked via DQM) + 10 data0 returned (but masked via DQM) + 11 data1 returned +*/ + +localparam STATE_RAS0 = 4'd0; // first state in cycle +localparam STATE_CAS0 = 4'd3; +localparam STATE_READ0 = 4'd8; // STATE_CAS0 + CAS_LATENCY + 2'd2; +localparam STATE_READ0b = 4'd9; +localparam STATE_DS0 = 4'd4; +localparam STATE_DS0b = 4'd5; +localparam STATE_RAS1 = 4'd4; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS1 = 4'd7; // CAS phase +localparam STATE_READ1 = 4'd0; +localparam STATE_READ1b = 4'd1; +localparam STATE_READ1c = 4'd2; +localparam STATE_READ1d = 4'd3; +localparam STATE_DS1a = 4'd8; +localparam STATE_DS1b = 4'd9; +localparam STATE_DS1c = 4'd10; +localparam STATE_DS1d = 4'd11; +localparam STATE_LAST = 4'd11; + +reg [3:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch[3]; +reg [24:1] addr_latch_next[2]; +reg [15:0] din_next; +reg [15:0] din_latch[2]; +reg oe_next; +reg [1:0] oe_latch; +reg we_next; +reg [1:0] we_latch; +reg [1:0] ds_next; +reg [1:0] ds[2]; + +reg port1_state; +reg port2_state; +reg cpu1_ram_req_state; +reg cpu2_ram_req_state; +reg vram_req_state; +reg sp_req_state; +reg sample_req_state; + +localparam PORT_NONE = 3'd0; +localparam PORT_CPU1_ROM = 3'd1; +localparam PORT_CPU1_RAM = 3'd2; +localparam PORT_CPU2_RAM = 3'd3; +localparam PORT_VRAM = 3'd4; +localparam PORT_GFX1 = 3'd1; +localparam PORT_GFX2 = 3'd2; +localparam PORT_GFX3 = 3'd3; +localparam PORT_SAMPLE = 3'd4; +localparam PORT_SP = 3'd5; +localparam PORT_REQ = 3'd6; + +reg [2:0] next_port[2]; +reg [2:0] port[2]; + +reg refresh; +reg [10:0] refresh_cnt; +wire need_refresh = (refresh_cnt >= RFRSH_CYCLES); + +// PORT1: bank 0,1 +always @(*) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + ds_next = 2'b00; + { oe_next, we_next } = 2'b00; + din_next = 0; + + if (refresh) begin + // nothing + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + ds_next = port1_ds; + { oe_next, we_next } = { ~port1_we, port1_we }; + din_next = port1_d; + end else if (vram_req ^ vram_req_state) begin + next_port[0] = PORT_VRAM; + addr_latch_next[0] = { 2'b00, vram_addr }; + ds_next = 2'b11; + { oe_next, we_next } = 2'b10; + end else if (/*cpu1_rom_addr != addr_last[PORT_CPU1_ROM] &&*/ cpu1_rom_cs && !cpu1_rom_valid) begin + next_port[0] = PORT_CPU1_ROM; + addr_latch_next[0] = { 4'd0, cpu1_rom_addr }; + ds_next = 2'b11; + { oe_next, we_next } = 2'b10; + end else if (cpu1_ram_req ^ cpu1_ram_req_state) begin + next_port[0] = PORT_CPU1_RAM; + addr_latch_next[0] = { 2'b00, cpu1_ram_addr }; + ds_next = cpu1_ram_ds; + { oe_next, we_next } = { ~cpu1_ram_we, cpu1_ram_we }; + din_next = cpu1_ram_d; + end else if (cpu2_ram_req ^ cpu2_ram_req_state) begin + next_port[0] = PORT_CPU2_RAM; + addr_latch_next[0] = { 2'b00, cpu2_ram_addr }; + ds_next = cpu2_ram_ds; + { oe_next, we_next } = { ~cpu2_ram_we, cpu2_ram_we }; + din_next = cpu2_ram_d; + end +end + +// PORT1: bank 2,3 +always @(*) begin + if (port2_req ^ port2_state) begin + next_port[1] = PORT_REQ; + addr_latch_next[1] = { 1'b1, port2_a }; + end else if (sp_req ^ sp_req_state) begin + next_port[1] = PORT_SP; + addr_latch_next[1] = { 1'b1, sp_addr }; + end else if (gfx1_req ^ gfx1_ack) begin + next_port[1] = PORT_GFX1; + addr_latch_next[1] = { 1'b1, gfx1_addr }; + end else if (gfx2_req ^ gfx2_ack) begin + next_port[1] = PORT_GFX2; + addr_latch_next[1] = { 1'b1, gfx2_addr }; + end else if (gfx3_req ^ gfx3_ack) begin + next_port[1] = PORT_GFX3; + addr_latch_next[1] = { 1'b1, gfx3_addr }; + end else if (sample_req ^ sample_req_state) begin + next_port[1] = PORT_SAMPLE; + addr_latch_next[1] = { 1'b1, sample_addr }; + end else begin + next_port[1] = PORT_NONE; + addr_latch_next[1] = addr_latch[1]; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + refresh_cnt <= refresh_cnt + 1'd1; + + if(init) begin + cpu1_rom_valid <= 0; + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + if (!cpu1_rom_cs) cpu1_rom_valid <= 0; + + // RAS phase + // bank 0,1 + if(t == STATE_RAS0) begin + addr_latch[0] <= addr_latch_next[0]; + port[0] <= next_port[0]; + ds[0] <= ds_next; + { oe_latch[0], we_latch[0] } <= { oe_next, we_next }; + din_latch[0] <= din_next; + + if (next_port[0] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[0][22:10]; + SDRAM_BA <= addr_latch_next[0][24:23]; + end + + if (next_port[0] == PORT_REQ) port1_state <= port1_req; + if (next_port[0] == PORT_CPU1_RAM) cpu1_ram_req_state <= cpu1_ram_req; + if (next_port[0] == PORT_CPU2_RAM) cpu2_ram_req_state <= cpu2_ram_req; + if (next_port[0] == PORT_VRAM) vram_req_state <= vram_req; + end + + // bank 2,3 + if(t == STATE_RAS1) begin + refresh <= 1'b0; + addr_latch[1] <= addr_latch_next[1]; + { oe_latch[1], we_latch[1] } <= 2'b00; + port[1] <= next_port[1]; + + if (next_port[1] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[1][22:10]; + SDRAM_BA <= addr_latch_next[1][24:23]; + if (next_port[1] == PORT_REQ) begin + { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we }; + ds[1] <= port2_ds; + din_latch[1] <= port2_d; + port2_state <= port2_req; + end else begin + { oe_latch[1], we_latch[1] } <= 2'b10; + ds[1] <= 2'b11; + end + end + if (next_port[1] == PORT_SP) sp_req_state <= sp_req; + if (next_port[1] == PORT_SAMPLE) sample_req_state <= sample_req; + + if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin + refresh <= 1'b1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + if (we_latch[0]) begin + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + SDRAM_DQ <= din_latch[0]; + case(port[0]) + PORT_REQ: port1_ack <= port1_req; + PORT_CPU1_RAM: cpu1_ram_ack <= cpu1_ram_req; + PORT_CPU2_RAM: cpu2_ram_ack <= cpu2_ram_req; + default: ; + endcase; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + if (we_latch[1]) begin + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + if(t == STATE_DS0 && oe_latch[0]) { SDRAM_DQMH, SDRAM_DQML } <= 0; + if(t == STATE_DS0b && oe_latch[0] && !we_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0; + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1_ROM: begin cpu1_rom_q <= sd_din; cpu1_rom_valid <= 1; end + PORT_CPU1_RAM: begin cpu1_ram_q <= sd_din; cpu1_ram_ack <= cpu1_ram_req; end + PORT_CPU2_RAM: begin cpu2_ram_q <= sd_din; cpu2_ram_ack <= cpu2_ram_req; end + PORT_VRAM: vram_q[15:0] <= sd_din; + default: ; + endcase; + end + if(t == STATE_READ0b && oe_latch[0]) begin + case(port[0]) + PORT_VRAM: begin vram_q[31:16] <= sd_din; vram_ack <= vram_req; end + default: ; + endcase; + end + + if(t == STATE_DS1a && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0; + if(t == STATE_DS1b && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0; + if(t == STATE_DS1c && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0; + if(t == STATE_DS1d && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0; + + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ : port2_q[15:0] <= sd_din; + PORT_GFX1 : gfx1_q[15:0] <= sd_din; + PORT_GFX2 : gfx2_q[15:0] <= sd_din; + PORT_GFX3 : gfx3_q[15:0] <= sd_din; + PORT_SAMPLE: sample_q[15:0] <= sd_din; + PORT_SP : sp_q[15:0] <= sd_din; + default: ; + endcase; + end + + if(t == STATE_READ1b && oe_latch[1]) begin + case(port[1]) + PORT_REQ : begin port2_q[31:16] <= sd_din; port2_ack <= port2_req; end + PORT_GFX1 : begin gfx1_q[31:16] <= sd_din; gfx1_ack <= gfx1_req; end + PORT_GFX2 : begin gfx2_q[31:16] <= sd_din; gfx2_ack <= gfx2_req; end + PORT_GFX3 : begin gfx3_q[31:16] <= sd_din; gfx3_ack <= gfx3_req; end + PORT_SAMPLE: sample_q[31:16] <= sd_din; + PORT_SP : sp_q[31:16] <= sd_din; + default: ; + endcase; + end + if(t == STATE_READ1c && oe_latch[1]) begin + case(port[1]) + PORT_SAMPLE: sample_q[47:32] <= sd_din; + PORT_SP: sp_q[47:32] <= sd_din; + default: ; + endcase; + end + if(t == STATE_READ1d && oe_latch[1]) begin + case(port[1]) + PORT_SAMPLE: begin sample_q[63:48] <= sd_din; sample_ack <= sample_req; end + PORT_SP: begin sp_q[63:48] <= sd_din; sp_ack <= sp_req; end + default: ; + endcase; + end + end +end + +endmodule diff --git a/rtl/sound.sv b/rtl/sound.sv new file mode 100644 index 0000000..f29b0c7 --- /dev/null +++ b/rtl/sound.sv @@ -0,0 +1,266 @@ +//============================================================================ +// Copyright (C) 2023 Martin Donlon +// +// 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 2 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ + +module sound( + input clk_sys, // 40M + input reset, + + input paused, + input filter_en, + input dbg_fm_en, + + input latch_wr, + input latch_rd, + + input [7:0] latch_din, + output [7:0] latch_dout, + output latch_rdy, + + // ioctl load + input [19:0] rom_addr, + input [7:0] rom_data, + input rom_wr, + + input [7:0] secure_addr, + input [7:0] secure_data, + input secure_wr, + + output reg [15:0] sample, + + // sdr + output [24:0] sdr_addr, + input [63:0] sdr_data, + output sdr_req, + input sdr_ack, + + output reg [24:0] sdr_cpu_addr, + input [15:0] sdr_cpu_dout, + output reg [15:0] sdr_cpu_din, + output reg sdr_cpu_req, + input sdr_cpu_ack, + output reg [1:0] sdr_cpu_wr_sel +); + + +wire [15:0] sample_out, fm_sample, fm_sample_flt; + +localparam OVERALL_GAIN = 0.9; +wire [11:0] fm_scale = int'(1.3 * OVERALL_GAIN * 128); +wire [11:0] pcm_scale = int'(3.1 * OVERALL_GAIN * 128); + +always_ff @(posedge clk_sys) begin + reg [27:0] sum; + reg [27:0] fm; + reg [27:0] pcm; + + fm <= $signed(filter_en ? fm_sample_flt : fm_sample) * fm_scale; + pcm <= $signed(sample_out) * pcm_scale; + if (!dbg_fm_en) fm <= 0; + + sum <= fm + pcm; + if (&sum[27:22] || &(~sum[27:22])) sample <= sum[22:7]; + else if (sum[27]) sample <= 16'h8000; + else sample <= 16'h7fff; +end + +wire ce_28m, ce_14m, ce_7m, ce_3_5m, ce_1_7m; +jtframe_frac_cen #(6) pixel_cen +( + .clk(clk_sys), + .cen_in(~paused), + .n(10'd63), + .m(10'd88), + .cen({ce_1_7m, ce_3_5m, ce_7m, ce_14m, ce_28m}) +); + +wire ram_cs, rom_cs, io_cs; +wire ym2151_cs, ga20_cs, snd_latch_cs, main_latch_cs; +wire [1:0] cpu_be; +wire [15:0] cpu_dout, cpu_din; +wire [19:0] cpu_addr; +reg [15:0] ramrom_dout; +wire cpu_rd, cpu_wr; + +wire [7:0] ym2151_dout; +wire ym2151_irq_n; + +wire [7:0] ga20_dout; + +reg [7:0] main_latch, snd_latch; +reg main_latch_rdy, snd_latch_rdy; + +assign latch_rdy = main_latch_rdy; +assign latch_dout = main_latch; + +wire [15:0] cpu_word_dout = cpu_addr[0] ? { cpu_dout[7:0], 8'h00 } : cpu_dout; +wire [1:0] cpu_word_be = cpu_addr[0] ? { cpu_be[0], 1'b0 } : cpu_be; + +assign ram_cs = cpu_addr[19:14] == {4'ha, 2'b00};// cpu_addr[13:12]>= 8'ha0 && cpu_addr[19:12] < 8'ha4; +assign io_cs = cpu_addr[19:12] == 8'ha8; +assign rom_cs = ~ram_cs & ~io_cs; + +assign ga20_cs = io_cs & cpu_addr[7:6] == 2'b00; // 0xa8000 - 0xa803f +assign ym2151_cs = io_cs & cpu_addr[7:2] == 6'b010000; // 0xa8040 - 0xa8043 +assign snd_latch_cs = io_cs & cpu_addr[7:0] == 8'h44; +assign main_latch_cs = io_cs & cpu_addr[7:0] == 8'h46; + +assign cpu_din = rom_cs ? ( cpu_addr[0] ? { ramrom_dout[7:0], ramrom_dout[15:8] } : ramrom_dout ) : + ram_cs ? ( cpu_addr[0] ? { 8'd0, ramrom_dout[15:8] } : ramrom_dout ) : + ym2151_cs ? { 8'd0, ym2151_dout } : + snd_latch_cs ? { 8'd0, snd_latch } : + ga20_cs ? { 8'd0, ga20_dout } : + 16'hffff; + +wire ram_rom_memrq = rom_cs | ram_cs; +wire cpu_region_writable = !rom_cs; +reg mem_rq_active; +reg cpu_rd_lat, cpu_wr_lat; +wire cpu_mem_read = cpu_rd | cpu_rd_lat; +wire cpu_mem_write = cpu_wr | cpu_wr_lat; +wire ramrom_busy = ((ram_rom_memrq) & (cpu_mem_read | cpu_mem_write)) | mem_rq_active; + +always_ff @(posedge clk_sys, posedge reset) begin + if (reset) begin + mem_rq_active <= 0; + end else begin + cpu_rd_lat <= cpu_rd; + cpu_wr_lat <= cpu_wr; + if (!mem_rq_active) begin + if (ram_rom_memrq & ((cpu_rd & ~cpu_rd_lat) | (cpu_wr & ~cpu_wr_lat))) begin // sdram request + sdr_cpu_wr_sel <= 2'b00; + sdr_cpu_addr <= rom_cs ? {REGION_SOUND.base_addr[24:17], cpu_addr[16:0]} : {REGION_SOUND_RAM.base_addr[24:14], cpu_addr[13:0]}; + if (cpu_wr & cpu_region_writable) begin + sdr_cpu_wr_sel <= cpu_word_be; + sdr_cpu_din <= cpu_word_dout; + end + sdr_cpu_req <= ~sdr_cpu_req; + mem_rq_active <= 1; + end + end else if (sdr_cpu_req == sdr_cpu_ack) begin + mem_rq_active <= 0; + ramrom_dout <= sdr_cpu_dout; + end + end +end + +v35 v35( + .clk(clk_sys), + .ce(ce_28m & !ramrom_busy), + .ce_cycle(ce_7m & !ramrom_busy), + .reset(reset), + + .mem_rd(cpu_rd), + .mem_wr(cpu_wr), + .mem_be(cpu_be), + .mem_addr(cpu_addr), + .mem_dout(cpu_dout), + .mem_din(cpu_din), + + .intp0(ym2151_irq_n), + .intp1(~snd_latch_rdy), + .intp2(0), + + .secure(1), + .secure_wr(secure_wr), + .secure_addr(secure_addr), + .secure_data(secure_data) +); + + +jt51 ym2151( + .rst(reset), + .clk(clk_sys), + .cen(ce_3_5m), + .cen_p1(ce_1_7m), + .cs_n(~ym2151_cs), + .wr_n(~cpu_wr), + .a0(cpu_addr[1]), + .din(cpu_dout[7:0]), + .dout(ym2151_dout), + .irq_n(ym2151_irq_n), + .xright(fm_sample), + .xleft() +); + +// fc1 = 19020hz +// fc2 = 8707hz +iir_filter #( .use_params(1), .stereo(0), .coeff_x(0.000001054852861174913), .coeff_x0(3), .coeff_x1(3), .coeff_x2(1), .coeff_y0(-2.94554610428990093496), .coeff_y1(2.89203308225615352001), .coeff_y2(-0.94647938909674766972)) lpf_ym ( + .clk(clk_sys), + .reset(reset), + + .ce(ce_3_5m), + .sample_ce(ce_3_5m), + + .cx(), .cx0(), .cx1(), .cx2(), .cy0(), .cy1(), .cy2(), + + .input_l(fm_sample), + .output_l(fm_sample_flt), + + .input_r(), + .output_r() +); + +wire [19:0] sample_rom_addr; +assign sdr_addr = { REGION_GA20.base_addr[24:20], sample_rom_addr }; + +ga20 ga20( + .clk(clk_sys), + .reset(reset), + .filter_en(filter_en), + .ce(ce_3_5m), + + .cs(ga20_cs), + .rd(cpu_rd), + .wr(cpu_wr), + .addr(cpu_addr[5:1]), + .din(cpu_dout[7:0]), + .dout(ga20_dout), + + .sample_rom_req(sdr_req), + .sample_rom_addr(sample_rom_addr), + .sample_rom_ack(sdr_ack), + .sample_rom_din(sdr_data), + + .sample_out(sample_out) +); + +always_ff @(posedge clk_sys, posedge reset) begin + if (reset) begin + main_latch_rdy <= 0; + snd_latch_rdy <= 0; + end else begin + if (latch_rd) begin + main_latch_rdy <= 0; + end + + if (latch_wr) begin + snd_latch <= latch_din; + snd_latch_rdy <= 1; + end + + if (snd_latch_cs & cpu_wr) begin + snd_latch_rdy <= 0; + end + + if (main_latch_cs & cpu_wr) begin + main_latch <= cpu_dout[7:0]; + main_latch_rdy <= 1; + end + end +end +endmodule \ No newline at end of file diff --git a/rtl/v35.sv b/rtl/v35.sv new file mode 100644 index 0000000..2e6b060 --- /dev/null +++ b/rtl/v35.sv @@ -0,0 +1,395 @@ +module v35( + input clk, + input ce, // 4x internal clock + input ce_cycle, // real internal clock + + input reset, + + output mem_rd, + output mem_wr, + output [1:0] mem_be, + output [19:0] mem_addr, + output [15:0] mem_dout, + input [15:0] mem_din, + + input intp0, + input intp1, + input intp2, + + input secure, + + input secure_wr, + input [7:0] secure_addr, + input [7:0] secure_data +); + +wire rd, wr; +wire prefetching; +wire [1:0] be; +wire [19:0] addr; +wire [15:0] dout, din; + +reg [2:0] irq_pending = 0; +reg [7:0] irq_vec; +wire irq_ack; +wire irq_fini; + +reg [15:0] TM0, MD0, TM1, MD1, WTC; +reg [7:0] P0, PM0, PMC0, P1, PM1, PMC1, P2, PM2; +reg [7:0] PMC2, PT, PMT, INTM, EMS0, EMS1, EMS2, EXIC0; +reg [7:0] EXIC1, EXIC2, ISPR, RXB0, TXB0, SRMS0, STMS0, SCM0; +reg [7:0] SCC0, BRG0, SCE0, SEIC0, SRIC0, STIC0, RXB1, TXB1; +reg [7:0] SRMS1, STMS1, SCM1, SCC1, BRG1, SCE1, SEIC1, SRIC1; +reg [7:0] STIC1, TMC0, TMC1, TMMS0, TMMS1, TMMS2, TMIC0, TMIC1; +reg [7:0] TMIC2, DMAC0, DMAM0, DMAC1, DMAM1, DIC0, DIC1, STBC; +reg [7:0] RFM, FLAG, PRC, TBIC, IDB; + +wire RAMEN = PRC[6]; +wire [1:0] TB = PRC[3:2]; +wire [1:0] PCK = PRC[1:0]; +wire ESNMI = INTM[0]; +wire ES0 = INTM[2]; +wire ES1 = INTM[4]; +wire ES2 = INTM[6]; + + +reg [7:0] exi_prio_bit; + +reg [15:0] internal_din; +reg [7:0] iram[256]; +reg [1:0] wait_cycles = 0; + +reg intp0_prev, intp1_prev, intp2_prev; + +wire internal_rq = ~prefetching && ( addr[19:9] == { IDB, 3'b111 } || addr[19:0] == 20'hfffff ); +wire internal_ram_rq = RAMEN & internal_rq & ~addr[8]; +wire sfr_area_rq = internal_rq & addr[8]; + +reg internal_rq_latch; + +assign mem_rd = rd & ~internal_rq; +assign mem_wr = wr & ~internal_rq; +assign mem_be = be; +assign mem_addr = addr; +assign mem_dout = dout; +assign din = internal_rq_latch ? internal_din : mem_din; + +always_ff @(posedge clk) begin + if (reset) begin + PM0 <= 8'hff; + PMC0 <= 8'h00; + PM1 <= 8'hff; + PMC1 <= 8'h00; + PM2 <= 8'hff; + PMC2 <= 8'h00; + PMT <= 8'h00; + INTM <= 8'h00; + EXIC0 <= 8'h47; + EXIC1 <= 8'h47; + EXIC2 <= 8'h47; + ISPR <= 8'h00; + SCM0 <= 8'h00; + SCC0 <= 8'h00; + BRG0 <= 8'h00; + SCE0 <= 8'h00; + SEIC0 <= 8'h47; + SRIC0 <= 8'h47; + STIC0 <= 8'h47; + SCM1 <= 8'h00; + SCC1 <= 8'h00; + BRG1 <= 8'h00; + SCE1 <= 8'h00; + SEIC1 <= 8'h47; + SRIC1 <= 8'h47; + STIC1 <= 8'h47; + TMC0 <= 8'h00; + TMC1 <= 8'h00; + TMIC0 <= 8'h47; + TMIC1 <= 8'h47; + TMIC2 <= 8'h47; + DMAM0 <= 8'h00; + DMAM1 <= 8'h00; + DIC0 <= 8'h47; + DIC1 <= 8'h47; + STBC <= 8'h00; + RFM <= 8'hfc; + WTC <= 16'hffff; + FLAG <= 8'h00; + PRC <= 8'h4e; + TBIC <= 8'h47; + IDB <= 8'hff; + + irq_pending <= 0; + wait_cycles <= 2'd0; + end else begin + if (sfr_area_rq) begin + if (wr) begin + case(addr[7:0]) + 8'h00: P0 <= dout[7:0]; + 8'h01: PM0 <= dout[7:0]; + 8'h02: PMC0 <= dout[7:0]; + 8'h08: P1 <= dout[7:0]; + 8'h09: PM1 <= dout[7:0]; + 8'h0a: PMC1 <= dout[7:0]; + 8'h10: P2 <= dout[7:0]; + 8'h11: PM2 <= dout[7:0]; + 8'h12: PMC2 <= dout[7:0]; + 8'h3b: PMT <= dout[7:0]; + 8'h40: INTM <= dout[7:0]; + 8'h44: EMS0 <= dout[7:0]; + 8'h45: EMS1 <= dout[7:0]; + 8'h46: EMS2 <= dout[7:0]; + 8'h4c: EXIC0 <= dout[7:0]; + 8'h4d: EXIC1 <= dout[7:0]; + 8'h4e: EXIC2 <= dout[7:0]; + 8'h62: TXB0 <= dout[7:0]; + 8'h65: SRMS0 <= dout[7:0]; + 8'h66: STMS0 <= dout[7:0]; + 8'h68: SCM0 <= dout[7:0]; + 8'h69: SCC0 <= dout[7:0]; + 8'h6a: BRG0 <= dout[7:0]; + 8'h6c: SEIC0 <= dout[7:0]; + 8'h6d: SRIC0 <= dout[7:0]; + 8'h6e: STIC0 <= dout[7:0]; + 8'h72: TXB1 <= dout[7:0]; + 8'h75: SRMS1 <= dout[7:0]; + 8'h76: STMS1 <= dout[7:0]; + 8'h78: SCM1 <= dout[7:0]; + 8'h79: SCC1 <= dout[7:0]; + 8'h7a: BRG1 <= dout[7:0]; + 8'h7c: SEIC1 <= dout[7:0]; + 8'h7d: SRIC1 <= dout[7:0]; + 8'h7e: STIC1 <= dout[7:0]; + 8'h80: begin + if (be[0]) TM0[7:0] <= dout[7:0]; + if (be[1]) TM0[15:8] <= dout[15:8]; + end + 8'h81: TM0[15:8] <= dout[7:0]; + 8'h82: begin + if (be[0]) MD0[7:0] <= dout[7:0]; + if (be[1]) MD0[15:8] <= dout[15:8]; + end + 8'h83: MD0[15:8] <= dout[7:0]; + 8'h88: begin + if (be[0]) TM1[7:0] <= dout[7:0]; + if (be[1]) TM1[15:8] <= dout[15:8]; + end + 8'h89: TM1[15:8] <= dout[7:0]; + 8'h8a: begin + if (be[0]) MD1[7:0] <= dout[7:0]; + if (be[1]) MD1[15:8] <= dout[15:8]; + end + 8'h8b: MD1[15:8] <= dout[7:0]; + 8'h90: TMC0 <= dout[7:0]; + 8'h91: TMC1 <= dout[7:0]; + 8'h94: TMMS0 <= dout[7:0]; + 8'h95: TMMS1 <= dout[7:0]; + 8'h96: TMMS2 <= dout[7:0]; + 8'h9c: TMIC0 <= dout[7:0]; + 8'h9d: TMIC1 <= dout[7:0]; + 8'h9e: TMIC2 <= dout[7:0]; + 8'ha0: DMAC0 <= dout[7:0]; + 8'ha1: DMAM0 <= dout[7:0]; + 8'ha2: DMAC1 <= dout[7:0]; + 8'ha3: DMAM1 <= dout[7:0]; + 8'hac: DIC0 <= dout[7:0]; + 8'had: DIC1 <= dout[7:0]; + 8'he0: STBC <= dout[7:0]; + 8'he1: RFM <= dout[7:0]; + 8'he8: begin + if (be[0]) WTC[7:0] <= dout[7:0]; + if (be[1]) WTC[15:8] <= dout[15:8]; + end + 8'he9: WTC[15:8] <= dout[7:0]; + 8'hea: FLAG <= dout[7:0]; + 8'heb: PRC <= dout[7:0]; + 8'hec: TBIC <= dout[7:0]; + 8'hff: IDB <= dout[7:0]; + endcase + end else if (rd) begin + case(addr[7:0]) + 8'h00: internal_din <= { 8'd0, P0 }; + 8'h08: internal_din <= { 8'd0, P1 }; + 8'h10: internal_din <= { 8'd0, P2 }; + 8'h38: internal_din <= { 8'd0, PT }; + 8'h3b: internal_din <= { 8'd0, PMT }; + 8'h40: internal_din <= { 8'd0, INTM }; + 8'h44: internal_din <= { 8'd0, EMS0 }; + 8'h45: internal_din <= { 8'd0, EMS1 }; + 8'h46: internal_din <= { 8'd0, EMS2 }; + 8'h4c: internal_din <= { 8'd0, EXIC0 }; + 8'h4d: internal_din <= { 8'd0, EXIC1 }; + 8'h4e: internal_din <= { 8'd0, EXIC2 }; + 8'hfc: internal_din <= { 8'd0, ISPR }; + 8'h60: internal_din <= { 8'd0, RXB0 }; + 8'h65: internal_din <= { 8'd0, SRMS0 }; + 8'h66: internal_din <= { 8'd0, STMS0 }; + 8'h68: internal_din <= { 8'd0, SCM0 }; + 8'h69: internal_din <= { 8'd0, SCC0 }; + 8'h6a: internal_din <= { 8'd0, BRG0 }; + 8'h6b: internal_din <= { 8'd0, SCE0 }; + 8'h6c: internal_din <= { 8'd0, SEIC0 }; + 8'h6d: internal_din <= { 8'd0, SRIC0 }; + 8'h6e: internal_din <= { 8'd0, STIC0 }; + 8'h70: internal_din <= { 8'd0, RXB1 }; + 8'h75: internal_din <= { 8'd0, SRMS1 }; + 8'h76: internal_din <= { 8'd0, STMS1 }; + 8'h78: internal_din <= { 8'd0, SCM1 }; + 8'h79: internal_din <= { 8'd0, SCC1 }; + 8'h7a: internal_din <= { 8'd0, BRG1 }; + 8'h7b: internal_din <= { 8'd0, SCE1 }; + 8'h7c: internal_din <= { 8'd0, SEIC1 }; + 8'h7d: internal_din <= { 8'd0, SRIC1 }; + 8'h7e: internal_din <= { 8'd0, STIC1 }; + 8'h80: internal_din <= TM0; + 8'h81: internal_din <= { 8'd0, TM0[15:8] }; + 8'h82: internal_din <= MD0; + 8'h83: internal_din <= { 8'd0, MD0[15:8] }; + 8'h88: internal_din <= TM1; + 8'h89: internal_din <= { 8'd0, TM1[15:8] }; + 8'h8a: internal_din <= MD1; + 8'h8b: internal_din <= { 8'd0, MD1[15:8] }; + 8'h90: internal_din <= { 8'd0, TMC0 }; + 8'h91: internal_din <= { 8'd0, TMC1 }; + 8'h94: internal_din <= { 8'd0, TMMS0 }; + 8'h95: internal_din <= { 8'd0, TMMS1 }; + 8'h96: internal_din <= { 8'd0, TMMS2 }; + 8'h9c: internal_din <= { 8'd0, TMIC0 }; + 8'h9d: internal_din <= { 8'd0, TMIC1 }; + 8'h9e: internal_din <= { 8'd0, TMIC2 }; + 8'ha0: internal_din <= { 8'd0, DMAC0 }; + 8'ha1: internal_din <= { 8'd0, DMAM0 }; + 8'ha2: internal_din <= { 8'd0, DMAC1 }; + 8'ha3: internal_din <= { 8'd0, DMAM1 }; + 8'hac: internal_din <= { 8'd0, DIC0 }; + 8'had: internal_din <= { 8'd0, DIC1 }; + 8'he0: internal_din <= { 8'd0, STBC }; + 8'he1: internal_din <= { 8'd0, RFM }; + 8'he8: internal_din <= WTC; + 8'he9: internal_din <= { 8'd0, WTC[15:8] }; + 8'hea: internal_din <= { 8'd0, FLAG }; + 8'heb: internal_din <= { 8'd0, PRC }; + 8'hec: internal_din <= { 8'd0, TBIC }; + 8'hff: internal_din <= { 8'd0, IDB }; + endcase + end + end else if (internal_ram_rq) begin +/* + if (wr) begin + if (be[0]) iram[addr[7:0]] <= dout[7:0]; + if (be[1]) iram[addr[7:0] + 8'd1] <= dout[15:8]; + end else if (rd) begin + internal_din <= { iram[addr[7:0] + 8'd1], iram[addr[7:0]] }; + end +*/ + end + + if (rd) internal_rq_latch <= internal_rq; + + if (rd | wr) begin + case(addr[19:16]) + 4'h0, 4'h1: wait_cycles <= WTC[1:0]; + 4'h2, 4'h3: wait_cycles <= WTC[3:2]; + 4'h4, 4'h5: wait_cycles <= WTC[5:4]; + 4'h6, 4'h7: wait_cycles <= WTC[7:6]; + 4'h8, 4'h9: wait_cycles <= WTC[9:8]; + 4'ha, 4'hb: wait_cycles <= WTC[11:10]; + 4'hc, 4'hf: wait_cycles <= WTC[13:12]; + endcase + end + + if (ce_cycle) begin + if (wait_cycles != 2'd0) wait_cycles <= wait_cycles - 2'd1; + + ///////////////////////////////////////////// + //// General CE processing + if (irq_ack) begin + ISPR <= ISPR | exi_prio_bit; + case(irq_pending) + 1: EXIC0[7] <= 0; + 2: EXIC1[7] <= 0; + 3: EXIC2[7] <= 0; + endcase + irq_pending <= 0; + end + + if (irq_fini) begin + casex(ISPR) + 8'bxxxxxxx1: ISPR <= ISPR & 8'b11111110; + 8'bxxxxxx10: ISPR <= ISPR & 8'b11111100; + 8'bxxxxx100: ISPR <= ISPR & 8'b11111000; + 8'bxxxx1000: ISPR <= ISPR & 8'b11110000; + 8'bxxx10000: ISPR <= ISPR & 8'b11100000; + 8'bxx100000: ISPR <= ISPR & 8'b11000000; + 8'bx1000000: ISPR <= ISPR & 8'b10000000; + 8'b10000000: ISPR <= ISPR & 8'b00000000; + endcase + end + + intp0_prev <= intp0; + intp1_prev <= intp1; + intp2_prev <= intp2; + + if (intp0 != intp0_prev && intp0 == ES0) EXIC0[7] <= 1; + if (intp1 != intp1_prev && intp1 == ES1) EXIC1[7] <= 1; + if (intp2 != intp2_prev && intp2 == ES2) EXIC2[7] <= 1; + + if (irq_pending == 0 && (ISPR & exi_prio_bit) == 8'd0) begin + if (EXIC0[7] & ~EXIC0[6]) begin + irq_pending <= 2'd1; + irq_vec <= 8'd24; + end else if (EXIC1[7] & ~EXIC1[6]) begin + irq_pending <= 2'd2; + irq_vec <= 8'd25; + end else if (EXIC2[7] & ~EXIC2[6]) begin + irq_pending <= 2'd3; + irq_vec <= 8'd26; + end + end + end + end + + exi_prio_bit <= 8'd1 << EXIC0[2:0]; +end + +v30 core( + .clk(clk), + .ce(ce_cycle & (wait_cycles == 2'd0)), + .ce_4x(ce & (wait_cycles == 2'd0)), + .reset(reset), + .turbo(1), + .SLOWTIMING(), + + .cpu_idle(), + .cpu_halt(), + .cpu_irqrequest(), + .cpu_prefix(), + .cpu_done(), + + .bus_read(rd), + .bus_write(wr), + .bus_prefetch(prefetching), + .bus_be(be), + .bus_addr(addr), + .bus_datawrite(dout), + .bus_dataread(din), + + .irqrequest_in(irq_pending != 0), + .irqvector_in({irq_vec, 2'b00}), + .irqrequest_ack(irq_ack), + .irqrequest_fini(irq_fini), + + .secure(secure), + .secure_wr(secure_wr), + .secure_addr(secure_addr), + .secure_data(secure_data), + + // TODO - m92 doesn't use IO ports, but we want to merge these with data anyway + .RegBus_Din(), + .RegBus_Adr(), + .RegBus_wren(), + .RegBus_rden(), + .RegBus_Dout(0) +); + +endmodule \ No newline at end of file diff --git a/target/pocket/core.qip b/target/pocket/core.qip new file mode 100644 index 0000000..97ce120 --- /dev/null +++ b/target/pocket/core.qip @@ -0,0 +1,5 @@ +# ============================================================================== +# Quartus Prime QIP Index File +# ============================================================================== +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "core_top.sv"] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "core_pll/core_pll.qip"] diff --git a/target/pocket/core_pll/core_pll.qip b/target/pocket/core_pll/core_pll.qip new file mode 100644 index 0000000..9bcb280 --- /dev/null +++ b/target/pocket/core_pll/core_pll.qip @@ -0,0 +1,337 @@ +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_TOOL_VERSION "17.1" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "core_pll" -name MISC_FILE [file join $::quartus(qip_path) "core_pll.cmp"] +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_COMPONENT_NAME "Y29yZV9wbGw=" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_COMPONENT_VERSION "MTcuMQ==" +set_global_assignment -entity "core_pll" -library "core_pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_NAME "Y29yZV9wbGxfMDAwMg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_VERSION "MTcuMQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NzQuMjU=::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NzQuMjUgTUh6::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::dHJ1ZQ==::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::NA==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::NA==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MTE5Ljk5OTk4OA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MzQ3MDY0NTk0::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::NQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::MzkuOTk5OTk2::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MzQ3MDY0NTk0::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MTU=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::Ni42NjY2NjY=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MzQ3MDY0NTk0::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::OTA=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::NS45NTI3NTUgTUh6::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::Ni42NjY2NjY=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MzQ3MDY0NTk0::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::OTA=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::ZGVncmVlcw==::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::OTAuMA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MTE5Ljk5OTk4OCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MzkuOTk5OTk2IE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::Ni42NjY2NjYgTUh6::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::Ni42NjY2NjYgTUh6::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::Mzc1MDAgcHM=::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T2Zm::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTIgSGkgRGl2aWRlLEMtQ291bnRlci0yIExvdyBEaXZpZGUsQy1Db3VudGVyLTIgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0yIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTIgSW5wdXQgU291cmNlLEMtQ291bnRlci0yIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTMgSGkgRGl2aWRlLEMtQ291bnRlci0zIExvdyBEaXZpZGUsQy1Db3VudGVyLTMgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0zIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTMgSW5wdXQgU291cmNlLEMtQ291bnRlci0zIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTMgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NCw0LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSwzLDIsMSwwLHBoX211eF9jbGssZmFsc2UsdHJ1ZSw4LDcsMSwwLHBoX211eF9jbGssZmFsc2UsdHJ1ZSw0NSw0NSwxLDAscGhfbXV4X2NsayxmYWxzZSxmYWxzZSw0NSw0NSwyMyw0LHBoX211eF9jbGssZmFsc2UsZmFsc2UsMiwyMCw0MDAwLDU5OS45OTk5NCBNSHosMzQ3MDY0NTk0LG5vbmUsZ2xiLG1fY250LHBoX211eF9jbGssZmFsc2U=::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "core_pll" -name VERILOG_FILE [file join $::quartus(qip_path) "core_pll.v"] +set_global_assignment -library "core_pll" -name VERILOG_FILE [file join $::quartus(qip_path) "core_pll/core_pll_0002.v"] +set_global_assignment -library "core_pll" -name QIP_FILE [file join $::quartus(qip_path) "core_pll/core_pll_0002.qip"] + +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_TOOL_VERSION "17.1" +set_global_assignment -entity "core_pll_0002" -library "core_pll" -name IP_TOOL_ENV "mwpim" diff --git a/target/pocket/core_pll/core_pll.v b/target/pocket/core_pll/core_pll.v new file mode 100644 index 0000000..2c48c3c --- /dev/null +++ b/target/pocket/core_pll/core_pll.v @@ -0,0 +1,259 @@ +// megafunction wizard: %Altera PLL v17.1% +// GENERATION: XML +// core_pll.v + +// Generated using ACDS version 17.1 590 + +`timescale 1 ps / 1 ps +module core_pll ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0, // outclk0.clk + output wire outclk_1, // outclk1.clk + output wire outclk_2, // outclk2.clk + output wire outclk_3, // outclk3.clk + output wire locked // locked.export + ); + + core_pll_0002 core_pll_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .outclk_1 (outclk_1), // outclk1.clk + .outclk_2 (outclk_2), // outclk2.clk + .outclk_3 (outclk_3), // outclk3.clk + .locked (locked) // locked.export + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : core_pll.vo +// RELATED_FILES: core_pll.v, core_pll_0002.v diff --git a/target/pocket/core_pll/core_pll/core_pll_0002.qip b/target/pocket/core_pll/core_pll/core_pll_0002.qip new file mode 100644 index 0000000..8646d01 --- /dev/null +++ b/target/pocket/core_pll/core_pll/core_pll_0002.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*core_pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*core_pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET OFF -to "*core_pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*core_pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/target/pocket/core_pll/core_pll/core_pll_0002.v b/target/pocket/core_pll/core_pll/core_pll_0002.v new file mode 100644 index 0000000..1ee1ac0 --- /dev/null +++ b/target/pocket/core_pll/core_pll/core_pll_0002.v @@ -0,0 +1,96 @@ +`timescale 1ns/10ps +module core_pll_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'outclk1' + output wire outclk_1, + + // interface 'outclk2' + output wire outclk_2, + + // interface 'outclk3' + output wire outclk_3, + + // interface 'locked' + output wire locked +); + + altera_pll #( + .fractional_vco_multiplier("true"), + .reference_clock_frequency("74.25 MHz"), + .operation_mode("direct"), + .number_of_clocks(4), + .output_clock_frequency0("119.999988 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("39.999996 MHz"), + .phase_shift1("0 ps"), + .duty_cycle1(50), + .output_clock_frequency2("6.666666 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("6.666666 MHz"), + .phase_shift3("37500 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("General"), + .pll_subtype("General") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_3, outclk_2, outclk_1, outclk_0}), + .locked (locked), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk) + ); +endmodule + diff --git a/target/pocket/core_top.sv b/target/pocket/core_top.sv new file mode 100644 index 0000000..dcba890 --- /dev/null +++ b/target/pocket/core_top.sv @@ -0,0 +1,1062 @@ +//------------------------------------------------------------------------------ +// SPDX-License-Identifier: MIT +// SPDX-FileType: SOURCE +// SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors +//------------------------------------------------------------------------------ +// +// Copyright (c) 2023, Marcus Andrade +// Copyright (c) 2022, Analogue Enterprises Limited +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------------ +// Platform Specific top-level +// Instantiated by the real top-level: apf_top +//------------------------------------------------------------------------------ + +`default_nettype none +`timescale 1ns/1ps + +module core_top + #( + //!------------------------------------------------------------------------- + //! System Configuration Parameters + //!------------------------------------------------------------------------- + // Memory + parameter USE_SDRAM = 1, //! Enable SDRAM + parameter USE_SRAM = 0, //! Enable SRAM + parameter USE_CRAM0 = 0, //! Enable Cellular RAM #1 + parameter USE_CRAM1 = 0, //! Enable Cellular RAM #2 + // Video + parameter BPP_R = 8, //! Bits Per Pixel Red + parameter BPP_G = 8, //! Bits Per Pixel Green + parameter BPP_B = 8, //! Bits Per Pixel Blue + parameter USE_INTERLACED = 0, //! Enable Interlaced Video Support + parameter USE_VBL = 0, //! Capture and Use VBlank value at HSync + parameter USE_ANALOGIZER = 0, //! Enable Support for Analogizer + // Audio + parameter AUDIO_DW = 16, //! Audio Bits + parameter AUDIO_S = 1, //! Signed Audio + parameter STEREO = 1, //! Stereo Output + parameter AUDIO_MIX = 0, //! [0] No Mix | [1] 25% | [2] 50% | [3] 100% (mono) + parameter MUTE_PAUSE = 1, //! Mute Audio on Pause + // Gamepad/Joystick + parameter JOY_PADS = 4, //! Total Number of Gamepads + parameter JOY_ALT = 0, //! 2 Players Alternate + // Data I/O - [MPU -> FPGA] + parameter DIO_MASK = 4'h0, //! Upper 4 bits of address + parameter DIO_AW = 27, //! Address Width + parameter DIO_DW = 8, //! Data Width (8 or 16 bits) + parameter DIO_DELAY = 7, //! Number of clock cycles to delay each write output + parameter DIO_HOLD = 4, //! Number of clock cycles to hold the ioctl_wr signal high + // HiScore I/O - [MPU <-> FPGA] + parameter HS_AW = 16, //! Max size of game RAM address for highscores + parameter HS_SW = 8, //! Max size of capture RAM For highscore data (default 8 = 256 bytes max) + parameter HS_CFG_AW = 2, //! Max size of RAM address for highscore.dat entries (default 4 = 16 entries max) + parameter HS_CFG_LW = 2, //! Max size of length for each highscore.dat entries (default 1 = 256 bytes max) + parameter HS_CONFIG = 2, //! Dataslot index for config transfer + parameter HS_DATA = 3, //! Dataslot index for save data transfer + parameter HS_MASK = 4'h1, //! Upper 4 bits of address + parameter HS_WR_DELAY = 4, //! Number of clock cycles to delay each write output + parameter HS_WR_HOLD = 1, //! Number of clock cycles to hold the nvram_wr signal high + parameter HS_RD_DELAY = 4, //! Number of clock cycles it takes for a read to complete + // Save I/O - [MPU <-> FPGA] + parameter SIO_MASK = 4'h1, //! Upper 4 bits of address + parameter SIO_AW = 27, //! Address Width + parameter SIO_DW = 8, //! Data Width (8 or 16 bits) + parameter SIO_WR_DELAY = 4, //! Number of clock cycles to delay each write output + parameter SIO_WR_HOLD = 1, //! Number of clock cycles to hold the nvram_wr signal high + parameter SIO_RD_DELAY = 4, //! Number of clock cycles it takes for a read to complete + parameter SIO_SAVE_IDX = 2 //! Dataslot index for save data transfer + ) ( + //!--------------------------------------------------------------------- + //! Clock Inputs 74.25mhz. + //! Not Phase Aligned, Treat These Domains as Asynchronous + //!--------------------------------------------------------------------- + input wire clk_74a, // mainclk1 + input wire clk_74b, // mainclk1 + + //!--------------------------------------------------------------------- + //! Cartridge Interface + //!--------------------------------------------------------------------- + // switches between 3.3v and 5v mechanically + // output enable for multibit translators controlled by pic32 + // GBA AD[15:8] + inout wire [7:0] cart_tran_bank2, + output wire cart_tran_bank2_dir, + // GBA AD[7:0] + inout wire [7:0] cart_tran_bank3, + output wire cart_tran_bank3_dir, + // GBA A[23:16] + inout wire [7:0] cart_tran_bank1, + output wire cart_tran_bank1_dir, + // GBA [7] PHI# + // GBA [6] WR# + // GBA [5] RD# + // GBA [4] CS1#/CS# + // [3:0] unwired + inout wire [7:4] cart_tran_bank0, + output wire cart_tran_bank0_dir, + // GBA CS2#/RES# + inout wire cart_tran_pin30, + output wire cart_tran_pin30_dir, + // when GBC cart is inserted, this signal when low or weak will pull GBC /RES low with a special circuit + // the goal is that when unconfigured, the FPGA weak pullups won't interfere. + // thus, if GBC cart is inserted, FPGA must drive this high in order to let the level translators + // and general IO drive this pin. + output wire cart_pin30_pwroff_reset, + // GBA IRQ/DRQ + inout wire cart_tran_pin31, + output wire cart_tran_pin31_dir, + + //!--------------------------------------------------------------------- + //! Infrared + //!--------------------------------------------------------------------- + input wire port_ir_rx, + output wire port_ir_tx, + output wire port_ir_rx_disable, + + //!--------------------------------------------------------------------- + //! GBA link port + //!--------------------------------------------------------------------- + inout wire port_tran_si, + output wire port_tran_si_dir, + inout wire port_tran_so, + output wire port_tran_so_dir, + inout wire port_tran_sck, + output wire port_tran_sck_dir, + inout wire port_tran_sd, + output wire port_tran_sd_dir, + + //!--------------------------------------------------------------------- + //! CellularRAM #0, 4Mx16 x2 [16 Mbyte] PSRAM (AS1C8M16PL-70BIN) + //!--------------------------------------------------------------------- + output wire [21:16] cram0_a, // Address bus + inout wire [15:0] cram0_dq, // Bidirectional data bus + input wire cram0_wait, // Wait + output wire cram0_clk, // Clock + output wire cram0_adv_n, // Address valid + output wire cram0_cre, // Control register enable + output wire cram0_ce0_n, // First Chip enable + output wire cram0_ce1_n, // Second Chip enable + output wire cram0_oe_n, // Output enable + output wire cram0_we_n, // Write enable + output wire cram0_ub_n, // Upper byte enable. DQ[15:8] + output wire cram0_lb_n, // Lower byte enable. DQ[7:0] + + //!--------------------------------------------------------------------- + //! CellularRAM #1, 4Mx16 x2 [16 Mbyte] PSRAM (AS1C8M16PL-70BIN) + //!--------------------------------------------------------------------- + output wire [21:16] cram1_a, // Address bus + inout wire [15:0] cram1_dq, // Bidirectional data bus + input wire cram1_wait, // Wait + output wire cram1_clk, // Clock + output wire cram1_adv_n, // Address valid + output wire cram1_cre, // Control register enable + output wire cram1_ce0_n, // First Chip enable + output wire cram1_ce1_n, // Second Chip enable + output wire cram1_oe_n, // Output enable + output wire cram1_we_n, // Write enable + output wire cram1_ub_n, // Upper byte enable. DQ[15:8] + output wire cram1_lb_n, // Lower byte enable. DQ[7:0] + + //!--------------------------------------------------------------------- + //! SDRAM, 32Mx16 [64 Mbyte] (AS4C32M16MSA-6BIN) + //!--------------------------------------------------------------------- + output wire [12:0] dram_a, // Address bus + output wire [1:0] dram_ba, // Bank select (single bits) + inout wire [15:0] dram_dq, // Bidirectional data bus + output wire [1:0] dram_dqm, // High/low byte mask + output wire dram_clk, // Clock + output wire dram_cke, // Clock enable + output wire dram_ras_n, // Select row address + output wire dram_cas_n, // Select column address + output wire dram_we_n, // Write enable + + //!--------------------------------------------------------------------- + //! SRAM, 128Kx16 [256 Kbyte] (AS6C2016-55BIN) + //!--------------------------------------------------------------------- + output wire [16:0] sram_a, // Address bus + inout wire [15:0] sram_dq, // Bidirectional data bus + output wire sram_oe_n, // Output enable + output wire sram_we_n, // Write enable + output wire sram_ub_n, // Upper Byte Mask + output wire sram_lb_n, // Lower Byte Mask + + //!--------------------------------------------------------------------- + //! VBlank driven by dock for sync in a certain mode + //!--------------------------------------------------------------------- + input wire vblank, + + //!--------------------------------------------------------------------- + //! I/O to 6515D breakout USB UART + //!--------------------------------------------------------------------- + output wire dbg_tx, + input wire dbg_rx, + + //!--------------------------------------------------------------------- + //! I/O pads near jtag connector user can solder to + //!--------------------------------------------------------------------- + output wire user1, + input wire user2, + + //!--------------------------------------------------------------------- + //! RFU internal i2c bus + //!--------------------------------------------------------------------- + inout wire aux_sda, + output wire aux_scl, + + //!--------------------------------------------------------------------- + //! RFU, do not use !!! + //!--------------------------------------------------------------------- + output wire vpll_feed, + + //!--------------------------------------------------------------------- + //! Logical Connections //////////////////////////////////////////////// + //!--------------------------------------------------------------------- + + //!--------------------------------------------------------------------- + //! Video Output to Scaler + //!--------------------------------------------------------------------- + output wire [23:0] video_rgb, + output wire video_rgb_clock, + output wire video_rgb_clock_90, + output wire video_hs, + output wire video_vs, + output wire video_de, + output wire video_skip, + + //!--------------------------------------------------------------------- + //! Audio + //!--------------------------------------------------------------------- + output wire audio_mclk, + output wire audio_lrck, + output wire audio_dac, + input wire audio_adc, + + //!--------------------------------------------------------------------- + //! Bridge Bus Connection (synchronous to clk_74a) + //!--------------------------------------------------------------------- + output wire bridge_endian_little, + input wire [31:0] bridge_addr, + input wire bridge_rd, + output reg [31:0] bridge_rd_data, + input wire bridge_wr, + input wire [31:0] bridge_wr_data, + + //!--------------------------------------------------------------------- + //! Controller Data + //!--------------------------------------------------------------------- + input wire [31:0] cont1_key, + input wire [31:0] cont2_key, + input wire [31:0] cont3_key, + input wire [31:0] cont4_key, + input wire [31:0] cont1_joy, + input wire [31:0] cont2_joy, + input wire [31:0] cont3_joy, + input wire [31:0] cont4_joy, + input wire [15:0] cont1_trig, + input wire [15:0] cont2_trig, + input wire [15:0] cont3_trig, + input wire [15:0] cont4_trig + ); + + //!------------------------------------------------------------------------- + //! Infrared + //!------------------------------------------------------------------------- + // not using the IR port, so turn off both the LED, and + // disable the receive circuit to save power + assign port_ir_tx = 0; + assign port_ir_rx_disable = 1; + + //!------------------------------------------------------------------------- + //! Bridge endianness + //!------------------------------------------------------------------------- + assign bridge_endian_little = 0; + + //!------------------------------------------------------------------------- + //! GB/GBA Link Port + //!------------------------------------------------------------------------- + // link port is input only + assign port_tran_so = 1'bZ; + assign port_tran_so_dir = 1'b0; // SO is output only + assign port_tran_si = 1'bZ; + assign port_tran_si_dir = 1'b0; // SI is input only + assign port_tran_sck = 1'bZ; + assign port_tran_sck_dir = 1'b0; // clock direction can change + assign port_tran_sd = 1'bZ; + assign port_tran_sd_dir = 1'b0; // SD is input and not used + + //!------------------------------------------------------------------------- + //! MISC + //!------------------------------------------------------------------------- + assign dbg_tx = 1'bZ; + assign user1 = 1'bZ; + assign aux_scl = 1'bZ; + assign vpll_feed = 1'bZ; + + //! Tie off the memory the pins not being used ///////////////////////////// + generate + //!--------------------------------------------------------------------- + //! Cartridge Slot + //!--------------------------------------------------------------------- + // cart is unused, so set all level translators accordingly + // directions are 0:IN, 1:OUT + if(USE_ANALOGIZER == 0) begin + assign cart_tran_bank3 = 8'hZZ; + assign cart_tran_bank3_dir = 1'b0; + assign cart_tran_bank2 = 8'hZZ; + assign cart_tran_bank2_dir = 1'b0; + assign cart_tran_bank1 = 8'hZZ; + assign cart_tran_bank1_dir = 1'b0; + assign cart_tran_bank0 = 4'hF; + assign cart_tran_bank0_dir = 1'b1; + assign cart_tran_pin30 = 1'b0; // reset or cs2, we let the hw control it by itself + assign cart_tran_pin30_dir = 1'bZ; + assign cart_pin30_pwroff_reset = 1'b0; // hardware can control this + assign cart_tran_pin31 = 1'bZ; // input + assign cart_tran_pin31_dir = 1'b0; // input + end + //!--------------------------------------------------------------------- + //! Cellular RAM + //!--------------------------------------------------------------------- + if(USE_CRAM0 == 0) begin + assign cram0_a = 'h0; + assign cram0_dq = {16{1'bZ}}; + assign cram0_clk = 0; + assign cram0_adv_n = 1; + assign cram0_cre = 0; + assign cram0_ce0_n = 1; + assign cram0_ce1_n = 1; + assign cram0_oe_n = 1; + assign cram0_we_n = 1; + assign cram0_ub_n = 1; + assign cram0_lb_n = 1; + end + if(USE_CRAM1 == 0) begin + assign cram1_a = 'h0; + assign cram1_dq = {16{1'bZ}}; + assign cram1_clk = 0; + assign cram1_adv_n = 1; + assign cram1_cre = 0; + assign cram1_ce0_n = 1; + assign cram1_ce1_n = 1; + assign cram1_oe_n = 1; + assign cram1_we_n = 1; + assign cram1_ub_n = 1; + assign cram1_lb_n = 1; + end + //!--------------------------------------------------------------------- + //! SDRAM + //!--------------------------------------------------------------------- + if(USE_SDRAM == 0) begin + assign dram_a = 'h0; + assign dram_ba = 'h0; + assign dram_dq = {16{1'bZ}}; + assign dram_dqm = 'h0; + assign dram_clk = 'h0; + assign dram_cke = 'h0; + assign dram_ras_n = 'h1; + assign dram_cas_n = 'h1; + assign dram_we_n = 'h1; + end + //!--------------------------------------------------------------------- + //! SRAM + //!--------------------------------------------------------------------- + if(USE_SRAM == 0) begin + assign sram_a = 'h0; + assign sram_dq = {16{1'bZ}}; + assign sram_oe_n = 1; + assign sram_we_n = 1; + assign sram_ub_n = 1; + assign sram_lb_n = 1; + end + endgenerate + + //!------------------------------------------------------------------------- + //! Host/Target Command Handler + //!------------------------------------------------------------------------- + wire reset_n; // driven by host commands, can be used as core-wide reset + wire [31:0] cmd_bridge_rd_data; + + // bridge host commands + // synchronous to clk_74a + wire status_boot_done = pll_core_locked_s; + wire status_setup_done = pll_core_locked_s; // rising edge triggers a target command + wire status_running = reset_n; // we are running as soon as reset_n goes high + + wire dataslot_requestread; + wire [15:0] dataslot_requestread_id; + wire dataslot_requestread_ack = 1; + wire dataslot_requestread_ok = 1; + + wire dataslot_requestwrite; + wire [15:0] dataslot_requestwrite_id; + wire [31:0] dataslot_requestwrite_size; + wire dataslot_requestwrite_ack = 1; + wire dataslot_requestwrite_ok = 1; + + wire dataslot_update; + wire [15:0] dataslot_update_id; + wire [31:0] dataslot_update_size; + + wire dataslot_allcomplete; + + wire [31:0] rtc_epoch_seconds; + wire [31:0] rtc_date_bcd; + wire [31:0] rtc_time_bcd; + wire rtc_valid; + + wire savestate_supported; + wire [31:0] savestate_addr; + wire [31:0] savestate_size; + wire [31:0] savestate_maxloadsize; + + wire savestate_start; + wire savestate_start_ack; + wire savestate_start_busy; + wire savestate_start_ok; + wire savestate_start_err; + + wire savestate_load; + wire savestate_load_ack; + wire savestate_load_busy; + wire savestate_load_ok; + wire savestate_load_err; + + wire osnotify_inmenu; + wire osnotify_docked; + wire osnotify_grayscale; + + // bridge target commands + // synchronous to clk_74a + reg target_dataslot_read; + reg target_dataslot_write; + reg target_dataslot_getfile; // require additional param/resp structs to be mapped + reg target_dataslot_openfile; // require additional param/resp structs to be mapped + + wire target_dataslot_ack; + wire target_dataslot_done; + wire [2:0] target_dataslot_err; + + reg [15:0] target_dataslot_id; + reg [31:0] target_dataslot_slotoffset; + reg [31:0] target_dataslot_bridgeaddr; + reg [31:0] target_dataslot_length; + + wire [31:0] target_buffer_param_struct; // to be mapped/implemented when using some Target commands + wire [31:0] target_buffer_resp_struct; // to be mapped/implemented when using some Target commands + + // bridge data slot access + // synchronous to clk_74a + wire [9:0] datatable_addr; + wire datatable_wren; + wire [31:0] datatable_data; + wire [31:0] datatable_q; + + core_bridge_cmd u_pocket_apf_bridge + ( + .clk ( clk_74a ), + .reset_n ( reset_n ), + + .bridge_endian_little ( bridge_endian_little ), + .bridge_addr ( bridge_addr ), + .bridge_rd ( bridge_rd ), + .bridge_rd_data ( cmd_bridge_rd_data ), + .bridge_wr ( bridge_wr ), + .bridge_wr_data ( bridge_wr_data ), + + .status_boot_done ( status_boot_done ), + .status_setup_done ( status_setup_done ), + .status_running ( status_running ), + + .dataslot_requestread ( dataslot_requestread ), + .dataslot_requestread_id ( dataslot_requestread_id ), + .dataslot_requestread_ack ( dataslot_requestread_ack ), + .dataslot_requestread_ok ( dataslot_requestread_ok ), + + .dataslot_requestwrite ( dataslot_requestwrite ), + .dataslot_requestwrite_id ( dataslot_requestwrite_id ), + .dataslot_requestwrite_size ( dataslot_requestwrite_size ), + .dataslot_requestwrite_ack ( dataslot_requestwrite_ack ), + .dataslot_requestwrite_ok ( dataslot_requestwrite_ok ), + + .dataslot_update ( dataslot_update ), + .dataslot_update_id ( dataslot_update_id ), + .dataslot_update_size ( dataslot_update_size ), + + .dataslot_allcomplete ( dataslot_allcomplete ), + + .rtc_epoch_seconds ( rtc_epoch_seconds ), + .rtc_date_bcd ( rtc_date_bcd ), + .rtc_time_bcd ( rtc_time_bcd ), + .rtc_valid ( rtc_valid ), + + .savestate_supported ( savestate_supported ), + .savestate_addr ( savestate_addr ), + .savestate_size ( savestate_size ), + .savestate_maxloadsize ( savestate_maxloadsize ), + + .savestate_start ( savestate_start ), + .savestate_start_ack ( savestate_start_ack ), + .savestate_start_busy ( savestate_start_busy ), + .savestate_start_ok ( savestate_start_ok ), + .savestate_start_err ( savestate_start_err ), + + .savestate_load ( savestate_load ), + .savestate_load_ack ( savestate_load_ack ), + .savestate_load_busy ( savestate_load_busy ), + .savestate_load_ok ( savestate_load_ok ), + .savestate_load_err ( savestate_load_err ), + + .osnotify_inmenu ( osnotify_inmenu ), + .osnotify_docked ( osnotify_docked ), + .osnotify_grayscale ( osnotify_grayscale ), + + .target_dataslot_read ( target_dataslot_read ), + .target_dataslot_write ( target_dataslot_write ), + .target_dataslot_getfile ( target_dataslot_getfile ), + .target_dataslot_openfile ( target_dataslot_openfile ), + + .target_dataslot_ack ( target_dataslot_ack ), + .target_dataslot_done ( target_dataslot_done ), + .target_dataslot_err ( target_dataslot_err ), + + .target_dataslot_id ( target_dataslot_id ), + .target_dataslot_slotoffset ( target_dataslot_slotoffset ), + .target_dataslot_bridgeaddr ( target_dataslot_bridgeaddr ), + .target_dataslot_length ( target_dataslot_length ), + + .target_buffer_param_struct ( target_buffer_param_struct ), + .target_buffer_resp_struct ( target_buffer_resp_struct ), + + .datatable_addr ( datatable_addr ), + .datatable_wren ( datatable_wren ), + .datatable_data ( datatable_data ), + .datatable_q ( datatable_q ) + ); + + //! END OF APF ///////////////////////////////////////////////////////////// + + //! //////////////////////////////////////////////////////////////////////// + //! @ System Modules + //! //////////////////////////////////////////////////////////////////////// + + //!------------------------------------------------------------------------- + //! APF Bridge Read Data + //!------------------------------------------------------------------------- + wire [31:0] int_bridge_rd_data; + wire [31:0] nvm_bridge_rd_data, nvm_bridge_rd_data_s; + + // Synchronize nvm_bridge_rd_data into clk_74a domain before usage + synch_3 #(32) u_sync_nvm(nvm_bridge_rd_data, nvm_bridge_rd_data_s, clk_74a); + + always_comb begin + casex(bridge_addr) + 32'hF8xxxxxx: begin bridge_rd_data <= cmd_bridge_rd_data; end // APF Bridge (Reserved) + 32'h10000000: begin bridge_rd_data <= nvm_bridge_rd_data_s; end // HiScore/NVRAM/SRAM Save + 32'hF0000000: begin bridge_rd_data <= int_bridge_rd_data; end // Reset + 32'hF0000010: begin bridge_rd_data <= int_bridge_rd_data; end // Service Mode Switch + 32'hF1000000: begin bridge_rd_data <= int_bridge_rd_data; end // DIP Switches + 32'hF2000000: begin bridge_rd_data <= int_bridge_rd_data; end // Modifiers + 32'hF3000000: begin bridge_rd_data <= int_bridge_rd_data; end // A/V Filters + 32'hF4000000: begin bridge_rd_data <= int_bridge_rd_data; end // Extra DIP Switches + 32'hF5000000: begin bridge_rd_data <= int_bridge_rd_data; end // NVRAM Size + 32'hFA000000: begin bridge_rd_data <= int_bridge_rd_data; end // Status Low [31:0] + 32'hFB000000: begin bridge_rd_data <= int_bridge_rd_data; end // Status High [63:32] + 32'hFC000000: begin bridge_rd_data <= int_bridge_rd_data; end // Inputs + 32'hA0000000: begin bridge_rd_data <= int_bridge_rd_data; end // Analogizer Settings + default: begin bridge_rd_data <= 32'h0; end + endcase + end + + //!------------------------------------------------------------------------- + //! Pause Core (Analogue OS Menu/Module Request) + //!------------------------------------------------------------------------- + wire pause_core, pause_req; + + pause_crtl u_core_pause + ( + .clk_sys ( clk_sys ), + .os_inmenu ( osnotify_inmenu ), + .pause_req ( pause_req ), + .pause_core ( pause_core ) + ); + + //!------------------------------------------------------------------------- + //! Interact: Dip Switches, Modifiers, Filters and Reset + //!------------------------------------------------------------------------- + wire reset_sw, svc_sw; + wire [7:0] dip_sw0, dip_sw1, dip_sw2, dip_sw3; + wire [7:0] ext_sw0, ext_sw1, ext_sw2, ext_sw3; + wire [7:0] mod_sw0, mod_sw1, mod_sw2, mod_sw3; + wire [7:0] inp_sw0, inp_sw1, inp_sw2, inp_sw3; + wire [3:0] scnl_sw, smask_sw, afilter_sw, vol_att; + wire [63:0] status; + wire [15:0] nvram_size; + wire [31:0] analogizer_sw; + + interact u_pocket_interact + ( + // Clocks and Reset + .clk_74a ( clk_74a ), // [i] + .clk_sync ( clk_sys ), // [i] + .reset_n ( reset_n ), // [i] + // Reset Switch + .reset_sw ( reset_sw ), // [o] + // Service Mode Switch + .svc_sw ( svc_sw ), // [o] + // DIP Switches + .dip_sw0 ( dip_sw0 ), // [o] + .dip_sw1 ( dip_sw1 ), // [o] + .dip_sw2 ( dip_sw2 ), // [o] + .dip_sw3 ( dip_sw3 ), // [o] + // Extra DIP Switches + .ext_sw0 ( ext_sw0 ), // [o] + .ext_sw1 ( ext_sw1 ), // [o] + .ext_sw2 ( ext_sw2 ), // [o] + .ext_sw3 ( ext_sw3 ), // [o] + // Modifiers + .mod_sw0 ( mod_sw0 ), // [o] + .mod_sw1 ( mod_sw1 ), // [o] + .mod_sw2 ( mod_sw2 ), // [o] + .mod_sw3 ( mod_sw3 ), // [o] + // Inputs Switches + .inp_sw0 ( inp_sw0 ), // [o] + .inp_sw1 ( inp_sw1 ), // [o] + .inp_sw2 ( inp_sw2 ), // [o] + .inp_sw3 ( inp_sw3 ), // [o] + // Status (Legacy Support) + .status ( status ), // [o] + // Filters Switches + .scnl_sw ( scnl_sw ), // [o] + .smask_sw ( smask_sw ), // [o] + .afilter_sw ( afilter_sw ), // [o] + .vol_att ( vol_att ), // [o] + // NVRAM/High Score + .nvram_size ( nvram_size ), // [o] + // Analogizer + .analogizer_sw ( analogizer_sw ), // [o] + // Pocket Bridge + .bridge_addr ( bridge_addr ), // [i] + .bridge_wr ( bridge_wr ), // [i] + .bridge_wr_data ( bridge_wr_data ), // [i] + .bridge_rd ( bridge_rd ), // [i] + .bridge_rd_data ( int_bridge_rd_data ) // [o] + ); + + //!------------------------------------------------------------------------- + //! Audio + //!------------------------------------------------------------------------- + wire [AUDIO_DW-1:0] core_snd_l, core_snd_r; // Audio Mono/Left/Right + + audio_mixer #(.DW(AUDIO_DW),.MUTE_PAUSE(MUTE_PAUSE),.STEREO(STEREO)) u_pocket_audio_mixer + ( + // Clocks and Reset + .clk_74b ( clk_74b ), + .clk_sys ( clk_sys ), + .reset ( reset_sw ), + // Controls + .afilter_sw ( afilter_sw ), + .vol_att ( vol_att ), + .mix ( AUDIO_MIX ), + .pause_core ( pause_core ), + // Audio From Core + .is_signed ( AUDIO_S ), + .core_l ( core_snd_l ), + .core_r ( core_snd_r ), + // I2S + .audio_mclk ( audio_mclk ), + .audio_lrck ( audio_lrck ), + .audio_dac ( audio_dac ) + ); + + //!------------------------------------------------------------------------- + //! Video + //!------------------------------------------------------------------------- + wire grayscale_en; // Enable Grayscale Output + wire [2:0] video_preset; // Video Preset Configuration + wire [BPP_R-1:0] core_r; // Video Red + wire [BPP_G-1:0] core_g; // Video Green + wire [BPP_B-1:0] core_b; // Video Blue + wire core_hs, core_hb; // Horizontal Sync/Blank + wire core_vs, core_vb; // Vertical Sync/Blank + wire interlaced, field; // Interlaced Video | Even/Odd Field + + wire [5:0] vga_r, vga_g, vga_b; // VGA RGB + wire vga_vs, vga_hs, vga_de; // VGA H/V Sync and Display Enable (Blank_N) + + synch_3 sync_bwmode(osnotify_grayscale, grayscale_en, clk_vid); + + video_mixer #( + .RW ( BPP_R ), // [p] + .GW ( BPP_G ), // [p] + .BW ( BPP_B ), // [p] + .ENABLE_INTERLACED ( USE_INTERLACED ), // [p] + .USE_VBL ( USE_VBL ) // [p] + ) u_pocket_video_mixer ( + // Clocks + .clk_74a ( clk_74a ), // [i] + .clk_sys ( clk_sys ), // [i] + .clk_vid ( clk_vid ), // [i] + .clk_vid_90deg ( clk_vid_90deg ), // [i] + // Input Controls + .grayscale_en ( grayscale_en ), // [i] + .video_preset ( video_preset ), // [i] + .scnl_sw ( scnl_sw ), // [i] + .smask_sw ( smask_sw ), // [i] + // Interlaced Video Controls + .field ( field ), // [i] + .interlaced ( interlaced ), // [i] + // Input Video from Core + .core_r ( core_r ), // [i] + .core_g ( core_g ), // [i] + .core_b ( core_b ), // [i] + .core_hs ( core_hs ), // [i] + .core_vs ( core_vs ), // [i] + .core_hb ( core_hb ), // [i] + .core_vb ( core_vb ), // [i] + // Output to Display + .video_rgb ( video_rgb ), // [o] + .video_hs ( video_hs ), // [o] + .video_vs ( video_vs ), // [o] + .video_de ( video_de ), // [o] + .video_skip ( video_skip ), // [o] + .video_rgb_clock ( video_rgb_clock ), // [o] + .video_rgb_clock_90 ( video_rgb_clock_90 ), // [o] + // Input Video from Core + .vga_r ( vga_r ), // [o] + .vga_g ( vga_g ), // [o] + .vga_b ( vga_b ), // [o] + .vga_vs ( vga_vs ), // [o] + .vga_hs ( vga_hs ), // [o] + .vga_de ( vga_de ) // [o] + ); + + //!------------------------------------------------------------------------- + //! Data I/O + //!------------------------------------------------------------------------- + wire ioctl_download; + wire [15:0] ioctl_index; + wire ioctl_wr; + wire [DIO_AW-1:0] ioctl_addr; + wire [DIO_DW-1:0] ioctl_data; + + data_io #(.MASK(DIO_MASK),.AW(DIO_AW),.DW(DIO_DW),.DELAY(DIO_DELAY),.HOLD(DIO_HOLD)) u_pocket_data_io + ( + // Clocks and Reset + .clk_74a ( clk_74a ), // [i] + .clk_memory ( clk_sys ), // [i] + // Pocket Bridge Slots + .dataslot_requestwrite ( dataslot_requestwrite ), // [i] + .dataslot_requestwrite_id ( dataslot_requestwrite_id ), // [i] + .dataslot_allcomplete ( dataslot_allcomplete ), // [i] + // MPU -> FPGA (MPU Write to FPGA) + // Pocket Bridge + .bridge_endian_little ( bridge_endian_little ), // [i] + .bridge_addr ( bridge_addr ), // [i] + .bridge_wr ( bridge_wr ), // [i] + .bridge_wr_data ( bridge_wr_data ), // [i] + // Controller Interface + .ioctl_download ( ioctl_download ), // [o] + .ioctl_index ( ioctl_index ), // [o] + .ioctl_wr ( ioctl_wr ), // [o] + .ioctl_addr ( ioctl_addr ), // [o] + .ioctl_data ( ioctl_data ) // [o] + ); + + //!------------------------------------------------------------------------- + //! Gamepad/Analog Stick + //!------------------------------------------------------------------------- + // Player 1 + // - DPAD + wire p1_up, p1_down, p1_left, p1_right; + wire p1_btn_y, p1_btn_x, p1_btn_b, p1_btn_a; + wire p1_btn_l1, p1_btn_l2, p1_btn_l3; + wire p1_btn_r1, p1_btn_r2, p1_btn_r3; + wire p1_select, p1_start; + // - Analog + wire j1_up, j1_down, j1_left, j1_right; + wire [7:0] j1_lx, j1_ly, j1_rx, j1_ry; + + // Player 2 + // - DPAD + wire p2_up, p2_down, p2_left, p2_right; + wire p2_btn_y, p2_btn_x, p2_btn_b, p2_btn_a; + wire p2_btn_l1, p2_btn_l2, p2_btn_l3; + wire p2_btn_r1, p2_btn_r2, p2_btn_r3; + wire p2_select, p2_start; + // - Analog + wire j2_up, j2_down, j2_left, j2_right; + wire [7:0] j2_lx, j2_ly, j2_rx, j2_ry; + + // Player 3 + // - DPAD + wire p3_up, p3_down, p3_left, p3_right; + wire p3_btn_y, p3_btn_x, p3_btn_b, p3_btn_a; + wire p3_btn_l1, p3_btn_l2, p3_btn_l3; + wire p3_btn_r1, p3_btn_r2, p3_btn_r3; + wire p3_select, p3_start; + // - Analog + wire j3_up, j3_down, j3_left, j3_right; + wire [7:0] j3_lx, j3_ly, j3_rx, j3_ry; + + // Player 4 + // - DPAD + wire p4_up, p4_down, p4_left, p4_right; + wire p4_btn_y, p4_btn_x, p4_btn_b, p4_btn_a; + wire p4_btn_l1, p4_btn_l2, p4_btn_l3; + wire p4_btn_r1, p4_btn_r2, p4_btn_r3; + wire p4_select, p4_start; + // - Analog + wire j4_up, j4_down, j4_left, j4_right; + wire [7:0] j4_lx, j4_ly, j4_rx, j4_ry; + + // Single Player or Alternate 2 Players for Arcade + wire m_start1, m_start2; + wire m_coin1, m_coin2, m_coin; + wire m_up, m_down, m_left, m_right; + wire m_btn1, m_btn2, m_btn3, m_btn4; + wire m_btn5, m_btn6, m_btn7, m_btn8; + + gamepad #(.JOY_PADS(JOY_PADS),.JOY_ALT(JOY_ALT)) u_pocket_gamepad + ( + .clk_sys ( clk_sys ), + // Pocket PAD Interface + .cont1_key ( cont1_key ), .cont1_joy ( cont1_joy ), // [i] + .cont2_key ( cont2_key ), .cont2_joy ( cont2_joy ), // [i] + .cont3_key ( cont3_key ), .cont3_joy ( cont3_joy ), // [i] + .cont4_key ( cont4_key ), .cont4_joy ( cont4_joy ), // [i] + // Input DIP Switches + .inp_sw0 ( inp_sw0 ), .inp_sw1 ( inp_sw1 ), // [i] + .inp_sw2 ( inp_sw2 ), .inp_sw3 ( inp_sw3 ), // [i] + // Player 1 + .p1_up ( p1_up ), .p1_down ( p1_down ), // [o] + .p1_left ( p1_left ), .p1_right ( p1_right ), // [o] + .p1_y ( p1_btn_y ), .p1_x ( p1_btn_x ), // [o] + .p1_b ( p1_btn_b ), .p1_a ( p1_btn_a ), // [o] + .p1_l1 ( p1_btn_l1 ), .p1_r1 ( p1_btn_r1 ), // [o] + .p1_l2 ( p1_btn_l2 ), .p1_r2 ( p1_btn_r2 ), // [o] + .p1_l3 ( p1_btn_l3 ), .p1_r3 ( p1_btn_r3 ), // [o] + .p1_se ( p1_select ), .p1_st ( p1_start ), // [o] + .j1_up ( j1_up ), .j1_down ( j1_down ), // [o] + .j1_left ( j1_left ), .j1_right ( j1_right ), // [o] + .j1_lx ( j1_lx ), .j1_ly ( j1_ly ), // [o] + .j1_rx ( j1_rx ), .j1_ry ( j1_ry ), // [o] + // Player 2 + .p2_up ( p2_up ), .p2_down ( p2_down ), // [o] + .p2_left ( p2_left ), .p2_right ( p2_right ), // [o] + .p2_y ( p2_btn_y ), .p2_x ( p2_btn_x ), // [o] + .p2_b ( p2_btn_b ), .p2_a ( p2_btn_a ), // [o] + .p2_l1 ( p2_btn_l1 ), .p2_r1 ( p2_btn_r1 ), // [o] + .p2_l2 ( p2_btn_l2 ), .p2_r2 ( p2_btn_r2 ), // [o] + .p2_l3 ( p2_btn_l3 ), .p2_r3 ( p2_btn_r3 ), // [o] + .p2_se ( p2_select ), .p2_st ( p2_start ), // [o] + .j2_up ( j2_up ), .j2_down ( j2_down ), // [o] + .j2_left ( j2_left ), .j2_right ( j2_right ), // [o] + .j2_lx ( j2_lx ), .j2_ly ( j2_ly ), // [o] + .j2_rx ( j2_rx ), .j2_ry ( j2_ry ), // [o] + // Player 3 + .p3_up ( p3_up ), .p3_down ( p3_down ), // [o] + .p3_left ( p3_left ), .p3_right ( p3_right ), // [o] + .p3_y ( p3_btn_y ), .p3_x ( p3_btn_x ), // [o] + .p3_b ( p3_btn_b ), .p3_a ( p3_btn_a ), // [o] + .p3_l1 ( p3_btn_l1 ), .p3_r1 ( p3_btn_r1 ), // [o] + .p3_l2 ( p3_btn_l2 ), .p3_r2 ( p3_btn_r2 ), // [o] + .p3_l3 ( p3_btn_l3 ), .p3_r3 ( p3_btn_r3 ), // [o] + .p3_se ( p3_select ), .p3_st ( p3_start ), // [o] + .j3_up ( j3_up ), .j3_down ( j3_down ), // [o] + .j3_left ( j3_left ), .j3_right ( j3_right ), // [o] + .j3_lx ( j3_lx ), .j3_ly ( j3_ly ), // [o] + .j3_rx ( j3_rx ), .j3_ry ( j3_ry ), // [o] + // Player 4 + .p4_up ( p4_up ), .p4_down ( p4_down ), // [o] + .p4_left ( p4_left ), .p4_right ( p4_right ), // [o] + .p4_y ( p4_btn_y ), .p4_x ( p4_btn_x ), // [o] + .p4_b ( p4_btn_b ), .p4_a ( p4_btn_a ), // [o] + .p4_l1 ( p4_btn_l1 ), .p4_r1 ( p4_btn_r1 ), // [o] + .p4_l2 ( p4_btn_l2 ), .p4_r2 ( p4_btn_r2 ), // [o] + .p4_l3 ( p4_btn_l3 ), .p4_r3 ( p4_btn_r3 ), // [o] + .p4_se ( p4_select ), .p4_st ( p4_start ), // [o] + .j4_up ( j4_up ), .j4_down ( j4_down ), // [o] + .j4_left ( j4_left ), .j4_right ( j4_right ), // [o] + .j4_lx ( j4_lx ), .j4_ly ( j4_ly ), // [o] + .j4_rx ( j4_rx ), .j4_ry ( j4_ry ) // [o] + ); + + //!------------------------------------------------------------------------- + //! HiScore NVRAM/SRAM Save I/O + //!------------------------------------------------------------------------- + wire [HS_AW-1:0] hs_address; + wire [7:0] hs_data_out; + wire [7:0] hs_data_in; + wire hs_write_en; + wire hs_access_read; + wire hs_access_write; + wire hs_configured; + + hiscore_io #( + // HiScore NVRAM + .HS_AW ( HS_AW ), // [p] + .HS_SW ( HS_SW ), // [p] + .HS_CFG_AW ( HS_CFG_AW ), // [p] + .HS_CFG_LW ( HS_CFG_LW ), // [p] + .HS_CONFIG ( HS_CONFIG ), // [p] + .HS_DATA ( HS_DATA ), // [p] + // MPU <-> FPGA (Data I/O) + .HS_MASK ( HS_MASK ), // [p] + .HS_WR_DELAY ( HS_WR_DELAY ), // [p] + .HS_WR_HOLD ( HS_WR_HOLD ), // [p] + .HS_RD_DELAY ( HS_RD_DELAY ) // [p] + ) u_pocket_hiscore_io ( + .clk_74a ( clk_74a ), // [i] + .clk_memory ( clk_sys ), // [i] + .pll_core_locked ( pll_core_locked_s ), // [i] + .reset_sw ( reset_sw ), // [i] + .pause_core ( pause_core ), // [i] + // Bridge Data Slots + .dataslot_requestwrite ( dataslot_requestwrite ), // [i] + .dataslot_requestwrite_id ( dataslot_requestwrite_id ), // [i] + .dataslot_requestread ( dataslot_requestread ), // [i] + .dataslot_requestread_id ( dataslot_requestread_id ), // [i] + .dataslot_allcomplete ( dataslot_allcomplete ), // [i] + // Bridge Write/Read to/From FPGA) + .bridge_endian_little ( bridge_endian_little ), // [i] + .bridge_addr ( bridge_addr ), // [i] + .bridge_wr ( bridge_wr ), // [i] + .bridge_wr_data ( bridge_wr_data ), // [i] + .bridge_rd ( bridge_rd ), // [i] + .bridge_rd_data ( nvm_bridge_rd_data ), // [o] + // Pocket Bridge Data Tables + .datatable_addr ( datatable_addr ), // [o] + .datatable_wren ( datatable_wren ), // [o] + .datatable_data ( datatable_data ), // [o] + // HiScore NVRAM Size + .nvram_size ( nvram_size ), // [i] Number of bytes required for Save + // HiScore Interface + .hs_write_en ( hs_write_en ), // [o] Write to game RAM (active high) + .hs_address ( hs_address ), // [o] Address in game RAM to read/write score data + .hs_data_in ( hs_data_in ), // [o] Data to send to game RAM + .hs_data_out ( hs_data_out ), // [i] Incoming data from game RAM + .hs_access_read ( hs_access_read ), // [o] + .hs_access_write ( hs_access_write ), // [o] + .hs_configured ( hs_configured ), // [o] + .hs_pause ( pause_req ) // [o] Pause core CPU to prepare for/relax after RAM access + ); + + //! ------------------------------------------------------------------------ + //! Clocks + //! ------------------------------------------------------------------------ + wire pll_core_locked, pll_core_locked_s; + wire clk_sys; //! Core : 40.000002Mhz + wire clk_vid; //! Video: 6.666667Mhz + wire clk_vid_90deg; //! Video: 6.666667Mhz @ 90deg Phase Shift + wire clk_ram; //! SDRAM: 120.000006Mhz + + core_pll core_pll + ( + .refclk ( clk_74a ), // [i] + .rst ( 0 ), // [i] + + .outclk_0 ( clk_ram ), // [o] + .outclk_1 ( clk_sys ), // [o] + .outclk_2 ( clk_vid ), // [o] + .outclk_3 ( clk_vid_90deg ), // [o] + + .locked ( pll_core_locked ) // [o] + ); + + // Synchronize pll_core_locked into clk_74a domain before usage + synch_3 sync_lck(pll_core_locked, pll_core_locked_s, clk_74a); + + //! ------------------------------------------------------------------------ + //! @ IP Core RTL + //! ------------------------------------------------------------------------ + irem_m92 u_irem_m92_top + ( + .clk_sys ( clk_sys ), // [i] + .clk_ram ( clk_ram ), // [i] + .pll_locked ( pll_core_locked_s ), // [i] + + .reset ( reset_sw ), // [i] + .pause ( pause_core ), // [i] + + .mod_sw ( mod_sw0 ), // [i] + .dsw_1 ( dip_sw0 ), // [i] + .dsw_2 ( dip_sw1 ), // [i] + .dsw_3 ( dip_sw2 ), // [i] + + .p1_coin ( p1_select ), .p2_coin ( p2_select ), // [i] + .p1_start ( p1_start ), .p2_start ( p2_start ), // [i] + .p1_up ( p1_up ), .p2_up ( p2_up ), // [i] + .p1_left ( p1_left ), .p2_left ( p2_left ), // [i] + .p1_down ( p1_down ), .p2_down ( p2_down ), // [i] + .p1_right ( p1_right ), .p2_right ( p2_right ), // [i] + .p1_btn_y ( p1_btn_y ), .p2_btn_y ( p2_btn_y ), // [i] + .p1_btn_x ( p1_btn_x ), .p2_btn_x ( p2_btn_x ), // [i] + .p1_btn_b ( p1_btn_b ), .p2_btn_b ( p2_btn_b ), // [i] + .p1_btn_a ( p1_btn_a ), .p2_btn_a ( p2_btn_a ), // [i] + .p1_btn_l ( p1_btn_l1 ), .p2_btn_l ( p2_btn_l1 ), // [i] + .p1_btn_r ( p1_btn_r1 ), .p2_btn_r ( p2_btn_r1 ), // [i] + + .p3_coin ( p3_select ), .p4_coin ( p4_select ), // [i] + .p3_start ( p3_start ), .p4_start ( p4_start ), // [i] + .p3_up ( p3_up ), .p4_up ( p4_up ), // [i] + .p3_left ( p3_left ), .p4_left ( p4_left ), // [i] + .p3_down ( p3_down ), .p4_down ( p4_down ), // [i] + .p3_right ( p3_right ), .p4_right ( p4_right ), // [i] + .p3_btn_y ( p3_btn_y ), .p4_btn_y ( p4_btn_y ), // [i] + .p3_btn_x ( p3_btn_x ), .p4_btn_x ( p4_btn_x ), // [i] + .p3_btn_b ( p3_btn_b ), .p4_btn_b ( p4_btn_b ), // [i] + .p3_btn_a ( p3_btn_a ), .p4_btn_a ( p4_btn_a ), // [i] + .p3_btn_l ( p3_btn_l1 ), .p4_btn_l ( p4_btn_l1 ), // [i] + .p3_btn_r ( p3_btn_r1 ), .p4_btn_r ( p4_btn_r1 ), // [i] + + .audio_l ( core_snd_l ), // [o] + .audio_r ( core_snd_r ), // [o] + + .video_r ( core_r ), // [o] + .video_g ( core_g ), // [o] + .video_b ( core_b ), // [o] + .video_hs ( core_hs ), // [o] + .video_vs ( core_vs ), // [o] + .video_hb ( core_hb ), // [o] + .video_vb ( core_vb ), // [o] + + .video_preset ( video_preset ), // [o] + + .ioctl_index ( ioctl_index ), // [i] + .ioctl_download ( ioctl_download ), // [i] + .ioctl_wr ( ioctl_wr ), // [i] + .ioctl_addr ( ioctl_addr ), // [i] + .ioctl_data ( ioctl_data ), // [i] + + .sdram_clk ( dram_clk ), // [o] + .sdram_cke ( dram_cke ), // [o] + .sdram_dq ( dram_dq ), // [b] + .sdram_a ( dram_a ), // [o] + .sdram_dqml ( dram_dqm[0] ), // [o] + .sdram_dqmh ( dram_dqm[1] ), // [o] + .sdram_ba ( dram_ba ), // [o] + .sdram_we_n ( dram_we_n ), // [o] + .sdram_ras_n ( dram_ras_n ), // [o] + .sdram_cas_n ( dram_cas_n ) // [o] + ); + +endmodule