mirror of
https://github.com/MiSTer-devel/ZXNext_MISTer.git
synced 2026-05-17 03:05:00 +00:00
Initial commit.
This commit is contained in:
39
.gitignore
vendored
Normal file
39
.gitignore
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
db
|
||||
greybox_tmp
|
||||
incremental_db
|
||||
output_files
|
||||
simulation
|
||||
hc_output
|
||||
scaler
|
||||
hps_isw_handoff
|
||||
vip
|
||||
*_sim
|
||||
.qsys_edit
|
||||
PLLJ_PLLSPE_INFO.txt
|
||||
*.bak
|
||||
*.orig
|
||||
*.rej
|
||||
*.qdf
|
||||
*.rpt
|
||||
*.smsg
|
||||
*.summary
|
||||
*.done
|
||||
*.jdi
|
||||
*.pin
|
||||
*.sof
|
||||
*.qws
|
||||
*.ppf
|
||||
*.ddb
|
||||
build_id.v
|
||||
c5_pin_model_dump.txt
|
||||
*.sopcinfo
|
||||
*.csv
|
||||
*.f
|
||||
*.cmp
|
||||
*.sip
|
||||
*.spd
|
||||
*.bsf
|
||||
*~
|
||||
*.xml
|
||||
*_netlist
|
||||
*.cdf
|
||||
339
LICENSE
Normal file
339
LICENSE
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) 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
|
||||
this service 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 make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. 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.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
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
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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 a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE 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.
|
||||
|
||||
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
|
||||
convey 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 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.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision 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, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This 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.
|
||||
59
README.md
Normal file
59
README.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# [ZX Spectrum Next](https://www.specnext.com/) port for MiSTer
|
||||
|
||||
## MiSTer specifics
|
||||
- Uses SDRAM instead of SRAM. Some wait states are added in 14MHz and 28MHz modes.
|
||||
- Bootstrap option to load other cores is not supported (obviously).
|
||||
- Video modes for VGA and HDMI aren't supported (MiSTer uses its own HDMI settings).
|
||||
- Added standard wide screen video crop and HV-Integer scaling for HDMI.
|
||||
|
||||
Note: in latest version of Next sources hardreset has beed removed. So to get into
|
||||
boot configuration you have to re-load the core.
|
||||
|
||||
|
||||
## Installation
|
||||
- Place rbf into root of SD card.
|
||||
- Unpack and place boot.vhd into `/Games/ZXNext` folder. Alternatively you can rename it to ZXNext.vhd and place into root of SD card.
|
||||
|
||||
|
||||
## Hotkeys
|
||||
* F1 - reset
|
||||
* F3 - toggle 50Hz/60Hz modes
|
||||
* F8 - change CPU speed: 3.5MHz, 7MHz, 14MHz, 28MHz
|
||||
* F10 - DivMMC NMI
|
||||
* F11 - NMI/Multiface
|
||||
|
||||
|
||||
## Original specs:
|
||||
|
||||
A brief summary of the current machine specifications:
|
||||
|
||||
* **CPU** : Z80N (z80 compatible with some additional instructions) operable at software selectable speeds of 3.5 MHz, 7 MHz, 14 MHz or 28 MHz with wait states.
|
||||
* **COPPER** : A co-processor running independently of the cpu executes simple instructions that can modify the nextreg state. For example, it can change palettes, alter the display mode or play stereo music. The copper is synchronized with the display generation so it is able to make these changes at precise locations in the display.
|
||||
* **DMA** : The ZXN DMA, compatible with a subset of the Z80 DMA chip, is able to perform transfers between memory and/or io using short two cycle reads and writes. In burst mode, the zxn dma can send bytes at programmable rates allowing it to play sampled music while returning control to the cpu between transfers. At this time the zxn dma and the cpu share the bus and the dma operates at the currently set cpu speed.
|
||||
* **RAM MEMORY** : 768K of RAM in the unexpanded machine or 1792K of RAM in the expanded machine. This memory is available in 16K banks as in the original 128K Spectrums and can be mapped as usual using the standard ports 0x7ffd and 0x1ffd. An additional port 0xdffd adds bits to port 0x7ffd to reach all memory banks. The native bankswitching scheme in the zx next is called MMU. This scheme divides the same memory into 8K pages and allows any page to be mapped into any 8K slot of the Z80's 64K address space.
|
||||
* **ROM MEMORY** : 64K of ROM is reserved for ROMs 0-3 as in the Spectrum +3. Also available is 32K of Alt ROM that can replace the normal ROMs; this ROM is user programmable.
|
||||
* **GRAPHICS** : The display is composed of layers with programmable priority. Layers are listed below.
|
||||
* ULA : Compatible timing, contention and floating bus behaviour with the 48k, 128k, +3 and Pentagon. Supports hardware pixel scrolling in the X and Y directions and these resolutions:
|
||||
* 256x192 pixel 32x24 attributes in bank 5 (48k / 128k)
|
||||
* 256x192 pixel 32x24 attributes in bank 7 (128k second display)
|
||||
* 256x192 pixel 32x24 attributes at 0x6000 in bank 5 (timex second display)
|
||||
* 256x192 pixel 32x192 attributes at 0x4000 and 0x6000 in bank 5 (timex hi-colour)
|
||||
* 512x192 pixel monochrome at 0x4000 and 0x6000 in bank 5 (timex hi-res)
|
||||
* LoRes : Occupies the same layer as the ULA with LoRes replacing the ULA where it is enabled. Supports hardware pixel scrolling in the X and Y directions. Two resolutions are available:
|
||||
* 128x96 4-bit colour per pixel at either 0x4000 or 0x6000 in bank 5 (Radastan mode originating on the ZX UNO)
|
||||
* 128x96 8-bit colour per pixel occupying 0x4000 and 0x6000 in bank 5
|
||||
* Layer 2 : A pixel mapped display without colour clash. Supports hardware pixel scrolling in the X and Y directions. Can be mapped to any location in memory starting at a 16K boundary. Available resolutions are:
|
||||
* 256x192 8-bit colour per pixel
|
||||
* 320x256 8-bit colour per pixel
|
||||
* 640x256 4-bit colour per pixel
|
||||
* Sprites : Up to 128 hardware sprites of size 16x16 pixels with either 8-bits or 4-bits of colour per pixel. A minimum of 100 sprites per line can be display at this size. Sprites can be scaled 1x 2x 4x 8x, rotated, mirrored and linked together.
|
||||
* Tilemap : A hardware character display coming in two resolutions (80x32 = 640x256 pixels, 40x32 = 320x256). Supports hardware pixel scrolling in the X and Y directions. The character map and glyphs are stored at programmable locations in bank 5. Individual characters can be independently rotated and mirrored. Each glyph is 8x8 pixels in size with 4-bits of colour per pixel. Another mode eliminates rotation and mirroring in favour of 8x8 pixel glyphs defined as monochrome UDGs but with more colour information stored in the character map.
|
||||
|
||||
Some layer priority modes allow layer 2 to be highlighted or darkened by the ULA. Another setting allows the tilemap and ULA to stencil each other.
|
||||
* **SOUND** : Stereo sound is played through HDMI, 3.5mm audio jack or optional internal speaker. Sound sources:
|
||||
* Beeper : Beeps and tape sound.
|
||||
* 3 x AY 8910 : Arranged to be compatible with the dual arrangement turbosound. AY instances can be programmed as mono or either ABC or ACB stereo mode.
|
||||
* 4 x 8-bit DACs : Two DACs are assigned to the left channel and two are assigned to the right channel. Common 8-bit dac peripherals in the spectrum community such as specdrum and soundrive are mapped to these dacs.
|
||||
* Raspberry PI I2S : Audio generated by an optional Pi accelerator can be mixed into the internal next audio stream or can be mapped to ear for tape loading.
|
||||
|
||||
|
||||
33
ZXNext.qpf
Normal file
33
ZXNext.qpf
Normal file
@@ -0,0 +1,33 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# 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 MegaCore Function License Agreement, or other
|
||||
# applicable license agreement, including, without limitation,
|
||||
# that your use is for the sole purpose of programming logic
|
||||
# devices manufactured by Intel and sold by Intel or its
|
||||
# authorized distributors. Please refer to the applicable
|
||||
# agreement for further details.
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Quartus Prime
|
||||
# Version 17.0.2 Build 602 07/19/2017 SJ Lite Edition
|
||||
# Date created = 00:23:38 September 19, 2020
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
QUARTUS_VERSION = "17.0"
|
||||
DATE = "00:23:38 September 19, 2020"
|
||||
|
||||
# Revisions
|
||||
|
||||
PROJECT_REVISION = "ZXNext"
|
||||
PROJECT_REVISION = "200919"
|
||||
PROJECT_REVISION = "200918"
|
||||
64
ZXNext.qsf
Normal file
64
ZXNext.qsf
Normal file
@@ -0,0 +1,64 @@
|
||||
# --------------------------------------------------------------------------
|
||||
#
|
||||
# MiSTer project
|
||||
#
|
||||
# WARNING WARNING WARNING:
|
||||
# Do not add files to project in Quartus IDE! It will mess this file!
|
||||
# Add the files manually to files.qip file.
|
||||
#
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
set_global_assignment -name TOP_LEVEL_ENTITY sys_top
|
||||
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
||||
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Standard Edition"
|
||||
|
||||
set_global_assignment -name GENERATE_RBF_FILE ON
|
||||
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
|
||||
set_global_assignment -name SAVE_DISK_SPACE OFF
|
||||
set_global_assignment -name SMART_RECOMPILE ON
|
||||
set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40"
|
||||
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100
|
||||
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)"
|
||||
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF
|
||||
set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF
|
||||
set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS
|
||||
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
|
||||
set_global_assignment -name OPTIMIZATION_MODE "AGGRESSIVE PERFORMANCE"
|
||||
set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON
|
||||
set_global_assignment -name QII_AUTO_PACKED_REGISTERS "SPARSE AUTO"
|
||||
set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON
|
||||
set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED
|
||||
set_global_assignment -name MUX_RESTRUCTURE ON
|
||||
set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON
|
||||
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 ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON
|
||||
set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION ON
|
||||
set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON
|
||||
set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON
|
||||
set_global_assignment -name ECO_OPTIMIZE_TIMING ON
|
||||
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 ALM_REGISTER_PACKING_EFFORT LOW
|
||||
set_global_assignment -name SEED 1
|
||||
|
||||
#set_global_assignment -name VERILOG_MACRO "ARCADE_SYS=1"
|
||||
#set_global_assignment -name VERILOG_MACRO "USE_FB=1"
|
||||
#set_global_assignment -name VERILOG_MACRO "USE_SDRAM=1"
|
||||
#set_global_assignment -name VERILOG_MACRO "USE_DDRAM=1"
|
||||
|
||||
#do not enable DEBUG_NOHDMI in release!
|
||||
#set_global_assignment -name VERILOG_MACRO "DEBUG_NOHDMI=1"
|
||||
|
||||
source sys/sys.tcl
|
||||
source sys/sys_analog.tcl
|
||||
source files.qip
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
23
ZXNext.sdc
Normal file
23
ZXNext.sdc
Normal file
@@ -0,0 +1,23 @@
|
||||
derive_pll_clocks
|
||||
derive_clock_uncertainty
|
||||
|
||||
create_generated_clock -source [get_pins {emu|pll|pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] \
|
||||
-name CLK_i0 -divide_by 2 -duty_cycle 50 [get_nets {emu|zxnext_top|CLK_i0}]
|
||||
|
||||
create_generated_clock -source [get_pins {emu|pll|pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] \
|
||||
-name CLK_CPU -divide_by 1 -duty_cycle 50 [get_nets {emu|zxnext_top|CLK_CPU}]
|
||||
|
||||
set clk_sys {*|pll|pll_inst|altera_pll_i|*[0].*|divclk}
|
||||
set clk_56m {*|pll|pll_inst|altera_pll_i|*[1].*|divclk}
|
||||
set clk_14m {*|pll|pll_inst|altera_pll_i|*[2].*|divclk}
|
||||
set clk_7m {*|pll|pll_inst|altera_pll_i|*[3].*|divclk}
|
||||
set clk_mem {*|pll|pll_inst|altera_pll_i|*[4].*|divclk}
|
||||
|
||||
set_multicycle_path -from [get_clocks $clk_sys] -to [get_clocks $clk_7m] -start -setup 2
|
||||
set_multicycle_path -from [get_clocks $clk_sys] -to [get_clocks $clk_7m] -start -hold 1
|
||||
set_multicycle_path -from [get_clocks $clk_56m] -to [get_clocks CLK_CPU] -start -setup 2
|
||||
set_multicycle_path -from [get_clocks $clk_56m] -to [get_clocks CLK_CPU] -start -hold 1
|
||||
set_multicycle_path -from [get_clocks $clk_mem] -to [get_clocks CLK_CPU] -start -setup 2
|
||||
set_multicycle_path -from [get_clocks $clk_mem] -to [get_clocks CLK_CPU] -start -hold 1
|
||||
set_multicycle_path -from [get_clocks CLK_CPU] -to [get_clocks $clk_mem] -setup 2
|
||||
set_multicycle_path -from [get_clocks CLK_CPU] -to [get_clocks $clk_mem] -hold 1
|
||||
28
ZXNext.srf
Normal file
28
ZXNext.srf
Normal file
@@ -0,0 +1,28 @@
|
||||
{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_kbd_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_mouse_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Synthesized away node \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|outclk_wire\[2\]\"" { } { } 0 14320 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[1\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Ignored locations or region assignments to the following nodes" { } { } 0 15705 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[2\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(129): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(134): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(97): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(102): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_hdmi:pll_hdmi\|pll_hdmi_0002:pll_hdmi_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Found combinational loop of 47 nodes" { } { } 0 332125 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Verilog HDL or VHDL warning at sys_top.v(209): object \"vip_newcfg\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Verilog HDL or VHDL warning at sys_top.v(594): object \"VSET\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Ignored filter at sys_top.sdc(17): vip\|output_inst\|vid_clk could not be matched with a net" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Ignored create_generated_clock at sys_top.sdc(16): Argument <targets> is an empty collection" { } { } 0 332049 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "Ignored filter at sys_top.sdc(37): VID_CLK could not be matched with a clock" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "*" { } { } 0 21074 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "*" { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "*" { } { } 0 276027 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "RST" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "altera_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "altera_cyclonev_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "altera_pll_reconfig_core.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{ "" "" "" "cyclonev_pll" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
504
ZXNext.sv
Normal file
504
ZXNext.sv
Normal file
@@ -0,0 +1,504 @@
|
||||
//============================================================================
|
||||
// ZX Spectrum Next
|
||||
// port for MiSTer
|
||||
// Copyright (C) 2021 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; 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 emu
|
||||
(
|
||||
//Master input clock
|
||||
input CLK_50M,
|
||||
|
||||
//Async reset from top-level module.
|
||||
//Can be used as initial reset.
|
||||
input RESET,
|
||||
|
||||
//Must be passed to hps_io module
|
||||
inout [45:0] HPS_BUS,
|
||||
|
||||
//Base video clock. Usually equals to CLK_SYS.
|
||||
output CLK_VIDEO,
|
||||
|
||||
//Multiple resolutions are supported using different CE_PIXEL rates.
|
||||
//Must be based on CLK_VIDEO
|
||||
output CE_PIXEL,
|
||||
|
||||
//Video aspect ratio for HDMI. Most retro systems have ratio 4:3.
|
||||
//if VIDEO_ARX[12] or VIDEO_ARY[12] is set then [11:0] contains scaled size instead of aspect ratio.
|
||||
output [12:0] VIDEO_ARX,
|
||||
output [12:0] VIDEO_ARY,
|
||||
|
||||
output [7:0] VGA_R,
|
||||
output [7:0] VGA_G,
|
||||
output [7:0] VGA_B,
|
||||
output VGA_HS,
|
||||
output VGA_VS,
|
||||
output VGA_DE, // = ~(VBlank | HBlank)
|
||||
output VGA_F1,
|
||||
output [1:0] VGA_SL,
|
||||
output VGA_SCALER, // Force VGA scaler
|
||||
|
||||
input [11:0] HDMI_WIDTH,
|
||||
input [11:0] HDMI_HEIGHT,
|
||||
|
||||
`ifdef USE_FB
|
||||
// Use framebuffer in DDRAM (USE_FB=1 in qsf)
|
||||
// FB_FORMAT:
|
||||
// [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp
|
||||
// [3] : 0=16bits 565 1=16bits 1555
|
||||
// [4] : 0=RGB 1=BGR (for 16/24/32 modes)
|
||||
//
|
||||
// FB_STRIDE either 0 (rounded to 256 bytes) or multiple of pixel size (in bytes)
|
||||
output FB_EN,
|
||||
output [4:0] FB_FORMAT,
|
||||
output [11:0] FB_WIDTH,
|
||||
output [11:0] FB_HEIGHT,
|
||||
output [31:0] FB_BASE,
|
||||
output [13:0] FB_STRIDE,
|
||||
input FB_VBL,
|
||||
input FB_LL,
|
||||
output FB_FORCE_BLANK,
|
||||
|
||||
// Palette control for 8bit modes.
|
||||
// Ignored for other video modes.
|
||||
output FB_PAL_CLK,
|
||||
output [7:0] FB_PAL_ADDR,
|
||||
output [23:0] FB_PAL_DOUT,
|
||||
input [23:0] FB_PAL_DIN,
|
||||
output FB_PAL_WR,
|
||||
`endif
|
||||
|
||||
output LED_USER, // 1 - ON, 0 - OFF.
|
||||
|
||||
// b[1]: 0 - LED status is system status OR'd with b[0]
|
||||
// 1 - LED status is controled solely by b[0]
|
||||
// hint: supply 2'b00 to let the system control the LED.
|
||||
output [1:0] LED_POWER,
|
||||
output [1:0] LED_DISK,
|
||||
|
||||
// I/O board button press simulation (active high)
|
||||
// b[1]: user button
|
||||
// b[0]: osd button
|
||||
output [1:0] BUTTONS,
|
||||
|
||||
input CLK_AUDIO, // 24.576 MHz
|
||||
output [15:0] AUDIO_L,
|
||||
output [15:0] AUDIO_R,
|
||||
output AUDIO_S, // 1 - signed audio samples, 0 - unsigned
|
||||
output [1:0] AUDIO_MIX, // 0 - no mix, 1 - 25%, 2 - 50%, 3 - 100% (mono)
|
||||
|
||||
//ADC
|
||||
inout [3:0] ADC_BUS,
|
||||
|
||||
//SD-SPI
|
||||
output SD_SCK,
|
||||
output SD_MOSI,
|
||||
input SD_MISO,
|
||||
output SD_CS,
|
||||
input SD_CD,
|
||||
|
||||
`ifdef USE_DDRAM
|
||||
//High latency DDR3 RAM interface
|
||||
//Use for non-critical time purposes
|
||||
output DDRAM_CLK,
|
||||
input DDRAM_BUSY,
|
||||
output [7:0] DDRAM_BURSTCNT,
|
||||
output [28:0] DDRAM_ADDR,
|
||||
input [63:0] DDRAM_DOUT,
|
||||
input DDRAM_DOUT_READY,
|
||||
output DDRAM_RD,
|
||||
output [63:0] DDRAM_DIN,
|
||||
output [7:0] DDRAM_BE,
|
||||
output DDRAM_WE,
|
||||
`endif
|
||||
|
||||
`ifdef USE_SDRAM
|
||||
//SDRAM interface with lower latency
|
||||
output SDRAM_CLK,
|
||||
output SDRAM_CKE,
|
||||
output [12:0] SDRAM_A,
|
||||
output [1:0] SDRAM_BA,
|
||||
inout [15:0] SDRAM_DQ,
|
||||
output SDRAM_DQML,
|
||||
output SDRAM_DQMH,
|
||||
output SDRAM_nCS,
|
||||
output SDRAM_nCAS,
|
||||
output SDRAM_nRAS,
|
||||
output SDRAM_nWE,
|
||||
`endif
|
||||
|
||||
`ifdef DUAL_SDRAM
|
||||
//Secondary SDRAM
|
||||
input SDRAM2_EN,
|
||||
output SDRAM2_CLK,
|
||||
output [12:0] SDRAM2_A,
|
||||
output [1:0] SDRAM2_BA,
|
||||
inout [15:0] SDRAM2_DQ,
|
||||
output SDRAM2_nCS,
|
||||
output SDRAM2_nCAS,
|
||||
output SDRAM2_nRAS,
|
||||
output SDRAM2_nWE,
|
||||
`endif
|
||||
|
||||
input UART_CTS,
|
||||
output UART_RTS,
|
||||
input UART_RXD,
|
||||
output UART_TXD,
|
||||
output UART_DTR,
|
||||
input UART_DSR,
|
||||
|
||||
// Open-drain User port.
|
||||
// 0 - D+/RX
|
||||
// 1 - D-/TX
|
||||
// 2..6 - USR2..USR6
|
||||
// Set USER_OUT to 1 to read from USER_IN.
|
||||
input [6:0] USER_IN,
|
||||
output [6:0] USER_OUT,
|
||||
|
||||
input OSD_STATUS
|
||||
);
|
||||
|
||||
assign USER_OUT = '1;
|
||||
assign {DDRAM_CLK, DDRAM_BURSTCNT, DDRAM_ADDR, DDRAM_DIN, DDRAM_BE, DDRAM_RD, DDRAM_WE} = '0;
|
||||
|
||||
assign AUDIO_S = 0; // 1 - signed audio samples, 0 - unsigned
|
||||
assign AUDIO_MIX = status[4:3];
|
||||
|
||||
assign LED_DISK = 0;
|
||||
assign LED_POWER = 0;
|
||||
assign LED_USER = sd_act & ~vsd_sel;
|
||||
assign BUTTONS = 0;
|
||||
|
||||
assign UART_RTS = 0;
|
||||
assign UART_DTR = 0;
|
||||
|
||||
assign VGA_SCALER = 0;
|
||||
assign VGA_F1 = 0;
|
||||
|
||||
// Status Bit Map:
|
||||
// Upper Lower
|
||||
// 0 1 2 3 4 5 6
|
||||
// 01234567890123456789012345678901 23456789012345678901234567890123
|
||||
// 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV
|
||||
// XXXXXXXXX XXXX
|
||||
|
||||
|
||||
`include "build_id.v"
|
||||
localparam CONF_STR = {
|
||||
"ZXNext;;",
|
||||
"-;",
|
||||
"S,VHD;",
|
||||
"O1,Reset after Mount,No,Yes;",
|
||||
"-;",
|
||||
"O78,Aspect Ratio,Original,Full Screen,[ARC1],[ARC2];",
|
||||
"O56,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
|
||||
"H2d1OS,Vertical Crop,No,Yes;",
|
||||
"h2d1OST,Vertical Crop,No,270,216;",
|
||||
"OQR,Scale,Normal,V-Integer,Narrower HV-Integer,Wider HV-Integer;",
|
||||
"-;",
|
||||
"O34,Stereo mix,none,25%,50%,100%;",
|
||||
"-;",
|
||||
"O2,Joysticks Swap,No,Yes;",
|
||||
"-;",
|
||||
"R0,Reset;",
|
||||
"J,A,B,C,X,Y,Z,Start;",
|
||||
"V,v",`BUILD_DATE
|
||||
};
|
||||
|
||||
wire clk_sys, CLK_14, CLK_7, CLK_56, CLK_112;
|
||||
wire pll_locked;
|
||||
|
||||
pll pll
|
||||
(
|
||||
.refclk(CLK_50M),
|
||||
.outclk_0(clk_sys),
|
||||
.outclk_1(CLK_56),
|
||||
.outclk_2(CLK_14),
|
||||
.outclk_3(CLK_7),
|
||||
.outclk_4(CLK_112),
|
||||
.locked(pll_locked)
|
||||
);
|
||||
|
||||
reg reset = 0;
|
||||
always @(posedge clk_sys) reset <= RESET | status[0] | buttons[1] | (status[1] && img_mounted);
|
||||
|
||||
wire forced_scandoubler;
|
||||
wire [1:0] buttons;
|
||||
wire [63:0] status;
|
||||
wire [10:0] ps2_key;
|
||||
wire [24:0] ps2_mouse;
|
||||
wire [7:0] ps2_mouse_ext;
|
||||
wire [15:0] joy_0, joy_1;
|
||||
|
||||
wire [31:0] sd_lba;
|
||||
wire sd_rd;
|
||||
wire sd_wr;
|
||||
wire sd_ack;
|
||||
wire [8:0] sd_buff_addr;
|
||||
wire [7:0] sd_buff_dout;
|
||||
wire [7:0] sd_buff_din;
|
||||
wire sd_buff_wr;
|
||||
wire img_mounted;
|
||||
wire img_readonly;
|
||||
wire [63:0] img_size;
|
||||
wire sd_ack_conf;
|
||||
|
||||
wire [21:0] gamma_bus;
|
||||
|
||||
hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io
|
||||
(
|
||||
.clk_sys(clk_sys),
|
||||
.HPS_BUS(HPS_BUS),
|
||||
|
||||
.conf_str(CONF_STR),
|
||||
.forced_scandoubler(forced_scandoubler),
|
||||
|
||||
.joystick_0(joy_0),
|
||||
.joystick_1(joy_1),
|
||||
|
||||
.buttons(buttons),
|
||||
.status(status),
|
||||
.status_menumask({en1080p,|vcrop,1'b0}),
|
||||
|
||||
.sd_lba(sd_lba),
|
||||
.sd_rd(sd_rd),
|
||||
.sd_wr(sd_wr),
|
||||
.sd_ack(sd_ack),
|
||||
.sd_ack_conf(sd_ack_conf),
|
||||
.sd_buff_addr(sd_buff_addr),
|
||||
.sd_buff_dout(sd_buff_dout),
|
||||
.sd_buff_din(sd_buff_din),
|
||||
.sd_buff_wr(sd_buff_wr),
|
||||
.img_mounted(img_mounted),
|
||||
.img_readonly(img_readonly),
|
||||
.img_size(img_size),
|
||||
|
||||
.ps2_key(ps2_key),
|
||||
.ps2_mouse(ps2_mouse),
|
||||
.ps2_mouse_ext(ps2_mouse_ext),
|
||||
|
||||
.gamma_bus(gamma_bus)
|
||||
);
|
||||
|
||||
wire [20:0] RAM_A_ADDR;
|
||||
wire RAM_A_REQ;
|
||||
wire RAM_A_RD_n;
|
||||
wire [7:0] RAM_A_DI;
|
||||
wire [7:0] RAM_A_DO;
|
||||
wire RAM_A_WAIT;
|
||||
wire [20:0] RAM_B_ADDR;
|
||||
wire RAM_B_REQ;
|
||||
wire [7:0] RAM_B_DO;
|
||||
|
||||
sdram sdram(.*, .clk(CLK_112), .init(~pll_locked));
|
||||
|
||||
wire [11:0] aud_l, aud_r;
|
||||
|
||||
// active high = X Z Y START A C B U D L R
|
||||
wire [10:0] j0 = {joy_0[7],joy_0[9],joy_0[8],joy_0[10],joy_0[4],joy_0[6],joy_0[5],joy_0[3:0]};
|
||||
wire [10:0] j1 = {joy_1[7],joy_1[9],joy_1[8],joy_1[10],joy_1[4],joy_1[6],joy_1[5],joy_1[3:0]};
|
||||
|
||||
zxnext_top zxnext_top
|
||||
(
|
||||
.CLK_28 (clk_sys),
|
||||
.CLK_14 (CLK_14),
|
||||
.CLK_7 (CLK_7),
|
||||
|
||||
.HW_RESET (reset),
|
||||
|
||||
.RAM_A_ADDR (RAM_A_ADDR),
|
||||
.RAM_A_REQ (RAM_A_REQ),
|
||||
.RAM_A_RD_n (RAM_A_RD_n),
|
||||
.RAM_A_DO (RAM_A_DI),
|
||||
.RAM_A_DI (RAM_A_DO),
|
||||
.RAM_A_WAIT (RAM_A_WAIT),
|
||||
.RAM_B_ADDR (RAM_B_ADDR),
|
||||
.RAM_B_REQ (RAM_B_REQ),
|
||||
.RAM_B_DI (RAM_B_DO),
|
||||
|
||||
.ps2_key (ps2_key),
|
||||
.ps2_mouse (ps2_mouse),
|
||||
.ps2_mouse_ext (ps2_mouse_ext),
|
||||
|
||||
.sd_cs0_n_o (sdss),
|
||||
.sd_sclk_o (sdclk),
|
||||
.sd_mosi_o (sdmosi),
|
||||
.sd_miso_i (sdmiso),
|
||||
|
||||
.audio_L (aud_l),
|
||||
.audio_R (aud_r),
|
||||
|
||||
.ear_port_i (~tape_in),
|
||||
|
||||
.joy_left (status[2] ? j1: j0),
|
||||
.joy_right (status[2] ? j0: j1),
|
||||
|
||||
.uart_rx_i (UART_RXD),
|
||||
.uart_tx_o (UART_TXD),
|
||||
|
||||
.RGB ({rgb_r,rgb_g,rgb_b}),
|
||||
.RGB_VS_n (VSync_n),
|
||||
.RGB_HS_n (HSync_n),
|
||||
.RGB_VB_n (VBlank_n),
|
||||
.RGB_HB_n (HBlank_n),
|
||||
.RGB_NTSC (ntsc)
|
||||
);
|
||||
|
||||
assign AUDIO_L = {aud_l, 4'b0000};
|
||||
assign AUDIO_R = {aud_r, 4'b0000};
|
||||
|
||||
assign CLK_VIDEO = CLK_56;
|
||||
|
||||
wire [2:0] scale = status[6:5];
|
||||
assign VGA_SL = scale ? scale[1:0] - 1'd1 : 2'd0;
|
||||
|
||||
wire HBlank_n, VBlank_n;
|
||||
wire HSync_n, VSync_n;
|
||||
wire ntsc;
|
||||
|
||||
wire [2:0] rgb_r;
|
||||
wire [2:0] rgb_g;
|
||||
wire [2:0] rgb_b;
|
||||
|
||||
reg ce_pix;
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg [1:0] div;
|
||||
|
||||
div <= div + 1'd1;
|
||||
ce_pix <= !div;
|
||||
end
|
||||
|
||||
reg narrow_hbl;
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg [10:0] hcnt;
|
||||
|
||||
if(ce_pix) begin
|
||||
hcnt <= hcnt + 1'd1;
|
||||
if(~HBlank_n) hcnt <= 0;
|
||||
narrow_hbl <= narrow && ((hcnt < 20) || (hcnt >= 700));
|
||||
end
|
||||
end
|
||||
|
||||
video_mixer #(.LINE_LENGTH(740), .GAMMA(1)) video_mixer
|
||||
(
|
||||
.*,
|
||||
|
||||
.hq2x(scale == 1),
|
||||
.scandoubler(scale || forced_scandoubler),
|
||||
|
||||
.VSync(~VSync_n),
|
||||
.HSync(~HSync_n),
|
||||
.VBlank(~VBlank_n),
|
||||
.HBlank(~HBlank_n | narrow_hbl),
|
||||
|
||||
.R({rgb_r,rgb_r,rgb_r[2:1]}),
|
||||
.G({rgb_g,rgb_g,rgb_g[2:1]}),
|
||||
.B({rgb_b,rgb_b,rgb_b[2:1]}),
|
||||
|
||||
.VGA_DE(vga_de)
|
||||
);
|
||||
|
||||
reg [9:0] vcrop;
|
||||
reg narrow;
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
vcrop <= 0;
|
||||
narrow <= 0;
|
||||
if(HDMI_WIDTH >= (HDMI_HEIGHT + HDMI_HEIGHT[11:1]) && !forced_scandoubler && !scale) begin
|
||||
if(HDMI_HEIGHT == 480) vcrop <= 240;
|
||||
if(HDMI_HEIGHT == 600) begin vcrop <= 200; narrow <= 1; end
|
||||
if(HDMI_HEIGHT == 720) vcrop <= 240;
|
||||
if(HDMI_HEIGHT == 768) vcrop <= 256;
|
||||
if(HDMI_HEIGHT == 800) begin vcrop <= 200; narrow <= 1; end
|
||||
if(HDMI_HEIGHT == 1080) vcrop <= status[29] ? 10'd216 : 10'd270;
|
||||
if(HDMI_HEIGHT == 1200) vcrop <= 240;
|
||||
end
|
||||
end
|
||||
|
||||
reg en1080p;
|
||||
always @(posedge CLK_VIDEO) en1080p <= (HDMI_WIDTH == 1920) && (HDMI_HEIGHT == 1080);
|
||||
|
||||
wire [1:0] ar = status[8:7];
|
||||
wire vcrop_en = en1080p ? |status[29:28] : status[28];
|
||||
wire vga_de;
|
||||
video_freak video_freak
|
||||
(
|
||||
.*,
|
||||
.VGA_DE_IN(vga_de),
|
||||
.ARX((!ar) ? (narrow ? 12'd340 : 12'd360) : (ar - 1'd1)),
|
||||
.ARY((!ar) ? (ntsc ? 12'd256 : 12'd303) : 12'd0),
|
||||
.CROP_SIZE(vcrop_en ? vcrop : 10'd0),
|
||||
.CROP_OFF(0),
|
||||
.SCALE(status[27:26])
|
||||
);
|
||||
|
||||
wire sdclk;
|
||||
wire sdmosi;
|
||||
wire sdmiso = vsd_sel ? vsdmiso : SD_MISO;
|
||||
wire sdss;
|
||||
|
||||
reg vsd_sel = 0;
|
||||
always @(posedge clk_sys) if(img_mounted) vsd_sel <= |img_size;
|
||||
|
||||
wire vsdmiso;
|
||||
sd_card sd_card
|
||||
(
|
||||
.*,
|
||||
.clk_spi(CLK_56),
|
||||
.sdhc(1),
|
||||
.sck(sdclk),
|
||||
.ss(sdss | ~vsd_sel),
|
||||
.mosi(sdmosi),
|
||||
.miso(vsdmiso)
|
||||
);
|
||||
|
||||
assign SD_CS = sdss | vsd_sel;
|
||||
assign SD_SCK = sdclk & ~vsd_sel;
|
||||
assign SD_MOSI = sdmosi & ~vsd_sel;
|
||||
|
||||
reg sd_act;
|
||||
|
||||
always @(posedge CLK_56) begin
|
||||
reg old_mosi, old_miso;
|
||||
integer timeout = 0;
|
||||
|
||||
old_mosi <= sdmosi;
|
||||
old_miso <= sdmiso;
|
||||
|
||||
sd_act <= 0;
|
||||
if(timeout < 1000000) begin
|
||||
timeout <= timeout + 1;
|
||||
sd_act <= 1;
|
||||
end
|
||||
|
||||
if((old_mosi ^ sdmosi) || (old_miso ^ sdmiso)) timeout <= 0;
|
||||
end
|
||||
|
||||
wire tape_in;
|
||||
wire tape_adc, tape_adc_act;
|
||||
|
||||
assign tape_in = tape_adc_act & tape_adc;
|
||||
|
||||
ltc2308_tape #(.CLK_RATE(28000000)) ltc2308_tape
|
||||
(
|
||||
.clk(clk_sys),
|
||||
.ADC_BUS(ADC_BUS),
|
||||
.dout(tape_adc),
|
||||
.active(tape_adc_act)
|
||||
);
|
||||
|
||||
endmodule
|
||||
36
clean.bat
Normal file
36
clean.bat
Normal file
@@ -0,0 +1,36 @@
|
||||
@echo off
|
||||
del /s *.bak
|
||||
del /s *.orig
|
||||
del /s *.rej
|
||||
del /s *~
|
||||
rmdir /s /q db
|
||||
rmdir /s /q incremental_db
|
||||
rmdir /s /q output_files
|
||||
rmdir /s /q simulation
|
||||
rmdir /s /q greybox_tmp
|
||||
rmdir /s /q hc_output
|
||||
rmdir /s /q .qsys_edit
|
||||
rmdir /s /q hps_isw_handoff
|
||||
rmdir /s /q sys\.qsys_edit
|
||||
rmdir /s /q sys\vip
|
||||
for /d %%i in (sys\*_sim) do rmdir /s /q "%%i"
|
||||
for /d %%i in (rtl\*_sim) do rmdir /s /q "%%i"
|
||||
del build_id.v
|
||||
del c5_pin_model_dump.txt
|
||||
del PLLJ_PLLSPE_INFO.txt
|
||||
del /s *.qws
|
||||
del /s *.ppf
|
||||
del /s *.ddb
|
||||
del /s *.csv
|
||||
del /s *.cmp
|
||||
del /s *.sip
|
||||
del /s *.spd
|
||||
del /s *.bsf
|
||||
del /s *.f
|
||||
del /s *.sopcinfo
|
||||
del /s *.xml
|
||||
del *.cdf
|
||||
del *.rpt
|
||||
del /s new_rtl_netlist
|
||||
del /s old_rtl_netlist
|
||||
pause
|
||||
47
files.qip
Normal file
47
files.qip
Normal file
@@ -0,0 +1,47 @@
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/ym2149.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/turbosound.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/soundrive.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/i2s.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/audio_mixer.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/i2s/i2s_transmit.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/i2s/i2s_slave.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/i2s/i2s_receive.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/audio/i2s/i2s_master.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/cpu/t80na.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/cpu/t80n_pack.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/cpu/t80n_mcode.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/cpu/t80n_alu.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/cpu/t80n.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/multiface.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/dma.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/divmmc.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/copper.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/im2_control.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/im2_device.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/im2_peripheral.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/peripherals.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/input/membrane/membrane.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/input/membrane/membrane_stick.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/input/keyboard/keymaps.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/misc/debounce.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/video/zxula_timing.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/video/zxula.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/video/tilemap.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/video/sprites.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/video/lores.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/video/layer2.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/serial/uart.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/serial/uart_rx.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/serial/uart_tx.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/serial/spi_master.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/serial/fifop.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/bootrom.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/ctc_chan.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/device/ctc.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/zxnext.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/mister/ps2_keyb.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/mister/bram.vhd
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mister/sdram.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/mister/zxnext_top.vhd
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ZXNext.sv
|
||||
set_global_assignment -name SDC_FILE ZXNext.sdc
|
||||
BIN
releases/boot.zip
Normal file
BIN
releases/boot.zip
Normal file
Binary file not shown.
107
rtl/audio/audio_mixer.vhd
Normal file
107
rtl/audio/audio_mixer.vhd
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
-- Audio Mixer
|
||||
-- Copyright 2020 Fabio Belavenuto and Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity audio_mixer is
|
||||
port
|
||||
(
|
||||
clock_i : in std_logic;
|
||||
reset_i : in std_logic;
|
||||
|
||||
-- beeper and tape
|
||||
|
||||
ear_i : in std_logic;
|
||||
mic_i : in std_logic;
|
||||
|
||||
-- ay
|
||||
|
||||
ay_L_i : in std_logic_vector(11 downto 0);
|
||||
ay_R_i : in std_logic_vector(11 downto 0);
|
||||
|
||||
-- dac
|
||||
|
||||
dac_L_i : in std_logic_vector(8 downto 0);
|
||||
dac_R_i : in std_logic_vector(8 downto 0);
|
||||
|
||||
-- pi i2s audio
|
||||
|
||||
pi_i2s_L_i : in std_logic_vector(9 downto 0);
|
||||
pi_i2s_R_i : in std_logic_vector(9 downto 0);
|
||||
|
||||
-- mixed pcm audio
|
||||
|
||||
pcm_L_o : out std_logic_vector(12 downto 0);
|
||||
pcm_R_o : out std_logic_vector(12 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of audio_mixer is
|
||||
|
||||
constant ear_volume : std_logic_vector(12 downto 0) := "0001000000000";
|
||||
constant mic_volume : std_logic_vector(12 downto 0) := "0000010000000";
|
||||
|
||||
signal ear : std_logic_vector(12 downto 0);
|
||||
signal mic : std_logic_vector(12 downto 0);
|
||||
signal ay_L : std_logic_vector(12 downto 0);
|
||||
signal ay_R : std_logic_vector(12 downto 0);
|
||||
signal dac_L : std_logic_vector(12 downto 0);
|
||||
signal dac_R : std_logic_vector(12 downto 0);
|
||||
signal i2s_L : std_logic_vector(12 downto 0);
|
||||
signal i2s_R : std_logic_vector(12 downto 0);
|
||||
|
||||
signal pcm_L : std_logic_vector(12 downto 0); -- 0 - 8191
|
||||
signal pcm_R : std_logic_vector(12 downto 0); -- 0 - 8191
|
||||
|
||||
begin
|
||||
|
||||
ear <= ear_volume when ear_i = '1' else (others => '0'); -- 0 / 512
|
||||
mic <= mic_volume when mic_i = '1' else (others => '0'); -- 0 / 128
|
||||
|
||||
ay_L <= '0' & ay_L_i; -- 0 - 2295
|
||||
ay_R <= '0' & ay_R_i; -- 0 - 2295
|
||||
|
||||
dac_L <= "00" & dac_L_i & "00"; -- 0 - 510 => 0 - 2040
|
||||
dac_R <= "00" & dac_R_i & "00"; -- 0 - 510 => 0 - 2040
|
||||
|
||||
i2s_L <= "000" & pi_i2s_L_i; -- 0 - 1023
|
||||
i2s_R <= "000" & pi_i2s_R_i; -- 0 - 1023
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_i = '1' then
|
||||
pcm_L <= (others => '0');
|
||||
pcm_R <= (others => '0');
|
||||
else
|
||||
pcm_L <= ear + mic + ay_L + dac_L + i2s_L; -- 0 - 5998
|
||||
pcm_R <= ear + mic + ay_R + dac_R + i2s_R; -- 0 - 5998
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
pcm_L_o <= pcm_L;
|
||||
pcm_R_o <= pcm_R;
|
||||
|
||||
end architecture;
|
||||
70
rtl/audio/dac.vhd
Normal file
70
rtl/audio/dac.vhd
Normal file
@@ -0,0 +1,70 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Delta-Sigma DAC
|
||||
--
|
||||
-- Refer to Xilinx Application Note XAPP154.
|
||||
--
|
||||
-- This DAC requires an external RC low-pass filter:
|
||||
--
|
||||
-- dac_o 0---XXXXX---+---0 analog audio
|
||||
-- 3k3 |
|
||||
-- === 4n7
|
||||
-- |
|
||||
-- GND
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity dac is
|
||||
|
||||
generic (
|
||||
msbi_g : integer := 7
|
||||
);
|
||||
port (
|
||||
clk_i : in std_logic;
|
||||
res_i : in std_logic;
|
||||
dac_i : in std_logic_vector(msbi_g downto 0);
|
||||
dac_o : out std_logic
|
||||
);
|
||||
|
||||
end dac;
|
||||
|
||||
library ieee;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
architecture rtl of dac is
|
||||
|
||||
signal DACout_q : std_logic;
|
||||
signal DeltaAdder_s,
|
||||
SigmaAdder_s,
|
||||
SigmaLatch_q,
|
||||
DeltaB_s : unsigned(msbi_g+2 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
DeltaB_s(msbi_g+2 downto msbi_g+1) <= SigmaLatch_q(msbi_g+2) &
|
||||
SigmaLatch_q(msbi_g+2);
|
||||
DeltaB_s(msbi_g downto 0) <= (others => '0');
|
||||
|
||||
DeltaAdder_s <= unsigned('0' & '0' & dac_i) + DeltaB_s;
|
||||
|
||||
SigmaAdder_s <= DeltaAdder_s + SigmaLatch_q;
|
||||
|
||||
seq: process (clk_i)
|
||||
begin
|
||||
if clk_i'event and clk_i = '1' then
|
||||
if res_i = '1' then
|
||||
SigmaLatch_q <= to_unsigned(2**(msbi_g+1), SigmaLatch_q'length);
|
||||
DACout_q <= '0';
|
||||
else
|
||||
SigmaLatch_q <= SigmaAdder_s;
|
||||
DACout_q <= SigmaLatch_q(msbi_g+2);
|
||||
end if;
|
||||
end if;
|
||||
end process seq;
|
||||
|
||||
dac_o <= DACout_q;
|
||||
|
||||
end rtl;
|
||||
208
rtl/audio/i2s.vhd
Normal file
208
rtl/audio/i2s.vhd
Normal file
@@ -0,0 +1,208 @@
|
||||
|
||||
-- I2S Pi0 + ZX Spectrum Next Interface
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Reference:
|
||||
-- <https://web.archive.org/web/20070102004400/http://www.nxp.com/acrobat_download/various/I2SBUS.pdf>
|
||||
--
|
||||
-- Sample Rate = SR = i_CLK / 2^(CLK_DIV_PRE) / (i_CLK_DIV+1) / LR_WIDTH / 4
|
||||
-- = 538461 / (i_CLK_DIV+1)
|
||||
--
|
||||
-- i_CLK_DIV = (i_CLK / 2^(CLK_DIV_PRE) / SR / LR_WIDTH / 4) - 1
|
||||
-- = 538461 / SR - 1
|
||||
--
|
||||
-- This is a two-way interface allowing the exchange of stereo audio between
|
||||
-- the zx next and the pi.
|
||||
--
|
||||
-- Audio from the pi is given the same loudness as a single 8-bit dac channel.
|
||||
-- The unsigned range of pcm therefore covers 10 bits per stereo channel.
|
||||
--
|
||||
-- Audio generated by the zx next is unsigned 13 bits per stereo channel.
|
||||
--
|
||||
-- i2s exchanges signed audio.
|
||||
|
||||
-- Note: Restricted to slave mode only
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity i2s_transmitter is
|
||||
port
|
||||
(
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_CLK : in std_logic;
|
||||
-- i_CLK_DIV : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- i_slave_mode : in std_logic; -- 1 = slave, external clock used
|
||||
|
||||
-- slave mode (incoming clock signals, synchronized)
|
||||
|
||||
i_i2s_sck : in std_logic;
|
||||
i_i2s_ws : in std_logic;
|
||||
|
||||
-- outgoing clock signals (master or slave)
|
||||
|
||||
o_i2s_sck : out std_logic;
|
||||
o_i2s_ws : out std_logic;
|
||||
o_i2s_wsp : out std_logic;
|
||||
|
||||
-- zx next audio to pi
|
||||
|
||||
i_audio_zxn_L : in std_logic_vector(12 downto 0);
|
||||
i_audio_zxn_R : in std_logic_vector(12 downto 0);
|
||||
o_i2s_sd_pi : out std_logic;
|
||||
|
||||
-- pi audio to zx next
|
||||
|
||||
i_i2s_sd_pi : in std_logic;
|
||||
o_audio_pi_L : out std_logic_vector(9 downto 0);
|
||||
o_audio_pi_R : out std_logic_vector(9 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of i2s_transmitter is
|
||||
|
||||
signal i2s_sck : std_logic;
|
||||
signal i2s_ws : std_logic;
|
||||
signal i2s_wsp : std_logic;
|
||||
|
||||
signal m_i2s_sck : std_logic;
|
||||
signal m_i2s_ws : std_logic;
|
||||
signal m_i2s_wsp : std_logic;
|
||||
|
||||
signal s_i2s_sck : std_logic;
|
||||
signal s_i2s_ws : std_logic;
|
||||
signal s_i2s_wsp : std_logic;
|
||||
|
||||
signal audio_pi_L : std_logic_vector(12 downto 0);
|
||||
signal audio_pi_R : std_logic_vector(12 downto 0);
|
||||
|
||||
signal audio_zxn_L : std_logic_vector(12 downto 0);
|
||||
signal audio_zxn_R : std_logic_vector(12 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- -- i2s master
|
||||
|
||||
-- i2s_master_mod : entity work.i2s_master
|
||||
-- generic map
|
||||
-- (
|
||||
-- CLK_DIV_PRE => 0,
|
||||
-- CLK_DIV_MBIT => 7,
|
||||
-- LR_WIDTH => 13,
|
||||
-- LR_WIDTH_MBIT => 3
|
||||
-- )
|
||||
-- port map
|
||||
-- (
|
||||
-- i_reset => i_reset or i_slave_mode,
|
||||
--
|
||||
-- i_CLK => i_CLK,
|
||||
-- i_CLK_DIV => i_CLK_DIV,
|
||||
--
|
||||
-- o_i2s_sck => m_i2s_sck,
|
||||
-- o_i2s_ws => m_i2s_ws,
|
||||
-- o_i2s_wsp => m_i2s_wsp
|
||||
-- );
|
||||
|
||||
-- i2s slave
|
||||
|
||||
i2s_slave_mod : entity work.i2s_slave
|
||||
port map
|
||||
(
|
||||
-- i_reset => i_reset or not i_slave_mode,
|
||||
--
|
||||
-- i_CLK => i_CLK,
|
||||
--
|
||||
i_i2s_sck => i_i2s_sck,
|
||||
i_i2s_ws => i_i2s_ws,
|
||||
|
||||
o_i2s_sck => s_i2s_sck,
|
||||
o_i2s_ws => s_i2s_ws,
|
||||
o_i2s_wsp => s_i2s_wsp
|
||||
);
|
||||
|
||||
-- master or slave
|
||||
|
||||
i2s_sck <= s_i2s_sck; -- when i_slave_mode = '1' else m_i2s_sck;
|
||||
i2s_ws <= s_i2s_ws; -- when i_slave_mode = '1' else m_i2s_ws;
|
||||
i2s_wsp <= s_i2s_wsp; -- when i_slave_mode = '1' else m_i2s_wsp;
|
||||
|
||||
o_i2s_sck <= i2s_sck;
|
||||
o_i2s_ws <= i2s_ws;
|
||||
o_i2s_wsp <= i2s_wsp;
|
||||
|
||||
-- i2s receive from pi
|
||||
|
||||
i2s_receiver_mod : entity work.i2s_receive
|
||||
generic map
|
||||
(
|
||||
LR_WIDTH => 13,
|
||||
LR_WIDTH_MBIT => 3
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_reset => i_reset,
|
||||
i_CLK => i_CLK,
|
||||
|
||||
i_i2s_sck => i2s_sck,
|
||||
i_i2s_ws => i2s_ws,
|
||||
i_i2s_wsp => i2s_wsp,
|
||||
i_i2s_sd => i_i2s_sd_pi,
|
||||
|
||||
o_i2s_L => audio_pi_L,
|
||||
o_i2s_R => audio_pi_R
|
||||
);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
o_audio_pi_L <= (not audio_pi_L(12)) & audio_pi_L(11 downto 3);
|
||||
o_audio_pi_R <= (not audio_pi_R(12)) & audio_pi_R(11 downto 3);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- i2s transmit to pi
|
||||
|
||||
audio_zxn_L <= (not i_audio_zxn_L(12)) & i_audio_zxn_L(11 downto 0);
|
||||
audio_zxn_R <= (not i_audio_zxn_R(12)) & i_audio_zxn_R(11 downto 0);
|
||||
|
||||
i2s_transmit_mod : entity work.i2s_transmit
|
||||
generic map
|
||||
(
|
||||
LR_WIDTH => 13
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_reset => i_reset,
|
||||
i_CLK => i_CLK,
|
||||
|
||||
i_i2s_sck => i2s_sck,
|
||||
i_i2s_ws => i2s_ws,
|
||||
i_i2s_wsp => i2s_wsp,
|
||||
o_i2s_sd => o_i2s_sd_pi,
|
||||
|
||||
i_i2s_L => audio_zxn_L,
|
||||
i_i2s_R => audio_zxn_R
|
||||
);
|
||||
|
||||
end architecture;
|
||||
153
rtl/audio/i2s/i2s_master.vhd
Normal file
153
rtl/audio/i2s/i2s_master.vhd
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
-- I2S Master
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Generates:
|
||||
-- sck - master clock
|
||||
-- ws - channel selection (0 = left, 1 = right)
|
||||
-- wsp - one on falling edge of sck indicates channel change
|
||||
--
|
||||
-- Reference:
|
||||
-- <https://web.archive.org/web/20070102004400/http://www.nxp.com/acrobat_download/various/I2SBUS.pdf>
|
||||
--
|
||||
-- Sample Rate = SR = i_CLK / 2^(CLK_DIV_PRE) / (i_CLK_DIV+1) / LR_WIDTH / 4
|
||||
-- i_CLK_DIV = (i_CLK / 2^(CLK_DIV_PRE) / SR / LR_WIDTH / 4) - 1
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity i2s_master is
|
||||
generic
|
||||
(
|
||||
constant CLK_DIV_PRE : natural := 0; -- divide clock by 2^(CLK_DIV_PRE)
|
||||
constant CLK_DIV_MBIT : positive := 7; -- size of programmable divider (7 downto 0)
|
||||
constant LR_WIDTH : positive := 8; -- number of bits in the left and right channels (8: 7 downto 0)
|
||||
constant LR_WIDTH_MBIT : positive := 2 -- number of bits needed to represent LR_WIDTH-1 (2 downto 0)
|
||||
);
|
||||
port
|
||||
(
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_CLK : in std_logic;
|
||||
i_CLK_DIV : in std_logic_vector(CLK_DIV_MBIT downto 0);
|
||||
|
||||
o_i2s_sck : out std_logic;
|
||||
o_i2s_ws : out std_logic;
|
||||
o_i2s_wsp : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of i2s_master is
|
||||
|
||||
signal sck : std_logic;
|
||||
signal sck_count : std_logic_vector((CLK_DIV_PRE + CLK_DIV_MBIT) downto 0);
|
||||
signal clk_div : std_logic_vector(CLK_DIV_MBIT downto 0);
|
||||
|
||||
signal sck_edge : std_logic;
|
||||
signal sck_fe : std_logic;
|
||||
signal sck_re : std_logic;
|
||||
|
||||
signal ws : std_logic;
|
||||
signal ws_d : std_logic;
|
||||
signal wsp : std_logic;
|
||||
signal width_count : std_logic_vector(LR_WIDTH_MBIT downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- sck
|
||||
|
||||
sck_edge <= '1' when (sck_count((CLK_DIV_PRE + CLK_DIV_MBIT) downto CLK_DIV_PRE) = clk_div) else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
sck <= '0';
|
||||
sck_count <= (others => '0');
|
||||
clk_div <= i_CLK_DIV;
|
||||
elsif sck_edge = '1' then
|
||||
if sck = '1' and wsp = '1' then
|
||||
clk_div <= i_CLK_DIV;
|
||||
end if;
|
||||
sck <= not sck;
|
||||
sck_count <= (others => '0');
|
||||
else
|
||||
sck_count <= sck_count + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sck_re <= sck_edge and not sck;
|
||||
sck_fe <= sck_edge and sck;
|
||||
|
||||
-- channel selection
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
ws <= '1';
|
||||
width_count <= std_logic_vector(to_unsigned(LR_WIDTH-1, width_count'length));
|
||||
elsif sck_fe = '1' then
|
||||
if width_count = std_logic_vector(to_unsigned(LR_WIDTH-1, width_count'length)) then
|
||||
ws <= not ws;
|
||||
width_count <= (others => '0');
|
||||
else
|
||||
width_count <= width_count + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
ws_d <= '1';
|
||||
elsif sck_fe = '1' then
|
||||
ws_d <= ws;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
wsp <= '0';
|
||||
elsif sck_re = '1' then
|
||||
if ws /= ws_d then
|
||||
wsp <= '1';
|
||||
else
|
||||
wsp <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- output
|
||||
|
||||
o_i2s_sck <= sck;
|
||||
o_i2s_ws <= ws;
|
||||
o_i2s_wsp <= wsp;
|
||||
|
||||
end architecture;
|
||||
146
rtl/audio/i2s/i2s_receive.vhd
Normal file
146
rtl/audio/i2s/i2s_receive.vhd
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
-- I2S Receiver
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Reference:
|
||||
-- https://web.archive.org/web/20070102004400/http://www.nxp.com/acrobat_download/various/I2SBUS.pdf
|
||||
|
||||
-- Signals are already synchronized
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity i2s_receive is
|
||||
generic
|
||||
(
|
||||
constant LR_WIDTH : positive := 8; -- number of bits in the left and right channels (8: 7 downto 0)
|
||||
constant LR_WIDTH_MBIT : positive := 2 -- number of bits needed to represent LR_WIDTH-1 (2 downto 0)
|
||||
);
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_i2s_sck : in std_logic;
|
||||
i_i2s_ws : in std_logic;
|
||||
i_i2s_wsp : in std_logic;
|
||||
i_i2s_sd : in std_logic;
|
||||
|
||||
o_i2s_L : out std_logic_vector(LR_WIDTH-1 downto 0);
|
||||
o_i2s_R : out std_logic_vector(LR_WIDTH-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of i2s_receive is
|
||||
|
||||
signal sck_d : std_logic;
|
||||
signal sck_re : std_logic;
|
||||
signal sck_fe : std_logic;
|
||||
|
||||
signal wsp_e : std_logic;
|
||||
|
||||
signal receiver : std_logic_vector(LR_WIDTH downto 0);
|
||||
signal recv_count : std_logic_vector(LR_WIDTH_MBIT downto 0);
|
||||
|
||||
signal recv_L : std_logic_vector(LR_WIDTH-1 downto 0);
|
||||
signal recv_R : std_logic_vector(LR_WIDTH-1 downto 0);
|
||||
|
||||
|
||||
begin
|
||||
|
||||
-- i2s clock
|
||||
-- (accepting a slip of one fast clock period)
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
sck_d <= '0';
|
||||
else
|
||||
sck_d <= i_i2s_sck;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sck_re <= i_i2s_sck and not sck_d;
|
||||
sck_fe <= sck_d and not i_i2s_sck;
|
||||
|
||||
-- change activation edge for wsp
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
wsp_e <= '0';
|
||||
elsif sck_fe = '1' then
|
||||
wsp_e <= i_i2s_wsp;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- bit receiver
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
receiver <= (others => '0');
|
||||
recv_count <= std_logic_vector(to_unsigned(LR_WIDTH-1, recv_count'length));
|
||||
elsif sck_re = '1' then
|
||||
if wsp_e = '1' then
|
||||
receiver(LR_WIDTH) <= i_i2s_sd;
|
||||
receiver(LR_WIDTH-1 downto 0) <= (others => '0');
|
||||
recv_count <= std_logic_vector(to_unsigned(LR_WIDTH-1, recv_count'length));
|
||||
else
|
||||
receiver(to_integer(unsigned(recv_count))) <= i_i2s_sd;
|
||||
if recv_count /= std_logic_vector(to_unsigned(0, recv_count'length)) then
|
||||
recv_count <= recv_count - 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- LR load
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
recv_L <= (others => '0');
|
||||
recv_R <= (others => '0');
|
||||
elsif sck_fe = '1' and i_i2s_wsp = '1' then
|
||||
if i_i2s_ws = '0' then
|
||||
recv_R <= receiver(LR_WIDTH downto 1);
|
||||
else
|
||||
recv_L <= receiver(LR_WIDTH downto 1);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- output
|
||||
|
||||
o_i2s_L <= recv_L;
|
||||
o_i2s_R <= recv_R;
|
||||
|
||||
end architecture;
|
||||
74
rtl/audio/i2s/i2s_slave.vhd
Normal file
74
rtl/audio/i2s/i2s_slave.vhd
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
-- I2S Slave
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Generates:
|
||||
-- wsp - one on falling edge of sck indicates channel change
|
||||
--
|
||||
-- Reference:
|
||||
-- <https://web.archive.org/web/20070102004400/http://www.nxp.com/acrobat_download/various/I2SBUS.pdf>
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity i2s_slave is
|
||||
port
|
||||
(
|
||||
i_i2s_sck : in std_logic;
|
||||
i_i2s_ws : in std_logic;
|
||||
|
||||
o_i2s_sck : out std_logic;
|
||||
o_i2s_ws : out std_logic;
|
||||
o_i2s_wsp : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of i2s_slave is
|
||||
|
||||
signal ws_d : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
o_i2s_sck <= i_i2s_sck;
|
||||
o_i2s_ws <= i_i2s_ws;
|
||||
|
||||
-- generate wsp
|
||||
|
||||
process (i_i2s_sck)
|
||||
begin
|
||||
if rising_edge(i_i2s_sck) then
|
||||
ws_d <= i_i2s_ws;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_i2s_sck)
|
||||
begin
|
||||
if rising_edge(i_i2s_sck) then
|
||||
if i_i2s_ws /= ws_d then
|
||||
o_i2s_wsp <= '1';
|
||||
else
|
||||
o_i2s_wsp <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
103
rtl/audio/i2s/i2s_transmit.vhd
Normal file
103
rtl/audio/i2s/i2s_transmit.vhd
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
-- I2S Transmitter
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Reference:
|
||||
-- <https://web.archive.org/web/20070102004400/http://www.nxp.com/acrobat_download/various/I2SBUS.pdf>
|
||||
--
|
||||
-- Signals are already synchronized
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity i2s_transmit is
|
||||
generic
|
||||
(
|
||||
constant LR_WIDTH : positive := 8 -- number of bits in the left and right channels (8: 7 downto 0)
|
||||
);
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_i2s_sck : in std_logic;
|
||||
i_i2s_ws : in std_logic;
|
||||
i_i2s_wsp : in std_logic;
|
||||
o_i2s_sd : out std_logic;
|
||||
|
||||
i_i2s_L : in std_logic_vector(LR_WIDTH-1 downto 0);
|
||||
i_i2s_R : in std_logic_vector(LR_WIDTH-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of i2s_transmit is
|
||||
|
||||
signal sck_d : std_logic;
|
||||
signal sck_fe : std_logic;
|
||||
|
||||
signal transmitter : std_logic_vector(LR_WIDTH-1 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- i2s clock
|
||||
-- (accepting a slip of one fast clock period)
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
sck_d <= '0';
|
||||
else
|
||||
sck_d <= i_i2s_sck;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sck_fe <= sck_d and not i_i2s_sck;
|
||||
|
||||
-- bit transmitter
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
transmitter(LR_WIDTH-1) <= '1';
|
||||
transmitter(LR_WIDTH-2 downto 0) <= (others => '0');
|
||||
elsif sck_fe = '1' then
|
||||
if i_i2s_wsp = '1' then
|
||||
if i_i2s_ws = '0' then
|
||||
transmitter <= i_i2s_L;
|
||||
else
|
||||
transmitter <= i_i2s_R;
|
||||
end if;
|
||||
else
|
||||
transmitter <= transmitter(LR_WIDTH-2 downto 0) & '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- output
|
||||
|
||||
o_i2s_sd <= transmitter(LR_WIDTH-1);
|
||||
|
||||
end architecture;
|
||||
97
rtl/audio/pwm.vhd
Normal file
97
rtl/audio/pwm.vhd
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
-- Pulse Width Modulator DAC
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Generates N/M output on a sample period of M
|
||||
-- Sample rate = i_CLK / M
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity pwm is
|
||||
generic
|
||||
(
|
||||
M : integer := 255;
|
||||
M_bit : integer := 7 -- highest bit number to represent M
|
||||
);
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_pcm : in std_logic_vector(M_bit downto 0);
|
||||
o_pwm : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of pwm is
|
||||
|
||||
signal sample : std_logic_vector(M_bit downto 0);
|
||||
signal period : std_logic_vector(M_bit downto 0);
|
||||
|
||||
signal tally : std_logic_vector(M_bit+1 downto 0);
|
||||
signal delta : std_logic_vector(M_bit+1 downto 0);
|
||||
|
||||
signal pwm_one : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
-- period counter
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
period <= (others => '0');
|
||||
elsif period = M then
|
||||
period <= (others => '0');
|
||||
else
|
||||
period <= period + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- pwm output
|
||||
|
||||
pwm_one <= '1' when tally >= ('0' & std_logic_vector(to_unsigned(M, M_bit+1))) else '0';
|
||||
delta <= ('0' & sample) when pwm_one = '0' else (('0' & sample) - ('0' & std_logic_vector(to_unsigned(M, M_bit+1))));
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
tally <= (others => '0');
|
||||
sample <= (others => '0');
|
||||
elsif period = M then
|
||||
tally <= '0' & i_pcm;
|
||||
sample <= i_pcm;
|
||||
else
|
||||
tally <= tally + delta;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- output
|
||||
|
||||
o_pwm <= pwm_one;
|
||||
|
||||
end architecture;
|
||||
117
rtl/audio/soundrive.vhd
Normal file
117
rtl/audio/soundrive.vhd
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
-- ZX Spectrum Next 4 x 8-bit DAC
|
||||
-- Copyright 2020 Victor Trucco
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity soundrive is
|
||||
port
|
||||
(
|
||||
clock_i : in std_logic;
|
||||
reset_i : in std_logic;
|
||||
|
||||
cpu_d_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- left
|
||||
|
||||
chA_wr_i : in std_logic;
|
||||
chB_wr_i : in std_logic;
|
||||
|
||||
-- right
|
||||
|
||||
chC_wr_i : in std_logic;
|
||||
chD_wr_i : in std_logic;
|
||||
|
||||
-- nextreg mirrors
|
||||
|
||||
nr_mono_we_i : in std_logic;
|
||||
nr_left_we_i : in std_logic;
|
||||
nr_right_we_i : in std_logic;
|
||||
|
||||
nr_audio_dat_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- pcm audio out
|
||||
|
||||
pcm_L_o : out std_logic_vector(8 downto 0);
|
||||
pcm_R_o : out std_logic_vector(8 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of soundrive is
|
||||
|
||||
signal chA : std_logic_vector(7 downto 0);
|
||||
signal chB : std_logic_vector(7 downto 0);
|
||||
signal chC : std_logic_vector(7 downto 0);
|
||||
signal chD : std_logic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_i = '1' then
|
||||
|
||||
chA <= X"80";
|
||||
chB <= X"80";
|
||||
chC <= X"80";
|
||||
chD <= X"80";
|
||||
|
||||
else
|
||||
|
||||
if chA_wr_i = '1' then
|
||||
chA <= cpu_d_i;
|
||||
elsif nr_mono_we_i = '1' then
|
||||
chA <= nr_audio_dat_i;
|
||||
end if;
|
||||
|
||||
if chB_wr_i = '1' then
|
||||
chB <= cpu_d_i;
|
||||
elsif nr_left_we_i = '1' then
|
||||
chB <= nr_audio_dat_i;
|
||||
end if;
|
||||
|
||||
if chC_wr_i = '1' then
|
||||
chC <= cpu_d_i;
|
||||
elsif nr_right_we_i = '1' then
|
||||
chC <= nr_audio_dat_i;
|
||||
end if;
|
||||
|
||||
if chD_wr_i = '1' then
|
||||
chD <= cpu_d_i;
|
||||
elsif nr_mono_we_i = '1' then
|
||||
chD <= nr_audio_dat_i;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
pcm_L_o <= ('0' & chA) + ('0' & chB);
|
||||
pcm_R_o <= ('0' & chC) + ('0' & chD);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
339
rtl/audio/turbosound.vhd
Normal file
339
rtl/audio/turbosound.vhd
Normal file
@@ -0,0 +1,339 @@
|
||||
|
||||
-- TurboSound Next
|
||||
-- Copyright 2020 Fabio Belavenuto and Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity turbosound is
|
||||
port
|
||||
(
|
||||
clock_i : in std_logic;
|
||||
clock_en_i : in std_logic;
|
||||
|
||||
reset_i : in std_logic;
|
||||
|
||||
aymode_i : in std_logic; -- 0 = YM, 1 = AY
|
||||
turbosound_en_i : in std_logic; -- 0 = use one AY, 1 = enable all AY
|
||||
|
||||
psg_reg_addr_i : in std_logic; -- select a new ay register
|
||||
psg_reg_wr_i : in std_logic; -- write to selected register
|
||||
psg_d_i : in std_logic_vector(7 downto 0); -- data in
|
||||
psg_d_o_reg_i : in std_logic; -- output selected register rather than contents
|
||||
psg_d_o : out std_logic_vector(7 downto 0); -- selected register's contents
|
||||
|
||||
mono_mode_i : in std_logic_vector(2 downto 0); -- 0 = stereo, 1 = mono for each psg
|
||||
stereo_mode_i : in std_logic; -- 0 = ABC, 1 = ACB for all psg
|
||||
|
||||
-- port_a_i : in std_logic_vector(7 downto 0); -- IO Port A input on default AY
|
||||
-- port_a_o : out std_logic_vector(7 downto 0); -- current R14 state
|
||||
|
||||
pcm_ay_L_o : out std_logic_vector(11 downto 0);
|
||||
pcm_ay_R_o : out std_logic_vector(11 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of turbosound is
|
||||
|
||||
signal ay_select : std_logic_vector(1 downto 0);
|
||||
signal psg0_pan : std_logic_vector(1 downto 0);
|
||||
signal psg1_pan : std_logic_vector(1 downto 0);
|
||||
signal psg2_pan : std_logic_vector(1 downto 0);
|
||||
signal psg_addr : std_logic;
|
||||
signal psg0_addr : std_logic;
|
||||
signal psg0_we : std_logic;
|
||||
signal psg1_addr : std_logic;
|
||||
signal psg1_we : std_logic;
|
||||
signal psg2_addr : std_logic;
|
||||
signal psg2_we : std_logic;
|
||||
|
||||
signal psg0_do : std_logic_vector(7 downto 0);
|
||||
signal psg0_A : std_logic_vector(7 downto 0);
|
||||
signal psg0_B : std_logic_vector(7 downto 0);
|
||||
signal psg0_C : std_logic_vector(7 downto 0);
|
||||
signal psg0_L_mux : std_logic_vector(7 downto 0);
|
||||
signal psg0_L_sum : std_logic_vector(8 downto 0);
|
||||
signal psg0_R_mux : std_logic_vector(8 downto 0);
|
||||
signal psg0_R_sum : std_logic_vector(9 downto 0);
|
||||
signal psg0_L_fin : std_logic_vector(9 downto 0);
|
||||
signal psg0_L : std_logic_vector(9 downto 0);
|
||||
signal psg0_R : std_logic_vector(9 downto 0);
|
||||
|
||||
signal psg1_do : std_logic_vector(7 downto 0);
|
||||
signal psg1_A : std_logic_vector(7 downto 0);
|
||||
signal psg1_B : std_logic_vector(7 downto 0);
|
||||
signal psg1_C : std_logic_vector(7 downto 0);
|
||||
signal psg1_L_mux : std_logic_vector(7 downto 0);
|
||||
signal psg1_L_sum : std_logic_vector(8 downto 0);
|
||||
signal psg1_R_mux : std_logic_vector(8 downto 0);
|
||||
signal psg1_R_sum : std_logic_vector(9 downto 0);
|
||||
signal psg1_L_fin : std_logic_vector(9 downto 0);
|
||||
signal psg1_L : std_logic_vector(9 downto 0);
|
||||
signal psg1_R : std_logic_vector(9 downto 0);
|
||||
|
||||
signal psg2_do : std_logic_vector(7 downto 0);
|
||||
signal psg2_A : std_logic_vector(7 downto 0);
|
||||
signal psg2_B : std_logic_vector(7 downto 0);
|
||||
signal psg2_C : std_logic_vector(7 downto 0);
|
||||
signal psg2_L_mux : std_logic_vector(7 downto 0);
|
||||
signal psg2_L_sum : std_logic_vector(8 downto 0);
|
||||
signal psg2_R_mux : std_logic_vector(8 downto 0);
|
||||
signal psg2_R_sum : std_logic_vector(9 downto 0);
|
||||
signal psg2_L_fin : std_logic_vector(9 downto 0);
|
||||
signal psg2_L : std_logic_vector(9 downto 0);
|
||||
signal psg2_R : std_logic_vector(9 downto 0);
|
||||
|
||||
signal psg0_L_pan : std_logic_vector(9 downto 0);
|
||||
signal psg1_L_pan : std_logic_vector(9 downto 0);
|
||||
signal psg2_L_pan : std_logic_vector(9 downto 0);
|
||||
signal psg0_R_pan : std_logic_vector(9 downto 0);
|
||||
signal psg1_R_pan : std_logic_vector(9 downto 0);
|
||||
signal psg2_R_pan : std_logic_vector(9 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
--
|
||||
-- AY Select & Panning
|
||||
--
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_i = '1' then
|
||||
|
||||
ay_select <= "11";
|
||||
|
||||
psg0_pan <= "11";
|
||||
psg1_pan <= "11";
|
||||
psg2_pan <= "11";
|
||||
|
||||
elsif turbosound_en_i = '1' and psg_reg_addr_i = '1' and psg_d_i(7) = '1' and psg_d_i(4 downto 2) = "111" then
|
||||
|
||||
case psg_d_i(1 downto 0) is
|
||||
when "10" => psg1_pan <= psg_d_i(6 downto 5); ay_select <= "10";
|
||||
when "01" => psg2_pan <= psg_d_i(6 downto 5); ay_select <= "01";
|
||||
when others => psg0_pan <= psg_d_i(6 downto 5); ay_select <= "11";
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
psg_addr <= '1' when psg_reg_addr_i = '1' and psg_d_i(7 downto 5) = "000" else '0';
|
||||
|
||||
psg0_addr <= '1' when ay_select = "11" and psg_addr = '1' else '0';
|
||||
psg0_we <= '1' when ay_select = "11" and psg_reg_wr_i = '1' else '0';
|
||||
|
||||
psg1_addr <= '1' when ay_select = "10" and psg_addr = '1' else '0';
|
||||
psg1_we <= '1' when ay_select = "10" and psg_reg_wr_i = '1' else '0';
|
||||
|
||||
psg2_addr <= '1' when ay_select = "01" and psg_addr = '1' else '0';
|
||||
psg2_we <= '1' when ay_select = "01" and psg_reg_wr_i = '1' else '0';
|
||||
|
||||
--
|
||||
-- AY #0
|
||||
--
|
||||
|
||||
psg0 : entity work.ym2149
|
||||
generic map (
|
||||
AY_ID => "11"
|
||||
)
|
||||
port map (
|
||||
CLK => clock_i, -- master clock more than 6MHz
|
||||
ENA => clock_en_i, -- gated clock signal used by ym2149
|
||||
RESET_H => reset_i,
|
||||
I_SEL_L => '1', -- 1 for compatible counting with ay8910
|
||||
-- data bus
|
||||
I_DA => psg_d_i,
|
||||
O_DA => psg0_do, -- read from currently selected register
|
||||
I_REG => psg_d_o_reg_i,
|
||||
-- control
|
||||
busctrl_addr => psg0_addr, -- 1 to change selected register
|
||||
busctrl_we => psg0_we, -- 1 to write to selected register
|
||||
ctrl_aymode => aymode_i, -- 0 = YM, 1 = AY
|
||||
-- I/O ports
|
||||
port_a_i => (others => '1'), -- external input to IO Port A (reg 14) AY#0
|
||||
port_a_o => open, -- last byte written to reg 14 (not the same as reading from reg 14) AY#0
|
||||
port_b_i => (others => '1'),
|
||||
port_b_o => open,
|
||||
-- audio channels out
|
||||
O_AUDIO_A => psg0_A,
|
||||
O_AUDIO_B => psg0_B,
|
||||
O_AUDIO_C => psg0_C
|
||||
);
|
||||
|
||||
-- stereo / mono mix
|
||||
|
||||
psg0_L_mux <= psg0_C when stereo_mode_i = '1' or mono_mode_i(0) = '1' else psg0_B;
|
||||
psg0_L_sum <= ('0' & psg0_L_mux) + ('0' & psg0_A);
|
||||
|
||||
psg0_R_mux <= psg0_L_sum when mono_mode_i(0) = '1' else ('0' & psg0_C);
|
||||
psg0_R_sum <= ('0' & psg0_R_mux) + ("00" & psg0_B);
|
||||
|
||||
psg0_L_fin <= psg0_R_sum when mono_mode_i(0) = '1' else ('0' & psg0_L_sum);
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if ay_select = "11" or turbosound_en_i = '1' then
|
||||
psg0_L <= psg0_L_fin;
|
||||
psg0_R <= psg0_R_sum;
|
||||
else
|
||||
psg0_L <= (others => '0');
|
||||
psg0_R <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--
|
||||
-- AY #1
|
||||
--
|
||||
|
||||
psg1 : entity work.ym2149
|
||||
generic map (
|
||||
AY_ID => "10"
|
||||
)
|
||||
port map (
|
||||
CLK => clock_i,
|
||||
ENA => clock_en_i,
|
||||
RESET_H => reset_i,
|
||||
I_SEL_L => '1',
|
||||
-- data bus
|
||||
I_DA => psg_d_i,
|
||||
O_DA => psg1_do,
|
||||
I_REG => psg_d_o_reg_i,
|
||||
-- control
|
||||
busctrl_addr => psg1_addr,
|
||||
busctrl_we => psg1_we,
|
||||
ctrl_aymode => aymode_i,
|
||||
-- I/O ports
|
||||
port_a_i => (others => '1'),
|
||||
port_a_o => open,
|
||||
port_b_i => (others => '1'),
|
||||
port_b_o => open,
|
||||
-- audio channels out
|
||||
O_AUDIO_A => psg1_A,
|
||||
O_AUDIO_B => psg1_B,
|
||||
O_AUDIO_C => psg1_C
|
||||
);
|
||||
|
||||
-- stereo / mono mix
|
||||
|
||||
psg1_L_mux <= psg1_C when stereo_mode_i = '1' or mono_mode_i(1) = '1' else psg1_B;
|
||||
psg1_L_sum <= ('0' & psg1_L_mux) + ('0' & psg1_A);
|
||||
|
||||
psg1_R_mux <= psg1_L_sum when mono_mode_i(1) = '1' else ('0' & psg1_C);
|
||||
psg1_R_sum <= ('0' & psg1_R_mux) + ("00" & psg1_B);
|
||||
|
||||
psg1_L_fin <= psg1_R_sum when mono_mode_i(1) = '1' else ('0' & psg1_L_sum);
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if ay_select = "10" or turbosound_en_i = '1' then
|
||||
psg1_L <= psg1_L_fin;
|
||||
psg1_R <= psg1_R_sum;
|
||||
else
|
||||
psg1_L <= (others => '0');
|
||||
psg1_R <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--
|
||||
-- AY #2
|
||||
--
|
||||
|
||||
psg2 : entity work.ym2149
|
||||
generic map (
|
||||
AY_ID => "01"
|
||||
)
|
||||
port map (
|
||||
CLK => clock_i,
|
||||
ENA => clock_en_i,
|
||||
RESET_H => reset_i,
|
||||
I_SEL_L => '1',
|
||||
-- data bus
|
||||
I_DA => psg_d_i,
|
||||
O_DA => psg2_do,
|
||||
I_REG => psg_d_o_reg_i,
|
||||
-- control
|
||||
busctrl_addr => psg2_addr,
|
||||
busctrl_we => psg2_we,
|
||||
ctrl_aymode => aymode_i,
|
||||
-- I/O ports
|
||||
port_a_i => (others => '1'),
|
||||
port_a_o => open,
|
||||
port_b_i => (others => '1'),
|
||||
port_b_o => open,
|
||||
-- audio channels out
|
||||
O_AUDIO_A => psg2_A,
|
||||
O_AUDIO_B => psg2_B,
|
||||
O_AUDIO_C => psg2_C
|
||||
);
|
||||
|
||||
-- stereo / mono mix
|
||||
|
||||
psg2_L_mux <= psg2_C when stereo_mode_i = '1' or mono_mode_i(2) = '1' else psg2_B;
|
||||
psg2_L_sum <= ('0' & psg2_L_mux) + ('0' & psg2_A);
|
||||
|
||||
psg2_R_mux <= psg2_L_sum when mono_mode_i(2) = '1' else ('0' & psg2_C);
|
||||
psg2_R_sum <= ('0' & psg2_R_mux) + ("00" & psg2_B);
|
||||
|
||||
psg2_L_fin <= psg2_R_sum when mono_mode_i(2) = '1' else ('0' & psg2_L_sum);
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if ay_select = "01" or turbosound_en_i = '1' then
|
||||
psg2_L <= psg2_L_fin;
|
||||
psg2_R <= psg2_R_sum;
|
||||
else
|
||||
psg2_L <= (others => '0');
|
||||
psg2_R <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--
|
||||
-- Turbosound Output
|
||||
--
|
||||
|
||||
psg_d_o <= psg1_do when ay_select = "10" else psg2_do when ay_select = "01" else psg0_do;
|
||||
|
||||
psg0_L_pan <= psg0_L when psg0_pan(1) = '1' else (others => '0');
|
||||
psg1_L_pan <= psg1_L when psg1_pan(1) = '1' else (others => '0');
|
||||
psg2_L_pan <= psg2_L when psg2_pan(1) = '1' else (others => '0');
|
||||
|
||||
psg0_R_pan <= psg0_R when psg0_pan(0) = '1' else (others => '0');
|
||||
psg1_R_pan <= psg1_R when psg1_pan(0) = '1' else (others => '0');
|
||||
psg2_R_pan <= psg2_R when psg2_pan(0) = '1' else (others => '0');
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
pcm_ay_L_o <= ("00" & psg0_L_pan) + ("00" & psg1_L_pan) + ("00" & psg2_L_pan);
|
||||
pcm_ay_R_o <= ("00" & psg0_R_pan) + ("00" & psg1_R_pan) + ("00" & psg2_R_pan);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
543
rtl/audio/ym2149.vhd
Normal file
543
rtl/audio/ym2149.vhd
Normal file
@@ -0,0 +1,543 @@
|
||||
--
|
||||
-- A simulation model of YM2149 (AY-3-8910 with bells on)
|
||||
--
|
||||
-- Copyright (c) MikeJ - Jan 2005
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- You are responsible for any legal issues arising from your use of this code.
|
||||
--
|
||||
-- The latest version of this file can be found at: www.fpgaarcade.com
|
||||
--
|
||||
-- Email support@fpgaarcade.com
|
||||
--
|
||||
-- Revision list
|
||||
--
|
||||
-- version 001 initial release
|
||||
--
|
||||
-- Clues from MAME sound driver and Kazuhiro TSUJIKAWA
|
||||
--
|
||||
-- These are the measured outputs from a real chip for a single Isolated channel into a 1K load (V)
|
||||
-- vol 15 .. 0
|
||||
-- 3.27 2.995 2.741 2.588 2.452 2.372 2.301 2.258 2.220 2.198 2.178 2.166 2.155 2.148 2.141 2.132
|
||||
-- As the envelope volume is 5 bit, I have fitted a curve to the not quite log shape in order
|
||||
-- to produced all the required values.
|
||||
-- (The first part of the curve is a bit steeper and the last bit is more linear than expected)
|
||||
--
|
||||
|
||||
-- Modifications made for the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- 1. Bus addressing moved out of module
|
||||
-- 2. Channel mixing moved out of module
|
||||
-- 3. Eliminate unnecessary busctrl_re
|
||||
-- 4. Make zero volume actually zero volume in the tables.
|
||||
-- (Not how the real hw works but it makes audio out of the zx next cleaner)
|
||||
-- 5. Add differences in how registers are read back on YM and AY
|
||||
-- 6. Fix bug where envelope period counter was not reset on envelope reset
|
||||
-- 7. Export currently selected register
|
||||
|
||||
library ieee;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity YM2149 is
|
||||
generic (
|
||||
constant AY_ID : std_logic_vector(1 downto 0) := "00"
|
||||
);
|
||||
port (
|
||||
CLK : in std_logic; -- note 6 Mhz
|
||||
ENA : in std_logic; -- clock enable for higher speed operation
|
||||
RESET_H : in std_logic;
|
||||
I_SEL_L : in std_logic;
|
||||
-- data bus
|
||||
I_DA : in std_logic_vector(7 downto 0);
|
||||
O_DA : out std_logic_vector(7 downto 0);
|
||||
I_REG : in std_logic;
|
||||
-- control
|
||||
busctrl_addr : in std_logic;
|
||||
busctrl_we : in std_logic;
|
||||
ctrl_aymode : in std_logic; -- 0 = YM, 1 = AY
|
||||
-- I/O ports
|
||||
port_a_i : in std_logic_vector(7 downto 0);
|
||||
port_a_o : out std_logic_vector(7 downto 0);
|
||||
port_b_i : in std_logic_vector(7 downto 0);
|
||||
port_b_o : out std_logic_vector(7 downto 0);
|
||||
-- audio channels out
|
||||
O_AUDIO_A : out std_logic_vector(7 downto 0);
|
||||
O_AUDIO_B : out std_logic_vector(7 downto 0);
|
||||
O_AUDIO_C : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end;
|
||||
|
||||
architecture RTL of YM2149 is
|
||||
|
||||
-- signals
|
||||
type array_16x8 is array (0 to 15) of std_logic_vector(7 downto 0);
|
||||
type array_3x12 is array (1 to 3) of std_logic_vector(11 downto 0);
|
||||
|
||||
signal cnt_div : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal noise_div : std_logic := '0';
|
||||
signal ena_div : std_logic;
|
||||
signal ena_div_noise : std_logic;
|
||||
signal noise_gen_comp : std_logic_vector(4 downto 0);
|
||||
signal poly17_zero : std_logic;
|
||||
signal poly17 : std_logic_vector(16 downto 0) := (others => '0');
|
||||
|
||||
-- registers
|
||||
signal addr : std_logic_vector(4 downto 0);
|
||||
|
||||
signal reg : array_16x8;
|
||||
signal env_reset : std_logic;
|
||||
|
||||
signal noise_gen_cnt : std_logic_vector(4 downto 0);
|
||||
signal noise_gen_op : std_logic;
|
||||
signal tone_gen_freq : array_3x12;
|
||||
signal tone_gen_comp : array_3x12;
|
||||
signal tone_gen_cnt : array_3x12 := (others => (others => '0'));
|
||||
signal tone_gen_op : std_logic_vector(3 downto 1) := "000";
|
||||
|
||||
signal is_zero : std_logic;
|
||||
signal is_ones : std_logic;
|
||||
signal is_bot : std_logic;
|
||||
signal is_bot_p1 : std_logic;
|
||||
signal is_top_m1 : std_logic;
|
||||
signal is_top : std_logic;
|
||||
|
||||
signal env_gen_freq : std_logic_vector(15 downto 0);
|
||||
signal env_gen_comp : std_logic_vector(15 downto 0);
|
||||
signal env_gen_cnt : std_logic_vector(15 downto 0);
|
||||
signal env_ena : std_logic;
|
||||
signal env_hold : std_logic;
|
||||
signal env_inc : std_logic;
|
||||
signal env_vol : std_logic_vector(4 downto 0);
|
||||
|
||||
signal chan_mixed : std_logic_vector(2 downto 0);
|
||||
|
||||
signal A : std_logic_vector(4 downto 0);
|
||||
signal B : std_logic_vector(4 downto 0);
|
||||
signal C : std_logic_vector(4 downto 0);
|
||||
|
||||
type volTableType32 is array (0 to 31) of unsigned(7 downto 0);
|
||||
type volTableType16 is array (0 to 15) of unsigned(7 downto 0);
|
||||
|
||||
constant volTableAy : volTableType16 :=(
|
||||
x"00", x"03", x"04", x"06",
|
||||
x"0a", x"0f", x"15", x"22",
|
||||
x"28", x"41", x"5b", x"72",
|
||||
x"90", x"b5", x"d7", x"ff"
|
||||
);
|
||||
|
||||
constant volTableYm : volTableType32 :=(
|
||||
x"00", x"01", x"01", x"02", x"02", x"03", x"03", x"04",
|
||||
x"06", x"07", x"09", x"0a", x"0c", x"0e", x"11", x"13",
|
||||
x"17", x"1b", x"20", x"25", x"2c", x"35", x"3e", x"47",
|
||||
x"54", x"66", x"77", x"88", x"a1", x"c0", x"e0", x"ff"
|
||||
);
|
||||
|
||||
begin
|
||||
|
||||
--p_waddr : process(RESET_H, busctrl_addr)
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
if (RESET_H = '1') then
|
||||
addr <= (others => '0');
|
||||
elsif busctrl_addr = '1' then -- yuk
|
||||
addr <= I_DA(4 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--p_wdata : process(RESET_H, busctrl_we, addr)
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
env_reset <= '0';
|
||||
|
||||
if RESET_H = '1' then
|
||||
reg <= (others => (others => '0'));
|
||||
reg(7) <= x"ff";
|
||||
|
||||
elsif busctrl_we = '1' and addr(4) = '0' then -- bits 7:5 are checked for 0 outside this module
|
||||
case addr(3 downto 0) is
|
||||
when x"0" => reg(0) <= I_DA;
|
||||
when x"1" => reg(1) <= I_DA;
|
||||
when x"2" => reg(2) <= I_DA;
|
||||
when x"3" => reg(3) <= I_DA;
|
||||
when x"4" => reg(4) <= I_DA;
|
||||
when x"5" => reg(5) <= I_DA;
|
||||
when x"6" => reg(6) <= I_DA;
|
||||
when x"7" => reg(7) <= I_DA;
|
||||
when x"8" => reg(8) <= I_DA;
|
||||
when x"9" => reg(9) <= I_DA;
|
||||
when x"A" => reg(10) <= I_DA;
|
||||
when x"B" => reg(11) <= I_DA;
|
||||
when x"C" => reg(12) <= I_DA;
|
||||
when x"D" => reg(13) <= I_DA;
|
||||
when x"E" => reg(14) <= I_DA;
|
||||
when x"F" => reg(15) <= I_DA;
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
if addr(3 downto 0) = x"D" then
|
||||
env_reset <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--p_rdata : process(busctrl_re, addr, reg)
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
if I_REG = '1' then
|
||||
O_DA <= AY_ID & '0' & addr;
|
||||
elsif addr(4) = '1' and ctrl_aymode = '0' then
|
||||
O_DA <= x"FF";
|
||||
else
|
||||
case addr(3 downto 0) is
|
||||
when x"0" => O_DA <= reg(0) ;
|
||||
when x"1" => O_DA <= (reg(1)(7) and not ctrl_aymode) & (reg(1)(6) and not ctrl_aymode) & (reg(1)(5) and not ctrl_aymode) & (reg(1)(4) and not ctrl_aymode) & reg(1)(3 downto 0) ;
|
||||
when x"2" => O_DA <= reg(2) ;
|
||||
when x"3" => O_DA <= (reg(3)(7) and not ctrl_aymode) & (reg(3)(6) and not ctrl_aymode) & (reg(3)(5) and not ctrl_aymode) & (reg(3)(4) and not ctrl_aymode) & reg(3)(3 downto 0) ;
|
||||
when x"4" => O_DA <= reg(4) ;
|
||||
when x"5" => O_DA <= (reg(5)(7) and not ctrl_aymode) & (reg(5)(6) and not ctrl_aymode) & (reg(5)(5) and not ctrl_aymode) & (reg(5)(4) and not ctrl_aymode) & reg(5)(3 downto 0) ;
|
||||
when x"6" => O_DA <= (reg(6)(7) and not ctrl_aymode) & (reg(6)(6) and not ctrl_aymode) & (reg(6)(5) and not ctrl_aymode) & reg(6)(4 downto 0) ;
|
||||
when x"7" => O_DA <= reg(7) ;
|
||||
when x"8" => O_DA <= (reg(8)(7) and not ctrl_aymode) & (reg(8)(6) and not ctrl_aymode) & (reg(8)(5) and not ctrl_aymode) & reg(8)(4 downto 0) ;
|
||||
when x"9" => O_DA <= (reg(9)(7) and not ctrl_aymode) & (reg(9)(6) and not ctrl_aymode) & (reg(9)(5) and not ctrl_aymode) & reg(9)(4 downto 0) ;
|
||||
when x"A" => O_DA <= (reg(10)(7) and not ctrl_aymode) & (reg(10)(6) and not ctrl_aymode) & (reg(10)(5) and not ctrl_aymode) & reg(10)(4 downto 0) ;
|
||||
when x"B" => O_DA <= reg(11);
|
||||
when x"C" => O_DA <= reg(12);
|
||||
when x"D" => O_DA <= (reg(13)(7) and not ctrl_aymode) & (reg(13)(6) and not ctrl_aymode) & (reg(13)(5) and not ctrl_aymode) & (reg(13)(4) and not ctrl_aymode) & reg(13)(3 downto 0) ;
|
||||
when x"E" => if (reg(7)(6) = '0') then -- input
|
||||
O_DA <= port_a_i;
|
||||
else
|
||||
O_DA <= reg(14) and port_a_i;
|
||||
end if;
|
||||
when x"F" => if (Reg(7)(7) = '0') then
|
||||
O_DA <= port_b_i;
|
||||
else
|
||||
O_DA <= reg(15) and port_b_i;
|
||||
end if;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
port_a_o <= reg(14);
|
||||
port_b_o <= reg(15);
|
||||
|
||||
-- p_divider : process
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
if ENA = '1' then
|
||||
ena_div <= '0';
|
||||
ena_div_noise <= '0';
|
||||
if (cnt_div = "0000") then
|
||||
cnt_div <= (not I_SEL_L) & "111";
|
||||
ena_div <= '1';
|
||||
|
||||
noise_div <= not noise_div;
|
||||
if (noise_div = '1') then
|
||||
ena_div_noise <= '1';
|
||||
end if;
|
||||
else
|
||||
cnt_div <= std_logic_vector(unsigned(cnt_div) - 1);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- p_noise_gen : process
|
||||
|
||||
noise_gen_comp <= (std_logic_vector(unsigned(reg(6)(4 downto 0)) - 1)) when (reg(6)(4 downto 1) /= "0000") else (others => '0');
|
||||
poly17_zero <= '1' when (poly17 = "00000000000000000") else '0';
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
if (ENA = '1') then
|
||||
if (ena_div_noise = '1') then -- divider ena
|
||||
if (noise_gen_cnt >= noise_gen_comp) then
|
||||
noise_gen_cnt <= "00000";
|
||||
poly17 <= (poly17(0) xor poly17(2) xor poly17_zero) & poly17(16 downto 1);
|
||||
else
|
||||
noise_gen_cnt <= std_logic_vector(unsigned(noise_gen_cnt) + 1);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
noise_gen_op <= poly17(0);
|
||||
|
||||
--p_tone_gens : process
|
||||
|
||||
tone_gen_freq(1) <= reg(1)(3 downto 0) & reg(0);
|
||||
tone_gen_freq(2) <= reg(3)(3 downto 0) & reg(2);
|
||||
tone_gen_freq(3) <= reg(5)(3 downto 0) & reg(4);
|
||||
|
||||
tone_gen_comp(1) <= (std_logic_vector(unsigned(tone_gen_freq(1)) - 1)) when (tone_gen_freq(1)(11 downto 1) /= (x"00" & "000")) else (others => '0');
|
||||
tone_gen_comp(2) <= (std_logic_vector(unsigned(tone_gen_freq(2)) - 1)) when (tone_gen_freq(2)(11 downto 1) /= (x"00" & "000")) else (others => '0');
|
||||
tone_gen_comp(3) <= (std_logic_vector(unsigned(tone_gen_freq(3)) - 1)) when (tone_gen_freq(3)(11 downto 1) /= (x"00" & "000")) else (others => '0');
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
if (ENA = '1') then
|
||||
for i in 1 to 3 loop
|
||||
if (ena_div = '1') then -- divider ena
|
||||
if (tone_gen_cnt(i) >= tone_gen_comp(i)) then
|
||||
tone_gen_cnt(i) <= x"000";
|
||||
tone_gen_op(i) <= not tone_gen_op(i);
|
||||
else
|
||||
tone_gen_cnt(i) <= std_logic_vector(unsigned(tone_gen_cnt(i)) + 1);
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--p_envelope_freq : process
|
||||
|
||||
env_gen_freq <= reg(12) & reg(11);
|
||||
env_gen_comp <= (std_logic_vector(unsigned(env_gen_freq) - 1)) when (env_gen_freq(15 downto 1) /= (x"000" & "000")) else (others => '0');
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
if env_reset = '1' then
|
||||
env_gen_cnt <= x"0000";
|
||||
env_ena <= '1';
|
||||
elsif (ENA = '1') then
|
||||
if (ena_div = '1') then -- divider ena
|
||||
if (env_gen_cnt >= env_gen_comp) then
|
||||
env_gen_cnt <= x"0000";
|
||||
env_ena <= '1';
|
||||
else
|
||||
env_gen_cnt <= std_logic_vector( unsigned( env_gen_cnt ) + 1 );
|
||||
env_ena <= '0';
|
||||
end if;
|
||||
else
|
||||
env_ena <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--p_envelope_shape : process(env_reset, CLK)
|
||||
|
||||
is_zero <= '1' when env_vol(4 downto 1) = "0000" else '0';
|
||||
is_ones <= '1' when env_vol(4 downto 1) = "1111" else '0';
|
||||
|
||||
is_bot <= '1' when is_zero = '1' and env_vol(0) = '0' else '0';
|
||||
is_bot_p1 <= '1' when is_zero ='1' and env_vol(0) = '1' else '0';
|
||||
is_top_m1 <= '1' when is_ones = '1' and env_vol(0) = '0' else '0';
|
||||
is_top <= '1' when is_ones = '1' and env_vol(0) = '1' else '0';
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
-- envelope shapes
|
||||
-- C AtAlH
|
||||
-- 0 0 x x \___
|
||||
--
|
||||
-- 0 1 x x /___
|
||||
--
|
||||
-- 1 0 0 0 \\\\
|
||||
--
|
||||
-- 1 0 0 1 \___
|
||||
--
|
||||
-- 1 0 1 0 \/\/
|
||||
-- ___
|
||||
-- 1 0 1 1 \
|
||||
--
|
||||
-- 1 1 0 0 ////
|
||||
-- ___
|
||||
-- 1 1 0 1 /
|
||||
--
|
||||
-- 1 1 1 0 /\/\
|
||||
--
|
||||
-- 1 1 1 1 /___
|
||||
if clk'event and clk = '1' then
|
||||
if env_reset = '1' then
|
||||
-- load initial state
|
||||
if (reg(13)(2) = '0') then -- attack
|
||||
env_vol <= "11111";
|
||||
env_inc <= '0'; -- -1
|
||||
else
|
||||
env_vol <= "00000";
|
||||
env_inc <= '1'; -- +1
|
||||
end if;
|
||||
env_hold <= '0';
|
||||
elsif (ENA = '1') and (env_ena = '1') then
|
||||
if (env_hold = '0') then
|
||||
if (env_inc = '1') then
|
||||
env_vol <= std_logic_vector( unsigned( env_vol ) + "00001");
|
||||
else
|
||||
env_vol <= std_logic_vector( unsigned( env_vol ) + "11111");
|
||||
end if;
|
||||
end if;
|
||||
-- envelope shape control.
|
||||
if (reg(13)(3) = '0') then
|
||||
if (env_inc = '0') then -- down
|
||||
if is_bot_p1 = '1' then
|
||||
env_hold <= '1';
|
||||
end if;
|
||||
else
|
||||
if is_top = '1' then
|
||||
env_hold <= '1';
|
||||
end if;
|
||||
end if;
|
||||
elsif (reg(13)(0) = '1') then -- hold = 1
|
||||
if (env_inc = '0') then -- down
|
||||
if (reg(13)(1) = '1') then -- alt
|
||||
if is_bot = '1' then
|
||||
env_hold <= '1';
|
||||
end if;
|
||||
else
|
||||
if is_bot_p1 = '1' then
|
||||
env_hold <= '1';
|
||||
end if;
|
||||
end if;
|
||||
else
|
||||
if (reg(13)(1) = '1') then -- alt
|
||||
if is_top = '1' then
|
||||
env_hold <= '1';
|
||||
end if;
|
||||
else
|
||||
if is_top_m1 = '1' then
|
||||
env_hold <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
elsif (reg(13)(1) = '1') then -- alternate
|
||||
if (env_inc = '0') then -- down
|
||||
if is_bot_p1 = '1' then
|
||||
env_hold <= '1';
|
||||
end if;
|
||||
if is_bot = '1' then
|
||||
env_hold <= '0';
|
||||
env_inc <= '1';
|
||||
end if;
|
||||
else
|
||||
if is_top_m1 = '1' then
|
||||
env_hold <= '1';
|
||||
end if;
|
||||
if is_top = '1' then
|
||||
env_hold <= '0';
|
||||
env_inc <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--p_chan_mixer_table : process
|
||||
|
||||
chan_mixed(0) <= (reg(7)(0) or tone_gen_op(1)) and (reg(7)(3) or noise_gen_op);
|
||||
chan_mixed(1) <= (reg(7)(1) or tone_gen_op(2)) and (reg(7)(4) or noise_gen_op);
|
||||
chan_mixed(2) <= (reg(7)(2) or tone_gen_op(3)) and (reg(7)(5) or noise_gen_op);
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
if (ENA = '1') then
|
||||
|
||||
A <= "00000";
|
||||
B <= "00000";
|
||||
C <= "00000";
|
||||
|
||||
if (chan_mixed(0) = '1') then
|
||||
if (reg(8)(4) = '0') then
|
||||
if (reg(8)(3 downto 0) = "0000") then
|
||||
A <= "00000";
|
||||
else
|
||||
A <= reg(8)(3 downto 0) & "1";
|
||||
end if;
|
||||
else
|
||||
A <= env_vol(4 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if (chan_mixed(1) = '1') then
|
||||
if (reg(9)(4) = '0') then
|
||||
if (reg(9)(3 downto 0) = "0000") then
|
||||
B <= "00000";
|
||||
else
|
||||
B <= reg(9)(3 downto 0) & "1";
|
||||
end if;
|
||||
else
|
||||
B <= env_vol(4 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if (chan_mixed(2) = '1') then
|
||||
if (reg(10)(4) = '0') then
|
||||
if (reg(10)(3 downto 0) = "0000") then
|
||||
C <= "00000";
|
||||
else
|
||||
C <= reg(10)(3 downto 0) & "1";
|
||||
end if;
|
||||
else
|
||||
C <= env_vol(4 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if clk'event and clk = '1' then
|
||||
if RESET_H = '1' then
|
||||
O_AUDIO_A <= x"00";
|
||||
O_AUDIO_B <= x"00";
|
||||
O_AUDIO_C <= x"00";
|
||||
else
|
||||
if(ctrl_aymode = '0') then
|
||||
O_AUDIO_A <= std_logic_vector( volTableYm( to_integer( unsigned( A ) ) ) );
|
||||
O_AUDIO_B <= std_logic_vector( volTableYm( to_integer( unsigned( B ) ) ) );
|
||||
O_AUDIO_C <= std_logic_vector( volTableYm( to_integer( unsigned( C ) ) ) );
|
||||
else
|
||||
O_AUDIO_A <= std_logic_vector( volTableAy( to_integer( unsigned( A(4 downto 1) ) ) ) );
|
||||
O_AUDIO_B <= std_logic_vector( volTableAy( to_integer( unsigned( B(4 downto 1) ) ) ) );
|
||||
O_AUDIO_C <= std_logic_vector( volTableAy( to_integer( unsigned( C(4 downto 1) ) ) ) );
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture RTL;
|
||||
1772
rtl/cpu/t80n.vhd
Normal file
1772
rtl/cpu/t80n.vhd
Normal file
File diff suppressed because it is too large
Load Diff
364
rtl/cpu/t80n_alu.vhd
Normal file
364
rtl/cpu/t80n_alu.vhd
Normal file
@@ -0,0 +1,364 @@
|
||||
--
|
||||
-- Z80 compatible microprocessor core
|
||||
--
|
||||
-- Version : 0247
|
||||
--
|
||||
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
|
||||
--
|
||||
-- Modifications for the ZX Spectrum Next Project
|
||||
-- Copyright 2020 Fabio Belavenuto, Victor Trucco, Charlie Ingley, Garry Lancaster, ACX
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- Please report bugs to the author, but before you do so, please
|
||||
-- make sure that this is not a derivative work and that
|
||||
-- you have the latest version of this file.
|
||||
--
|
||||
-- The latest version of this file can be found at:
|
||||
-- http://www.opencores.org/cvsweb.shtml/t80/
|
||||
--
|
||||
-- Limitations :
|
||||
--
|
||||
-- File history :
|
||||
--
|
||||
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
|
||||
--
|
||||
-- 0238 : Fixed zero flag for 16 bit SBC and ADC
|
||||
--
|
||||
-- 0240 : Added GB operations
|
||||
--
|
||||
-- 0242 : Cleanup
|
||||
--
|
||||
-- 0247 : Cleanup
|
||||
--
|
||||
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- Modifications for the ZX Spectrum Next were made by:
|
||||
--
|
||||
-- Fabio Belavenuto : partial fix of wait bug
|
||||
-- Victor Trucco, Fabio Belavenuto, Garry Lancaster : additional instructions
|
||||
-- Charlie Ingley : complete fix of wait logic
|
||||
-- ACX : implement undocumented flags for SLI r,(IY+s)
|
||||
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity T80N_ALU is
|
||||
generic(
|
||||
Mode : integer := 0;
|
||||
Flag_C : integer := 0;
|
||||
Flag_N : integer := 1;
|
||||
Flag_P : integer := 2;
|
||||
Flag_X : integer := 3;
|
||||
Flag_H : integer := 4;
|
||||
Flag_Y : integer := 5;
|
||||
Flag_Z : integer := 6;
|
||||
Flag_S : integer := 7
|
||||
);
|
||||
port(
|
||||
Arith16 : in std_logic;
|
||||
Z16 : in std_logic;
|
||||
ALU_Op : in std_logic_vector(3 downto 0);
|
||||
IR : in std_logic_vector(5 downto 0);
|
||||
ISet : in std_logic_vector(1 downto 0);
|
||||
BusA : in std_logic_vector(7 downto 0);
|
||||
BusB : in std_logic_vector(7 downto 0);
|
||||
F_In : in std_logic_vector(7 downto 0);
|
||||
Q : out std_logic_vector(7 downto 0);
|
||||
F_Out : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end T80N_ALU;
|
||||
|
||||
architecture rtl of T80N_ALU is
|
||||
|
||||
procedure AddSub(A : std_logic_vector;
|
||||
B : std_logic_vector;
|
||||
Sub : std_logic;
|
||||
Carry_In : std_logic;
|
||||
signal Res : out std_logic_vector;
|
||||
signal Carry : out std_logic) is
|
||||
variable B_i : unsigned(A'length - 1 downto 0);
|
||||
variable Res_i : unsigned(A'length + 1 downto 0);
|
||||
begin
|
||||
if Sub = '1' then
|
||||
B_i := not unsigned(B);
|
||||
else
|
||||
B_i := unsigned(B);
|
||||
end if;
|
||||
Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1");
|
||||
Carry <= Res_i(A'length + 1);
|
||||
Res <= std_logic_vector(Res_i(A'length downto 1));
|
||||
end;
|
||||
|
||||
-- AddSub variables (temporary signals)
|
||||
signal UseCarry : std_logic;
|
||||
signal Carry7_v : std_logic;
|
||||
signal Overflow_v : std_logic;
|
||||
signal HalfCarry_v : std_logic;
|
||||
signal Carry_v : std_logic;
|
||||
signal Q_v : std_logic_vector(7 downto 0);
|
||||
|
||||
signal BitMask : std_logic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
with IR(5 downto 3) select BitMask <= "00000001" when "000",
|
||||
"00000010" when "001",
|
||||
"00000100" when "010",
|
||||
"00001000" when "011",
|
||||
"00010000" when "100",
|
||||
"00100000" when "101",
|
||||
"01000000" when "110",
|
||||
"10000000" when others;
|
||||
|
||||
UseCarry <= not ALU_Op(2) and ALU_Op(0);
|
||||
AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v);
|
||||
AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v);
|
||||
AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v);
|
||||
OverFlow_v <= Carry_v xor Carry7_v;
|
||||
|
||||
process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
|
||||
variable Q_t : std_logic_vector(7 downto 0);
|
||||
variable DAA_Q : unsigned(8 downto 0);
|
||||
begin
|
||||
Q_t := "--------";
|
||||
F_Out <= F_In;
|
||||
DAA_Q := "---------";
|
||||
case ALU_Op is
|
||||
when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" =>
|
||||
F_Out(Flag_N) <= '0';
|
||||
F_Out(Flag_C) <= '0';
|
||||
case ALU_OP(2 downto 0) is
|
||||
when "000" | "001" => -- ADD, ADC
|
||||
Q_t := Q_v;
|
||||
F_Out(Flag_C) <= Carry_v;
|
||||
F_Out(Flag_H) <= HalfCarry_v;
|
||||
F_Out(Flag_P) <= OverFlow_v;
|
||||
when "010" | "011" | "111" => -- SUB, SBC, CP
|
||||
Q_t := Q_v;
|
||||
F_Out(Flag_N) <= '1';
|
||||
F_Out(Flag_C) <= not Carry_v;
|
||||
F_Out(Flag_H) <= not HalfCarry_v;
|
||||
F_Out(Flag_P) <= OverFlow_v;
|
||||
when "100" => -- AND
|
||||
Q_t(7 downto 0) := BusA and BusB;
|
||||
F_Out(Flag_H) <= '1';
|
||||
when "101" => -- XOR
|
||||
Q_t(7 downto 0) := BusA xor BusB;
|
||||
F_Out(Flag_H) <= '0';
|
||||
when others => -- OR "110"
|
||||
Q_t(7 downto 0) := BusA or BusB;
|
||||
F_Out(Flag_H) <= '0';
|
||||
end case;
|
||||
if ALU_Op(2 downto 0) = "111" then -- CP
|
||||
F_Out(Flag_X) <= BusB(3);
|
||||
F_Out(Flag_Y) <= BusB(5);
|
||||
else
|
||||
F_Out(Flag_X) <= Q_t(3);
|
||||
F_Out(Flag_Y) <= Q_t(5);
|
||||
end if;
|
||||
if Q_t(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
if Z16 = '1' then
|
||||
F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC
|
||||
end if;
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_S) <= Q_t(7);
|
||||
case ALU_Op(2 downto 0) is
|
||||
when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP
|
||||
when others =>
|
||||
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
|
||||
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
|
||||
end case;
|
||||
if Arith16 = '1' then
|
||||
F_Out(Flag_S) <= F_In(Flag_S);
|
||||
F_Out(Flag_Z) <= F_In(Flag_Z);
|
||||
F_Out(Flag_P) <= F_In(Flag_P);
|
||||
end if;
|
||||
when "1100" =>
|
||||
-- DAA
|
||||
F_Out(Flag_H) <= F_In(Flag_H);
|
||||
F_Out(Flag_C) <= F_In(Flag_C);
|
||||
DAA_Q(7 downto 0) := unsigned(BusA);
|
||||
DAA_Q(8) := '0';
|
||||
if F_In(Flag_N) = '0' then
|
||||
-- After addition
|
||||
-- Alow > 9 or H = 1
|
||||
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
|
||||
if (DAA_Q(3 downto 0) > 9) then
|
||||
F_Out(Flag_H) <= '1';
|
||||
else
|
||||
F_Out(Flag_H) <= '0';
|
||||
end if;
|
||||
DAA_Q := DAA_Q + 6;
|
||||
end if;
|
||||
-- new Ahigh > 9 or C = 1
|
||||
if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then
|
||||
DAA_Q := DAA_Q + 96; -- 0x60
|
||||
end if;
|
||||
else
|
||||
-- After subtraction
|
||||
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
|
||||
if DAA_Q(3 downto 0) > 5 then
|
||||
F_Out(Flag_H) <= '0';
|
||||
end if;
|
||||
DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6;
|
||||
end if;
|
||||
if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then
|
||||
DAA_Q := DAA_Q - 352; -- 0x160
|
||||
end if;
|
||||
end if;
|
||||
F_Out(Flag_X) <= DAA_Q(3);
|
||||
F_Out(Flag_Y) <= DAA_Q(5);
|
||||
F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8);
|
||||
Q_t := std_logic_vector(DAA_Q(7 downto 0));
|
||||
if DAA_Q(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_S) <= DAA_Q(7);
|
||||
F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor
|
||||
DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7));
|
||||
when "1101" | "1110" =>
|
||||
-- RLD, RRD
|
||||
Q_t(7 downto 4) := BusA(7 downto 4);
|
||||
if ALU_Op(0) = '1' then
|
||||
Q_t(3 downto 0) := BusB(7 downto 4);
|
||||
else
|
||||
Q_t(3 downto 0) := BusB(3 downto 0);
|
||||
end if;
|
||||
F_Out(Flag_H) <= '0';
|
||||
F_Out(Flag_N) <= '0';
|
||||
F_Out(Flag_X) <= Q_t(3);
|
||||
F_Out(Flag_Y) <= Q_t(5);
|
||||
if Q_t(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_S) <= Q_t(7);
|
||||
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
|
||||
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
|
||||
when "1001" =>
|
||||
-- BIT
|
||||
Q_t(7 downto 0) := BusB and BitMask;
|
||||
F_Out(Flag_S) <= Q_t(7);
|
||||
if Q_t(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
F_Out(Flag_P) <= '1';
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
F_Out(Flag_P) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_H) <= '1';
|
||||
F_Out(Flag_N) <= '0';
|
||||
F_Out(Flag_X) <= '0';
|
||||
F_Out(Flag_Y) <= '0';
|
||||
if IR(2 downto 0) /= "110" then
|
||||
F_Out(Flag_X) <= BusB(3);
|
||||
F_Out(Flag_Y) <= BusB(5);
|
||||
end if;
|
||||
when "1010" =>
|
||||
-- SET
|
||||
Q_t(7 downto 0) := BusB or BitMask;
|
||||
when "1011" =>
|
||||
-- RES
|
||||
Q_t(7 downto 0) := BusB and not BitMask;
|
||||
when "1000" =>
|
||||
-- ROT
|
||||
case IR(5 downto 3) is
|
||||
when "000" => -- RLC
|
||||
Q_t(7 downto 1) := BusA(6 downto 0);
|
||||
Q_t(0) := BusA(7);
|
||||
F_Out(Flag_C) <= BusA(7);
|
||||
when "010" => -- RL
|
||||
Q_t(7 downto 1) := BusA(6 downto 0);
|
||||
Q_t(0) := F_In(Flag_C);
|
||||
F_Out(Flag_C) <= BusA(7);
|
||||
when "001" => -- RRC
|
||||
Q_t(6 downto 0) := BusA(7 downto 1);
|
||||
Q_t(7) := BusA(0);
|
||||
F_Out(Flag_C) <= BusA(0);
|
||||
when "011" => -- RR
|
||||
Q_t(6 downto 0) := BusA(7 downto 1);
|
||||
Q_t(7) := F_In(Flag_C);
|
||||
F_Out(Flag_C) <= BusA(0);
|
||||
when "100" => -- SLA
|
||||
Q_t(7 downto 1) := BusA(6 downto 0);
|
||||
Q_t(0) := '0';
|
||||
F_Out(Flag_C) <= BusA(7);
|
||||
when "110" => -- SLL (Undocumented) / SWAP
|
||||
if Mode = 3 then
|
||||
Q_t(7 downto 4) := BusA(3 downto 0);
|
||||
Q_t(3 downto 0) := BusA(7 downto 4);
|
||||
F_Out(Flag_C) <= '0';
|
||||
else
|
||||
Q_t(7 downto 1) := BusA(6 downto 0);
|
||||
Q_t(0) := '1';
|
||||
F_Out(Flag_C) <= BusA(7);
|
||||
end if;
|
||||
when "101" => -- SRA
|
||||
Q_t(6 downto 0) := BusA(7 downto 1);
|
||||
Q_t(7) := BusA(7);
|
||||
F_Out(Flag_C) <= BusA(0);
|
||||
when others => -- SRL
|
||||
Q_t(6 downto 0) := BusA(7 downto 1);
|
||||
Q_t(7) := '0';
|
||||
F_Out(Flag_C) <= BusA(0);
|
||||
end case;
|
||||
F_Out(Flag_H) <= '0';
|
||||
F_Out(Flag_N) <= '0';
|
||||
F_Out(Flag_X) <= Q_t(3);
|
||||
F_Out(Flag_Y) <= Q_t(5);
|
||||
F_Out(Flag_S) <= Q_t(7);
|
||||
if Q_t(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
|
||||
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
|
||||
if ISet = "00" then
|
||||
F_Out(Flag_P) <= F_In(Flag_P);
|
||||
F_Out(Flag_S) <= F_In(Flag_S);
|
||||
F_Out(Flag_Z) <= F_In(Flag_Z);
|
||||
end if;
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
Q <= Q_t;
|
||||
end process;
|
||||
|
||||
end;
|
||||
2610
rtl/cpu/t80n_mcode.vhd
Normal file
2610
rtl/cpu/t80n_mcode.vhd
Normal file
File diff suppressed because it is too large
Load Diff
265
rtl/cpu/t80n_pack.vhd
Normal file
265
rtl/cpu/t80n_pack.vhd
Normal file
@@ -0,0 +1,265 @@
|
||||
--
|
||||
-- Z80 compatible microprocessor core
|
||||
--
|
||||
-- Version : 0242
|
||||
--
|
||||
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
|
||||
--
|
||||
-- Modifications for the ZX Spectrum Next Project
|
||||
-- Copyright 2020 Fabio Belavenuto, Victor Trucco, Charlie Ingley, Garry Lancaster, ACX
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- Please report bugs to the author, but before you do so, please
|
||||
-- make sure that this is not a derivative work and that
|
||||
-- you have the latest version of this file.
|
||||
--
|
||||
-- The latest version of this file can be found at:
|
||||
-- http://www.opencores.org/cvsweb.shtml/t80/
|
||||
--
|
||||
-- Limitations :
|
||||
--
|
||||
-- File history :
|
||||
--
|
||||
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- Modifications for the ZX Spectrum Next were made by:
|
||||
--
|
||||
-- Fabio Belavenuto : partial fix of wait bug
|
||||
-- Victor Trucco, Fabio Belavenuto, Garry Lancaster : additional instructions
|
||||
-- Charlie Ingley : complete fix of wait logic
|
||||
-- ACX : implement undocumented flags for SLI r,(IY+s)
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.std_logic_vector;
|
||||
|
||||
package Z80N_pack is
|
||||
type Z80N_seq is ( NONE, MMU, NEXTREGW, MUL_DE, ADD_HL_A, ADD_DE_A, ADD_BC_A, SWAPNIB_A,
|
||||
PIXELDN, SET_A_E, PIXELAD, MIRROR_A, PUSH_nn, LDPIRX, ADD_HL_nn, ADD_DE_nn,
|
||||
ADD_BC_nn, LDIRSCALE, BSLA_DE_B, BSRA_DE_B, BSRL_DE_B, BSRF_DE_B, BRLC_DE_B,
|
||||
JP_C, NMIACK_LSB, NMIACK_MSB, RETN_LSB, RETN_MSB );
|
||||
signal Z80N_seq_s : Z80N_seq;
|
||||
end package;
|
||||
|
||||
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use work.Z80N_pack.all;
|
||||
|
||||
package T80N_Pack is
|
||||
|
||||
|
||||
|
||||
component T80N
|
||||
generic(
|
||||
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
|
||||
IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle
|
||||
Flag_C : integer := 0;
|
||||
Flag_N : integer := 1;
|
||||
Flag_P : integer := 2;
|
||||
Flag_X : integer := 3;
|
||||
Flag_H : integer := 4;
|
||||
Flag_Y : integer := 5;
|
||||
Flag_Z : integer := 6;
|
||||
Flag_S : integer := 7
|
||||
);
|
||||
port(
|
||||
RESET_n : in std_logic;
|
||||
CLK_n : in std_logic;
|
||||
CEN : in std_logic;
|
||||
WAIT_n : in std_logic;
|
||||
INT_n : in std_logic;
|
||||
NMI_n : in std_logic;
|
||||
BUSRQ_n : in std_logic;
|
||||
M1_n : out std_logic;
|
||||
IORQ : out std_logic;
|
||||
NoRead : out std_logic;
|
||||
Write : out std_logic;
|
||||
RFSH_n : out std_logic;
|
||||
HALT_n : out std_logic;
|
||||
BUSAK_n : out std_logic;
|
||||
A : out std_logic_vector(15 downto 0);
|
||||
DInst : in std_logic_vector(7 downto 0);
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
MC : out std_logic_vector(2 downto 0);
|
||||
TS : out std_logic_vector(2 downto 0);
|
||||
IntCycle_n : out std_logic;
|
||||
IntE : out std_logic;
|
||||
Stop : out std_logic;
|
||||
-- extended functions
|
||||
Z80N_dout_o : out std_logic := '0';
|
||||
Z80N_data_o : out std_logic_vector(15 downto 0);
|
||||
Z80N_command_o : out Z80N_seq
|
||||
);
|
||||
end component;
|
||||
|
||||
component T80N_Reg
|
||||
port(
|
||||
Clk : in std_logic;
|
||||
CEN : in std_logic;
|
||||
WEH : in std_logic;
|
||||
WEL : in std_logic;
|
||||
AddrA : in std_logic_vector(2 downto 0);
|
||||
AddrB : in std_logic_vector(2 downto 0);
|
||||
AddrC : in std_logic_vector(2 downto 0);
|
||||
DIH : in std_logic_vector(7 downto 0);
|
||||
DIL : in std_logic_vector(7 downto 0);
|
||||
DOAH : out std_logic_vector(7 downto 0);
|
||||
DOAL : out std_logic_vector(7 downto 0);
|
||||
DOBH : out std_logic_vector(7 downto 0);
|
||||
DOBL : out std_logic_vector(7 downto 0);
|
||||
DOCH : out std_logic_vector(7 downto 0);
|
||||
DOCL : out std_logic_vector(7 downto 0);
|
||||
|
||||
--extended
|
||||
reg_wr_i : in std_logic_vector(5 downto 0) := (others=>'0');
|
||||
reg_BC_i : in std_logic_vector(15 downto 0);
|
||||
reg_HL_i : in std_logic_vector(15 downto 0);
|
||||
reg_DE_i : in std_logic_vector(15 downto 0);
|
||||
reg_BC_o : out std_logic_vector(15 downto 0);
|
||||
reg_HL_o : out std_logic_vector(15 downto 0);
|
||||
reg_DE_o : out std_logic_vector(15 downto 0)
|
||||
|
||||
);
|
||||
end component;
|
||||
|
||||
component T80N_MCode
|
||||
generic(
|
||||
Mode : integer := 0;
|
||||
Flag_C : integer := 0;
|
||||
Flag_N : integer := 1;
|
||||
Flag_P : integer := 2;
|
||||
Flag_X : integer := 3;
|
||||
Flag_H : integer := 4;
|
||||
Flag_Y : integer := 5;
|
||||
Flag_Z : integer := 6;
|
||||
Flag_S : integer := 7
|
||||
);
|
||||
port(
|
||||
IR : in std_logic_vector(7 downto 0);
|
||||
ISet : in std_logic_vector(1 downto 0);
|
||||
MCycle : in std_logic_vector(2 downto 0);
|
||||
F : in std_logic_vector(7 downto 0);
|
||||
NMICycle : in std_logic;
|
||||
IntCycle : in std_logic;
|
||||
XY_State : in std_logic_vector(1 downto 0);
|
||||
MCycles : out std_logic_vector(2 downto 0);
|
||||
TStates : out std_logic_vector(2 downto 0);
|
||||
Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD
|
||||
Inc_PC : out std_logic;
|
||||
Inc_WZ : out std_logic;
|
||||
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
|
||||
Read_To_Reg : out std_logic;
|
||||
Read_To_Acc : out std_logic;
|
||||
Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
|
||||
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
|
||||
ALU_Op : out std_logic_vector(3 downto 0);
|
||||
-- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
|
||||
Save_ALU : out std_logic;
|
||||
PreserveC : out std_logic;
|
||||
Arith16 : out std_logic;
|
||||
Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
|
||||
IORQ : out std_logic;
|
||||
Jump : out std_logic;
|
||||
JumpE : out std_logic;
|
||||
JumpXY : out std_logic;
|
||||
Call : out std_logic;
|
||||
RstP : out std_logic;
|
||||
LDZ : out std_logic;
|
||||
LDW : out std_logic;
|
||||
LDSPHL : out std_logic;
|
||||
Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
|
||||
ExchangeDH : out std_logic;
|
||||
ExchangeRp : out std_logic;
|
||||
ExchangeAF : out std_logic;
|
||||
ExchangeRS : out std_logic;
|
||||
I_DJNZ : out std_logic;
|
||||
I_CPL : out std_logic;
|
||||
I_CCF : out std_logic;
|
||||
I_SCF : out std_logic;
|
||||
I_RETN : out std_logic;
|
||||
I_BT : out std_logic;
|
||||
I_BC : out std_logic;
|
||||
I_BTR : out std_logic;
|
||||
I_RLD : out std_logic;
|
||||
I_RRD : out std_logic;
|
||||
I_INRC : out std_logic;
|
||||
SetDI : out std_logic;
|
||||
SetEI : out std_logic;
|
||||
IMode : out std_logic_vector(1 downto 0);
|
||||
Halt : out std_logic;
|
||||
NoRead : out std_logic;
|
||||
Write : out std_logic;
|
||||
XYbit_undoc : out std_logic;
|
||||
|
||||
-- entended functions
|
||||
ext_ACC_i : in std_logic_vector(7 downto 0);
|
||||
ext_Data_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
Z80N_dout_o : out std_logic := '0';
|
||||
Z80N_data_o : out std_logic_vector(7 downto 0);
|
||||
Z80N_data_o_strobe_lo : out std_logic;
|
||||
Z80N_data_o_strobe_hi : out std_logic;
|
||||
Z80N_command_o : out Z80N_seq
|
||||
);
|
||||
end component;
|
||||
|
||||
component T80N_ALU
|
||||
generic(
|
||||
Mode : integer := 0;
|
||||
Flag_C : integer := 0;
|
||||
Flag_N : integer := 1;
|
||||
Flag_P : integer := 2;
|
||||
Flag_X : integer := 3;
|
||||
Flag_H : integer := 4;
|
||||
Flag_Y : integer := 5;
|
||||
Flag_Z : integer := 6;
|
||||
Flag_S : integer := 7
|
||||
);
|
||||
port(
|
||||
Arith16 : in std_logic;
|
||||
Z16 : in std_logic;
|
||||
ALU_Op : in std_logic_vector(3 downto 0);
|
||||
IR : in std_logic_vector(5 downto 0);
|
||||
ISet : in std_logic_vector(1 downto 0);
|
||||
BusA : in std_logic_vector(7 downto 0);
|
||||
BusB : in std_logic_vector(7 downto 0);
|
||||
F_In : in std_logic_vector(7 downto 0);
|
||||
Q : out std_logic_vector(7 downto 0);
|
||||
F_Out : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
|
||||
|
||||
end;
|
||||
342
rtl/cpu/t80na.vhd
Normal file
342
rtl/cpu/t80na.vhd
Normal file
@@ -0,0 +1,342 @@
|
||||
--
|
||||
-- Z80 compatible microprocessor core, asynchronous top level
|
||||
--
|
||||
-- Version : 0247
|
||||
--
|
||||
-- Copyright 2001-2002 Daniel Wallner (jesus@opencores.org)
|
||||
--
|
||||
-- Modifications for the ZX Spectrum Next Project
|
||||
-- Copyright 2020 Fabio Belavenuto, Victor Trucco, Charlie Ingley, Garry Lancaster, ACX
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- Please report bugs to the author, but before you do so, please make sure that
|
||||
-- this is not a derivative work and that you have the latest version of this file.
|
||||
--
|
||||
-- The latest version of this file can be found at:
|
||||
-- <http://www.opencores.org/cvsweb.shtml/t80/>
|
||||
--
|
||||
-- Limitations :
|
||||
--
|
||||
-- File history :
|
||||
--
|
||||
-- 0208 : First complete release
|
||||
--
|
||||
-- 0211 : Fixed interrupt cycle
|
||||
--
|
||||
-- 0235 : Updated for T80 interface change
|
||||
--
|
||||
-- 0238 : Updated for T80 interface change
|
||||
--
|
||||
-- 0240 : Updated for T80 interface change
|
||||
--
|
||||
-- 0242 : Updated for T80 interface change
|
||||
--
|
||||
-- 0247 : Fixed bus req/ack cycle
|
||||
--
|
||||
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- Modifications for the ZX Spectrum Next were made by:
|
||||
--
|
||||
-- Fabio Belavenuto : partial fix of wait bug
|
||||
-- Victor Trucco, Fabio Belavenuto, Garry Lancaster : additional instructions
|
||||
-- Charlie Ingley : complete fix of wait logic
|
||||
-- ACX : implement undocumented flags for SLI r,(IY+s)
|
||||
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
use work.T80N_Pack.all;
|
||||
use work.Z80N_pack.all;
|
||||
|
||||
entity T80Na is
|
||||
|
||||
generic(
|
||||
Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
|
||||
);
|
||||
port(
|
||||
RESET_n : in std_logic;
|
||||
CLK_n : in std_logic;
|
||||
WAIT_n : in std_logic;
|
||||
INT_n : in std_logic;
|
||||
NMI_n : in std_logic;
|
||||
BUSRQ_n : in std_logic;
|
||||
M1_n : out std_logic;
|
||||
MREQ_n : out std_logic;
|
||||
IORQ_n : out std_logic;
|
||||
RD_n : out std_logic;
|
||||
WR_n : out std_logic;
|
||||
RFSH_n : out std_logic;
|
||||
HALT_n : out std_logic;
|
||||
BUSAK_n : out std_logic;
|
||||
A : out std_logic_vector(15 downto 0);
|
||||
-- D : inout std_logic_vector( 7 downto 0);
|
||||
D_i : in std_logic_vector( 7 downto 0);
|
||||
D_o : out std_logic_vector( 7 downto 0);
|
||||
|
||||
-- extended functions
|
||||
Z80N_dout_o : out std_logic := '0';
|
||||
Z80N_data_o : out std_logic_vector(15 downto 0);
|
||||
Z80N_command_o : out Z80N_seq
|
||||
);
|
||||
end T80Na;
|
||||
|
||||
|
||||
architecture rtl of T80Na is
|
||||
|
||||
signal CEN : std_logic;
|
||||
signal Reset_s : std_logic;
|
||||
signal IntCycle_n : std_logic;
|
||||
signal IORQ : std_logic;
|
||||
signal NoRead : std_logic;
|
||||
signal Write : std_logic;
|
||||
signal MREQ : std_logic;
|
||||
signal MReq_Inhibit : std_logic;
|
||||
signal Req_Inhibit : std_logic;
|
||||
signal RD : std_logic;
|
||||
signal MREQ_n_i : std_logic;
|
||||
signal MREQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add MREQ control
|
||||
signal IORQ_n_i : std_logic;
|
||||
signal IORQ_t1 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control
|
||||
signal IORQ_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control
|
||||
signal IORQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control
|
||||
signal IORQ_int : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ interrupt control
|
||||
signal RD_n_i : std_logic;
|
||||
signal WR_n_i : std_logic;
|
||||
signal WR_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add WR control
|
||||
signal RFSH_n_i : std_logic;
|
||||
signal BUSAK_n_i : std_logic;
|
||||
signal A_i : std_logic_vector(15 downto 0);
|
||||
signal DO : std_logic_vector(7 downto 0);
|
||||
signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser
|
||||
signal MCycle : std_logic_vector(2 downto 0);
|
||||
signal TState : std_logic_vector(2 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
CEN <= '1';
|
||||
|
||||
BUSAK_n <= BUSAK_n_i; -- 30/10/19 Charlie Ingley - IORQ/RD/WR changes
|
||||
MREQ_rw <= MREQ and (Req_Inhibit or MReq_Inhibit); -- added MREQ timing control
|
||||
MREQ_n_i <= not MREQ_rw; -- changed MREQ generation
|
||||
IORQ_rw <= IORQ and not (IORQ_t1 or IORQ_t2); -- added IORQ generation timing control
|
||||
IORQ_n_i <= not (IORQ_int or IORQ_rw); -- changed IORQ generation
|
||||
RD_n_i <= not (RD and (MREQ_rw or IORQ_rw)); -- changed RD/IORQ generation
|
||||
WR_n_i <= not (Write and ((WR_t2 and MREQ_rw) or IORQ_rw)); -- added WR/IORQ timing control
|
||||
|
||||
-- MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z';
|
||||
-- IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z';
|
||||
-- RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z';
|
||||
-- WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z';
|
||||
-- RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z';
|
||||
-- A <= A_i when BUSAK_n_i = '1' else (others => 'Z');
|
||||
-- D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z');
|
||||
|
||||
MREQ_n <= MREQ_n_i;
|
||||
IORQ_n <= IORQ_n_i;
|
||||
RD_n <= RD_n_i;
|
||||
WR_n <= WR_n_i;
|
||||
RFSH_n <= RFSH_n_i;
|
||||
A <= A_i;
|
||||
D_o <= DO;
|
||||
|
||||
process (RESET_n, CLK_n)
|
||||
begin
|
||||
if RESET_n = '0' then
|
||||
Reset_s <= '0';
|
||||
elsif CLK_n'event and CLK_n = '1' then
|
||||
Reset_s <= '1';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
z80n : T80N
|
||||
generic map(
|
||||
Mode => Mode,
|
||||
IOWait => 1)
|
||||
port map(
|
||||
CEN => CEN,
|
||||
M1_n => M1_n,
|
||||
IORQ => IORQ,
|
||||
NoRead => NoRead,
|
||||
Write => Write,
|
||||
RFSH_n => RFSH_n_i,
|
||||
HALT_n => HALT_n,
|
||||
WAIT_n => Wait_n,
|
||||
INT_n => INT_n,
|
||||
NMI_n => NMI_n,
|
||||
RESET_n => Reset_s,
|
||||
BUSRQ_n => BUSRQ_n,
|
||||
BUSAK_n => BUSAK_n_i,
|
||||
CLK_n => CLK_n,
|
||||
A => A_i,
|
||||
-- DInst => D,
|
||||
DInst => D_i,
|
||||
DI => DI_Reg,
|
||||
DO => DO,
|
||||
MC => MCycle,
|
||||
TS => TState,
|
||||
IntCycle_n => IntCycle_n,
|
||||
|
||||
Z80N_dout_o => Z80N_dout_o,
|
||||
Z80N_data_o => Z80N_data_o,
|
||||
Z80N_command_o => Z80N_command_o
|
||||
);
|
||||
|
||||
process (CLK_n)
|
||||
begin
|
||||
if CLK_n'event and CLK_n = '0' then
|
||||
if TState = "011" and BUSAK_n_i = '1' then
|
||||
-- DI_Reg <= to_x01(D);
|
||||
DI_Reg <= D_i;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 30/10/19 Charlie Ingley - Generate WR_t2 to correct MREQ/WR timing
|
||||
process (Reset_s,CLK_n)
|
||||
begin
|
||||
if Reset_s = '0' then
|
||||
WR_t2 <= '0';
|
||||
elsif CLK_n'event and CLK_n = '0' then
|
||||
if MCycle /= "001" then
|
||||
if TState = "010" then -- WR starts on falling edge of T2 for MREQ
|
||||
WR_t2 <= Write;
|
||||
end if;
|
||||
end if;
|
||||
if TState = "011" then -- end WR
|
||||
WR_t2 <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Generate Req_Inhibit
|
||||
process (Reset_s,CLK_n)
|
||||
begin
|
||||
if Reset_s = '0' then
|
||||
Req_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity
|
||||
elsif CLK_n'event and CLK_n = '1' then
|
||||
if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n
|
||||
Req_Inhibit <= '0';
|
||||
else
|
||||
Req_Inhibit <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Generate MReq_Inhibit
|
||||
process (Reset_s, CLK_n)
|
||||
begin
|
||||
if Reset_s = '0' then
|
||||
MReq_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity
|
||||
elsif CLK_n'event and CLK_n = '0' then
|
||||
if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n
|
||||
MReq_Inhibit <= '0';
|
||||
else
|
||||
MReq_Inhibit <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Generate RD for MREQ
|
||||
process(Reset_s,CLK_n)
|
||||
begin
|
||||
if Reset_s = '0' then
|
||||
RD <= '0';
|
||||
MREQ <= '0';
|
||||
elsif CLK_n'event and CLK_n = '0' then
|
||||
if MCycle = "001" then
|
||||
if TState = "001" then
|
||||
RD <= IntCycle_n;
|
||||
MREQ <= IntCycle_n;
|
||||
end if;
|
||||
if TState = "011" then
|
||||
RD <= '0';
|
||||
MREQ <= '1';
|
||||
end if;
|
||||
if TState = "100" then
|
||||
MREQ <= '0';
|
||||
end if;
|
||||
else
|
||||
if TState = "001" and NoRead = '0' then
|
||||
RD <= not Write;
|
||||
MREQ <= not IORQ;
|
||||
end if;
|
||||
if TState = "011" then
|
||||
RD <= '0';
|
||||
MREQ <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 30/10/19 Charlie Ingley - Generate IORQ_int for IORQ interrupt timing control
|
||||
process(Reset_s,CLK_n)
|
||||
begin
|
||||
if Reset_s = '0' then
|
||||
IORQ_int <= '0';
|
||||
elsif CLK_n'event and CLK_n = '1' then
|
||||
if MCycle = "001" then
|
||||
if TState = "001" then
|
||||
IORQ_int <= not IntCycle_n;
|
||||
end if;
|
||||
if TState = "010" then
|
||||
IORQ_int <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 30/10/19 Charlie Ingley - Generate IORQ_t1 for IORQ timing control
|
||||
process(Reset_s, CLK_n)
|
||||
begin
|
||||
if Reset_s = '0' then
|
||||
IORQ_t1 <= '1';
|
||||
elsif CLK_n'event and CLK_n = '0' then
|
||||
if TState = "001" then
|
||||
IORQ_t1 <= not IntCycle_n;
|
||||
end if;
|
||||
if TState = "011" then
|
||||
IORQ_t1 <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 30/10/19 Charlie Ingley - Generate IORQ_t2 for IORQ timing control
|
||||
process (RESET_n, CLK_n)
|
||||
begin
|
||||
if RESET_n = '0' then
|
||||
IORQ_t2 <= '1';
|
||||
elsif CLK_n'event and CLK_n = '1' then
|
||||
IORQ_t2 <= IORQ_t1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end;
|
||||
125
rtl/device/copper.vhd
Normal file
125
rtl/device/copper.vhd
Normal file
@@ -0,0 +1,125 @@
|
||||
|
||||
-- ZX Spectrum Next Copper Coprocessor
|
||||
-- Copyright 2020 Victor Trucco
|
||||
-- Theoretical Model - Mike Dailly
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use IEEE.std_logic_unsigned.ALL;
|
||||
|
||||
entity copper is
|
||||
port (
|
||||
clock_i : in std_logic;
|
||||
reset_i : in std_logic;
|
||||
|
||||
copper_en_i : in std_logic_vector(1 downto 0);
|
||||
|
||||
hcount_i : in unsigned(8 downto 0);
|
||||
vcount_i : in unsigned(8 downto 0);
|
||||
|
||||
copper_list_addr_o : out std_logic_vector(9 downto 0);
|
||||
copper_list_data_i : in std_logic_vector(15 downto 0);
|
||||
|
||||
copper_dout_o : out std_logic;
|
||||
copper_data_o : out std_logic_vector(14 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of copper is
|
||||
|
||||
signal copper_list_addr_s : std_logic_vector(9 downto 0);
|
||||
signal copper_dout_s : std_logic := '0';
|
||||
signal last_state_s : std_logic_vector(1 downto 0) := "00";
|
||||
|
||||
begin
|
||||
|
||||
process (clock_i)
|
||||
variable line_v : unsigned(8 downto 0);
|
||||
begin
|
||||
|
||||
if rising_edge(clock_i) then
|
||||
|
||||
if reset_i = '1' then
|
||||
|
||||
copper_list_addr_s <= (others => '0');
|
||||
|
||||
copper_dout_s <= '0';
|
||||
copper_data_o <= (others => '0');
|
||||
|
||||
else
|
||||
|
||||
-- check if we are entering on "01" or "11" mode and reset the address to 0000
|
||||
if last_state_s /= copper_en_i then
|
||||
|
||||
last_state_s <= copper_en_i;
|
||||
|
||||
if copper_en_i = "01" or copper_en_i = "11" then
|
||||
copper_list_addr_s <= (others=>'0');
|
||||
end if;
|
||||
|
||||
copper_dout_s <= '0';
|
||||
|
||||
elsif copper_en_i = "11" and vcount_i = 0 and hcount_i = 0 then --restart at frame start
|
||||
|
||||
copper_list_addr_s <= (others=>'0');
|
||||
copper_dout_s <= '0';
|
||||
|
||||
elsif copper_en_i /= "00" then
|
||||
|
||||
if copper_dout_s = '1' then --if we are on MOVE, clear the output for the next cycle
|
||||
|
||||
copper_dout_s <= '0';
|
||||
|
||||
-- command WAIT
|
||||
elsif copper_list_data_i(15) = '1' then
|
||||
|
||||
if vcount_i = unsigned(copper_list_data_i(8 downto 0)) and hcount_i >= unsigned(copper_list_data_i(14 downto 9)&"000") + 12 then
|
||||
copper_list_addr_s <= copper_list_addr_s + 1; -- if it's time, load the next copper command
|
||||
end if;
|
||||
|
||||
copper_dout_s <= '0';
|
||||
|
||||
else -- command MOVE
|
||||
|
||||
copper_data_o <= copper_list_data_i(14 downto 0);
|
||||
|
||||
if copper_list_data_i(14 downto 8) /= "0000000" then -- dont generate the write pulse if its a NOP (MOVE 0,0)
|
||||
copper_dout_s <= '1';
|
||||
end if;
|
||||
|
||||
copper_list_addr_s <= copper_list_addr_s + 1;
|
||||
|
||||
end if;
|
||||
|
||||
else
|
||||
|
||||
copper_dout_s <= '0';
|
||||
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
copper_list_addr_o <= copper_list_addr_s;
|
||||
copper_dout_o <= copper_dout_s;
|
||||
|
||||
end architecture;
|
||||
169
rtl/device/ctc.vhd
Normal file
169
rtl/device/ctc.vhd
Normal file
@@ -0,0 +1,169 @@
|
||||
-- Z80 CTC
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Reference:
|
||||
-- http://www.zilog.com/docs/z80/ps0181.pdf
|
||||
--
|
||||
-- The im2 vector and im2 interrupt are not implemented here. Instead
|
||||
-- relevant signals are exported so that im2 mode can be optionally
|
||||
-- implemented by the instantiating module.
|
||||
--
|
||||
-- Clarifications per CTC channel:
|
||||
--
|
||||
-- 1. Hard reset requires a control word to be written with D2 = 1
|
||||
-- (time constant follows) otherwise the channel effectively
|
||||
-- ignores the control word and will remain in the hard reset state.
|
||||
--
|
||||
-- 2. Soft reset is generated when the control word's D1 = 1. if
|
||||
-- D2 = 0, the channel will enter the hard reset state. If D2 = 1
|
||||
-- the channel expects a time constant to be written next and after
|
||||
-- that the counter/timer will run as expected.
|
||||
--
|
||||
-- 3. Changing the trigger edge selection in bit 4 counts as a clock edge.
|
||||
-- A timer waiting for a clock edge to start will start and in counter
|
||||
-- mode, the count will be decremented.
|
||||
--
|
||||
-- 4. ZC/TO is asserted for one clock cycle and not for the entire
|
||||
-- duration that the count is at zero.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity ctc is
|
||||
generic (
|
||||
constant NUM_CTC : positive := 4;
|
||||
constant NUM_CTC_LOG2 : positive := 2
|
||||
);
|
||||
port (
|
||||
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_port_ctc_wr : in std_logic; -- one of the ctc channel ports is being written
|
||||
i_port_ctc_sel : in std_logic_vector(NUM_CTC_LOG2-1 downto 0); -- which one, numbered
|
||||
|
||||
i_int_en_wr : in std_logic; -- separately write interrupt enable bits, must not overlap port_ctc_wr
|
||||
i_int_en : in std_logic_vector(NUM_CTC-1 downto 0); -- interrupt enable bits
|
||||
|
||||
i_cpu_d : in std_logic_vector(7 downto 0);
|
||||
o_cpu_d : out std_logic_vector(7 downto 0); -- data read from ctc port
|
||||
|
||||
i_clk_trg : in std_logic_vector(NUM_CTC-1 downto 0); -- clock/trigger signals for each ctc channel, must be synchronized
|
||||
|
||||
o_im2_vector_wr : out std_logic; -- im2 vector is being written (not handled in this module)
|
||||
|
||||
o_zc_to : out std_logic_vector(NUM_CTC-1 downto 0); -- zc/to for each ctc channel, asserted for one i_CLK cycle
|
||||
o_int_en : out std_logic_vector(NUM_CTC-1 downto 0) -- interrupt enable for each channel
|
||||
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of ctc is
|
||||
|
||||
type dout_t is array (NUM_CTC-1 downto 0) of std_logic_vector(7 downto 0);
|
||||
signal dout : dout_t;
|
||||
|
||||
signal sel : std_logic_vector(NUM_CTC-1 downto 0);
|
||||
|
||||
signal iowr : std_logic_vector(NUM_CTC-1 downto 0);
|
||||
signal iowr_tc : std_logic_vector(NUM_CTC-1 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- CTC Channels
|
||||
|
||||
gen_ctc:
|
||||
for I in 0 to NUM_CTC-1 generate
|
||||
|
||||
ctc: entity work.ctc_chan
|
||||
port map (
|
||||
i_CLK => i_CLK,
|
||||
i_reset => i_reset,
|
||||
|
||||
i_iowr => iowr(I),
|
||||
o_iowr_tc => iowr_tc(I),
|
||||
|
||||
i_int_en_wr => i_int_en_wr,
|
||||
i_int_en => i_int_en(I),
|
||||
|
||||
i_cpu_d => i_cpu_d,
|
||||
o_cpu_d => dout(I),
|
||||
|
||||
i_clk_trg => i_clk_trg(I),
|
||||
|
||||
o_zc_to => o_zc_to(I),
|
||||
o_int_en => o_int_en(I)
|
||||
);
|
||||
|
||||
end generate;
|
||||
|
||||
-- Select CTC
|
||||
|
||||
process (i_port_ctc_sel)
|
||||
begin
|
||||
for I in 0 to NUM_CTC-1 loop
|
||||
if I = unsigned(i_port_ctc_sel) then
|
||||
sel(I) <= '1';
|
||||
else
|
||||
sel(I) <= '0';
|
||||
end if;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
-- Route Signals
|
||||
|
||||
process (i_port_ctc_wr, sel)
|
||||
begin
|
||||
for I in 0 to NUM_CTC-1 loop
|
||||
iowr(I) <= i_port_ctc_wr and sel(I);
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
-- Output
|
||||
|
||||
process (iowr_tc, sel, i_port_ctc_wr, i_cpu_d)
|
||||
variable tmp_iowr_tc : std_logic;
|
||||
begin
|
||||
tmp_iowr_tc := iowr_tc(0) and sel(0);
|
||||
|
||||
for I in 1 to NUM_CTC-1 loop
|
||||
tmp_iowr_tc := tmp_iowr_tc or (iowr_tc(I) and sel(I));
|
||||
end loop;
|
||||
|
||||
o_im2_vector_wr <= i_port_ctc_wr and (not i_cpu_d(0)) and (not tmp_iowr_tc);
|
||||
end process;
|
||||
|
||||
process (dout, sel)
|
||||
variable tmp_dout : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
tmp_dout := (dout(0)(7) and sel(0)) & (dout(0)(6) and sel(0)) & (dout(0)(5) and sel(0)) & (dout(0)(4) and sel(0)) &
|
||||
(dout(0)(3) and sel(0)) & (dout(0)(2) and sel(0)) & (dout(0)(1) and sel(0)) & (dout(0)(0) and sel(0));
|
||||
|
||||
for I in 1 to NUM_CTC-1 loop
|
||||
tmp_dout := tmp_dout or ((dout(I)(7) and sel(I)) & (dout(I)(6) and sel(I)) & (dout(I)(5) and sel(I)) & (dout(I)(4) and sel(I)) &
|
||||
(dout(I)(3) and sel(I)) & (dout(I)(2) and sel(I)) & (dout(I)(1) and sel(I)) & (dout(I)(0) and sel(I)) );
|
||||
end loop;
|
||||
|
||||
o_cpu_d <= tmp_dout;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
267
rtl/device/ctc_chan.vhd
Normal file
267
rtl/device/ctc_chan.vhd
Normal file
@@ -0,0 +1,267 @@
|
||||
-- Z80 CTC Channel
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- One channel of a Z80 CTC (counter/timer circuit)
|
||||
-- http://www.zilog.com/docs/z80/ps0181.pdf
|
||||
--
|
||||
-- Clarifications:
|
||||
--
|
||||
-- 1. Hard reset requires a control word to be written with D2 = 1
|
||||
-- (time constant follows) otherwise the channel effectively
|
||||
-- ignores the control word and will remain in the hard reset state.
|
||||
--
|
||||
-- 2. Soft reset is generated when the control word's D1 = 1. if
|
||||
-- D2 = 0, the channel will enter the hard reset state. If D2 = 1
|
||||
-- the channel expects a time constant to be written next and after
|
||||
-- that the counter/timer will run as expected.
|
||||
--
|
||||
-- 3. Changing the trigger edge selection in bit 4 counts as a clock edge.
|
||||
-- A timer waiting for a clock edge to start will start and in counter
|
||||
-- mode, the count will be decremented.
|
||||
--
|
||||
-- 4. ZC/TO is asserted for one clock cycle and not for the entire
|
||||
-- duration that the count is at zero.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity ctc_chan is
|
||||
port (
|
||||
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic; -- hard reset
|
||||
|
||||
i_iowr : in std_logic; -- write to this channel
|
||||
o_iowr_tc : out std_logic; -- channel expects time constant next (ignore vector write)
|
||||
|
||||
i_int_en_wr : in std_logic; -- separately write interrupt enable, must not overlap iowr
|
||||
i_int_en : in std_logic;
|
||||
|
||||
i_cpu_d : in std_logic_vector(7 downto 0);
|
||||
o_cpu_d : out std_logic_vector(7 downto 0); -- current count
|
||||
|
||||
i_clk_trg : in std_logic; -- external clock / trigger, must be synchronized with rising edge of i_CLK
|
||||
|
||||
o_zc_to : out std_logic; -- asserted for one i_CLK cycle
|
||||
o_int_en : out std_logic -- set if interrupt is enabled
|
||||
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of ctc_chan is
|
||||
|
||||
signal reset_hard : std_logic;
|
||||
signal reset_soft : std_logic;
|
||||
|
||||
signal clk_trg_d : std_logic;
|
||||
signal clk_trg_edge : std_logic;
|
||||
|
||||
signal p_count : std_logic_vector(7 downto 0);
|
||||
signal p_count_lo : std_logic;
|
||||
signal p_count_hi : std_logic;
|
||||
signal prescaler_clk : std_logic;
|
||||
|
||||
signal t_count_en : std_logic;
|
||||
signal t_count_zero : std_logic;
|
||||
signal t_count : std_logic_vector(7 downto 0);
|
||||
signal t_count_zero_d : std_logic;
|
||||
signal zc_to : std_logic;
|
||||
|
||||
type state_t is (S_CONTROL_WORD, S_TIME_CONSTANT, S_WAIT, S_RUNNING);
|
||||
signal state : state_t;
|
||||
signal state_next : state_t;
|
||||
|
||||
signal iowr_d : std_logic;
|
||||
signal iowr : std_logic;
|
||||
signal iowr_tc_exp : std_logic;
|
||||
signal iowr_tc : std_logic;
|
||||
signal iowr_cr : std_logic;
|
||||
signal control_reg : std_logic_vector(5 downto 0);
|
||||
signal time_constant_reg : std_logic_vector(7 downto 0);
|
||||
signal reset_soft_trigger : std_logic;
|
||||
signal clk_edge_change : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
-- RESET
|
||||
|
||||
reset_hard <= i_reset;
|
||||
reset_soft <= '1' when state /= S_RUNNING else '0';
|
||||
|
||||
-- CLOCK / TRIGGER
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
clk_trg_d <= i_clk_trg;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
clk_trg_edge <= ((clk_trg_d and not i_clk_trg) or clk_edge_change) when control_reg(4-2) = '0' else ((i_clk_trg and not clk_trg_d) or clk_edge_change); -- one cycle
|
||||
|
||||
-- PRESCALER
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if reset_soft = '1' then
|
||||
p_count <= (others => '0');
|
||||
else
|
||||
p_count <= p_count + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_count_lo <= '1' when p_count(3 downto 0) = "1111" else '0';
|
||||
p_count_hi <= '1' when p_count(7 downto 4) = "1111" else '0';
|
||||
|
||||
prescaler_clk <= (p_count_lo) when control_reg(5-2) = '0' else (p_count_lo and p_count_hi); -- one cycle
|
||||
|
||||
-- COUNTER
|
||||
|
||||
t_count_en <= prescaler_clk when control_reg(6-2) = '0' else clk_trg_edge;
|
||||
t_count_zero <= '1' when t_count = X"00" else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if reset_soft = '1' then
|
||||
t_count <= time_constant_reg;
|
||||
elsif zc_to = '1' then
|
||||
t_count <= time_constant_reg;
|
||||
elsif t_count_en = '1' then
|
||||
t_count <= t_count - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_cpu_d <= t_count;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
t_count_zero_d <= t_count_zero;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
zc_to <= '1' when t_count_zero = '1' and t_count_zero_d = '0' and state = S_RUNNING else '0'; -- one cycle
|
||||
|
||||
o_zc_to <= zc_to;
|
||||
|
||||
-- STATE MACHINE
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if reset_hard = '1' then
|
||||
state <= S_CONTROL_WORD;
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (reset_soft_trigger, i_cpu_d, state, iowr_cr, iowr_tc, control_reg, clk_trg_edge)
|
||||
begin
|
||||
if reset_soft_trigger = '1' then
|
||||
if i_cpu_d(2) = '0' then
|
||||
state_next <= S_CONTROL_WORD;
|
||||
else
|
||||
state_next <= S_TIME_CONSTANT;
|
||||
end if;
|
||||
else
|
||||
case state is
|
||||
when S_CONTROL_WORD =>
|
||||
if iowr_cr = '1' and i_cpu_d(2) = '1' then
|
||||
state_next <= S_TIME_CONSTANT;
|
||||
else
|
||||
state_next <= S_CONTROL_WORD;
|
||||
end if;
|
||||
when S_TIME_CONSTANT =>
|
||||
if iowr_tc = '1' then
|
||||
state_next <= S_WAIT;
|
||||
else
|
||||
state_next <= S_TIME_CONSTANT;
|
||||
end if;
|
||||
when S_WAIT =>
|
||||
if control_reg(6-2) = '0' and control_reg(3-2) = '1' and clk_trg_edge = '0' then
|
||||
state_next <= S_WAIT;
|
||||
else
|
||||
state_next <= S_RUNNING;
|
||||
end if;
|
||||
when S_RUNNING =>
|
||||
state_next <= S_RUNNING;
|
||||
when others =>
|
||||
state_next <= S_CONTROL_WORD;
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- REGISTERS
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
iowr_d <= i_iowr;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
iowr <= i_iowr and not iowr_d;
|
||||
iowr_tc_exp <= '1' when (control_reg(2-2) = '1' and state /= S_CONTROL_WORD) else '0';
|
||||
|
||||
o_iowr_tc <= iowr_tc_exp;
|
||||
|
||||
iowr_tc <= '1' when iowr = '1' and iowr_tc_exp = '1' else '0';
|
||||
iowr_cr <= '1' when iowr = '1' and iowr_tc_exp = '0' and i_cpu_d(0) = '1' else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if reset_hard = '1' then
|
||||
control_reg <= (others => '0');
|
||||
elsif iowr_cr = '1' then
|
||||
control_reg <= i_cpu_d(7 downto 2);
|
||||
elsif iowr_tc = '1' then
|
||||
control_reg(2-2) <= '0';
|
||||
elsif i_int_en_wr = '1' then
|
||||
control_reg(7-2) <= i_int_en;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_int_en <= control_reg(7-2);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if reset_hard = '1' then
|
||||
time_constant_reg <= (others => '0');
|
||||
elsif iowr_tc = '1' then
|
||||
time_constant_reg <= i_cpu_d;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
reset_soft_trigger <= '1' when iowr_cr = '1' and i_cpu_d(1) = '1' else '0';
|
||||
clk_edge_change <= '1' when iowr_cr = '1' and (i_cpu_d(4) /= control_reg(4-2)) else '0';
|
||||
|
||||
end architecture;
|
||||
150
rtl/device/divmmc.vhd
Normal file
150
rtl/device/divmmc.vhd
Normal file
@@ -0,0 +1,150 @@
|
||||
|
||||
-- ZXN Divmmc
|
||||
-- Copyright 2020 Alvin Albrecht and Fabio Belavenuto
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity divmmc is
|
||||
port (
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_cpu_a_15_13 : in std_logic_vector(2 downto 0);
|
||||
i_cpu_mreq_n : in std_logic;
|
||||
i_cpu_m1_n : in std_logic;
|
||||
|
||||
i_en : in std_logic;
|
||||
i_automap_reset : in std_logic;
|
||||
i_automap_active : in std_logic;
|
||||
i_automap_rom3_active: in std_logic;
|
||||
i_retn_seen : in std_logic;
|
||||
|
||||
i_divmmc_button : in std_logic;
|
||||
i_divmmc_reg : in std_logic_vector(7 downto 0);
|
||||
|
||||
i_automap_instant_on : in std_logic;
|
||||
i_automap_delayed_on : in std_logic;
|
||||
i_automap_delayed_off : in std_logic;
|
||||
i_automap_rom3_instant_on : in std_logic;
|
||||
i_automap_rom3_delayed_on : in std_logic;
|
||||
i_automap_nmi_instant_on : in std_logic;
|
||||
i_automap_nmi_delayed_on : in std_logic;
|
||||
|
||||
o_divmmc_rom_en : out std_logic;
|
||||
o_divmmc_ram_en : out std_logic;
|
||||
o_divmmc_rdonly : out std_logic;
|
||||
o_divmmc_ram_bank : out std_logic_vector(3 downto 0);
|
||||
|
||||
o_disable_nmi : out std_logic;
|
||||
o_automap_held : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of divmmc is
|
||||
|
||||
signal conmem : std_logic;
|
||||
signal mapram : std_logic;
|
||||
signal page0 : std_logic;
|
||||
signal page1 : std_logic;
|
||||
signal rom_en : std_logic;
|
||||
signal ram_en : std_logic;
|
||||
signal ram_bank : std_logic_vector(3 downto 0);
|
||||
|
||||
signal button_nmi : std_logic;
|
||||
|
||||
signal automap_nmi_instant_on : std_logic;
|
||||
signal automap_nmi_delayed_on : std_logic;
|
||||
|
||||
signal automap_hold : std_logic;
|
||||
signal automap_held : std_logic;
|
||||
signal automap : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
-- DIVMMC Paging
|
||||
|
||||
conmem <= i_divmmc_reg(7);
|
||||
mapram <= i_divmmc_reg(6);
|
||||
|
||||
page0 <= '1' when i_cpu_a_15_13 = "000" else '0';
|
||||
page1 <= '1' when i_cpu_a_15_13 = "001" else '0';
|
||||
|
||||
rom_en <= '1' when (page0 = '1' and (conmem = '1' or (mapram = '0' and automap = '1'))) else '0';
|
||||
ram_en <= '1' when (page0 = '1' and conmem = '0' and mapram = '1' and automap = '1') or (page1 = '1' and (conmem = '1' or automap = '1')) else '0';
|
||||
ram_bank <= X"3" when page0 = '1' else i_divmmc_reg(3 downto 0);
|
||||
|
||||
o_divmmc_rom_en <= rom_en and i_en;
|
||||
o_divmmc_ram_en <= ram_en and i_en;
|
||||
o_divmmc_rdonly <= page0;
|
||||
o_divmmc_ram_bank <= ram_bank;
|
||||
|
||||
-- NMI
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or i_automap_reset = '1' or i_retn_seen = '1' then
|
||||
button_nmi <= '0';
|
||||
elsif i_divmmc_button = '1' then
|
||||
button_nmi <= '1';
|
||||
elsif automap_held = '1' then
|
||||
button_nmi <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Automap
|
||||
|
||||
automap_nmi_instant_on <= i_automap_nmi_instant_on and button_nmi;
|
||||
automap_nmi_delayed_on <= i_automap_nmi_delayed_on and button_nmi;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or i_automap_reset = '1' or i_retn_seen = '1' then
|
||||
automap_hold <= '0';
|
||||
elsif i_cpu_mreq_n = '0' and i_cpu_m1_n = '0' then
|
||||
automap_hold <= (i_automap_active and (i_automap_instant_on or i_automap_delayed_on or automap_nmi_instant_on or automap_nmi_delayed_on)) or
|
||||
(i_automap_rom3_active and (i_automap_rom3_instant_on or i_automap_rom3_delayed_on)) or
|
||||
(automap_held and not (i_automap_active and i_automap_delayed_off));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or i_automap_reset = '1' or i_retn_seen = '1' then
|
||||
automap_held <= '0';
|
||||
elsif i_cpu_mreq_n = '1' then
|
||||
automap_held <= automap_hold;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- automap <= (not i_automap_reset) and (automap_held or (i_automap_active and (i_automap_instant_on or automap_nmi_instant_on) and not i_cpu_m1_n) or (i_automap_rom3_active and i_automap_rom3_instant_on and not i_cpu_m1_n));
|
||||
automap <= (not i_automap_reset) and (automap_held or (i_automap_active and (i_automap_instant_on or automap_nmi_instant_on)) or (i_automap_rom3_active and i_automap_rom3_instant_on));
|
||||
|
||||
o_disable_nmi <= automap or button_nmi;
|
||||
o_automap_held <= automap_held;
|
||||
|
||||
end architecture;
|
||||
1148
rtl/device/dma.vhd
Normal file
1148
rtl/device/dma.vhd
Normal file
File diff suppressed because it is too large
Load Diff
206
rtl/device/im2_control.vhd
Normal file
206
rtl/device/im2_control.vhd
Normal file
@@ -0,0 +1,206 @@
|
||||
-- Z80 IM2 CONTROL BLOCK
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
--
|
||||
-- This control block is responsible for recognizing the reti instruction
|
||||
-- (opcode bytes ED 4D only, which is compatible with Zilog peripherals) and
|
||||
-- for indicating when a reti instruction may be decoded so that IEO is
|
||||
-- only asserted by already acknowledged interrupters. It also decodes the
|
||||
-- retn instruction ED 45.
|
||||
--
|
||||
-- IM2 peripherals should use the output signals as follows:
|
||||
--
|
||||
-- o_reti_decode : When asserted, peripherals must only make IEO low
|
||||
-- if the peripheral's interrupt has already been acknowledged or if
|
||||
-- IEI is low. Synchronized to the rising edge of CLK.
|
||||
--
|
||||
-- o_reti_seen : When asserted, the peripheral with its IEI signal high
|
||||
-- and whose interrupt has already been acknowledged should reset its
|
||||
-- interrupt logic since its interrupt routine is terminating. Asserted
|
||||
-- for exactly one cycle and synchronized to the rising edge of CLK.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity im2_control is
|
||||
port (
|
||||
i_CLK_CPU : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_m1_n : in std_logic;
|
||||
i_mreq_n : in std_logic;
|
||||
i_iorq_n : in std_logic;
|
||||
|
||||
i_rd_n : in std_logic;
|
||||
i_wr_n : in std_logic;
|
||||
|
||||
i_cpu_d : in std_logic_vector(7 downto 0);
|
||||
|
||||
o_reti_decode : out std_logic; -- reti is being decoded, only acknowledged interrupters should deassert IEO
|
||||
o_reti_seen : out std_logic; -- reti instruction has been detected active in T3 for rising edge of T4
|
||||
|
||||
o_retn_seen : out std_logic; -- retn instruction has been detected active in T3 for rising edge of T4
|
||||
|
||||
o_dma_delay : out std_logic -- delay dma busak through reti pop
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of im2_control is
|
||||
|
||||
signal ifetch : std_logic;
|
||||
signal ifetch_cancel : std_logic;
|
||||
signal ifetch_d : std_logic;
|
||||
signal ifetch_fe_t3 : std_logic;
|
||||
|
||||
signal cpu_opcode : std_logic_vector(7 downto 0);
|
||||
|
||||
signal opcode_ed : std_logic;
|
||||
signal opcode_4d : std_logic;
|
||||
signal opcode_cb : std_logic;
|
||||
signal opcode_45 : std_logic;
|
||||
|
||||
type state_t is (S_0, S_ED_T4, S_ED4D_T4, S_ED45_T4, S_CB_T4, S_SRL_T1, S_SRL_T2);
|
||||
signal state : state_t;
|
||||
signal state_next : state_t;
|
||||
|
||||
begin
|
||||
|
||||
-- detect instruction fetch cycles
|
||||
|
||||
ifetch <= '1' when i_m1_n = '0' and i_mreq_n = '0' else '0';
|
||||
-- ifetch_cancel <= '1' when (i_m1_n = '1' and i_mreq_n = '0' and i_rfsh_n = '1') or i_iorq_n = '0' else '0'; -- includes dma operations
|
||||
ifetch_cancel <= '1' when ((i_m1_n = '1' or i_mreq_n = '1') and (i_rd_n = '0' or i_wr_n = '0')) or i_iorq_n = '0' else '0';
|
||||
|
||||
process (i_CLK_CPU)
|
||||
begin
|
||||
if rising_edge(i_CLK_CPU) then
|
||||
if i_reset = '1' then
|
||||
ifetch_d <= '0';
|
||||
else
|
||||
ifetch_d <= ifetch;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
ifetch_fe_t3 <= ifetch_d and not ifetch;
|
||||
|
||||
-- hold opcode read by cpu
|
||||
|
||||
process (i_CLK_CPU)
|
||||
begin
|
||||
if rising_edge(i_CLK_CPU) then
|
||||
if i_reset = '1' then
|
||||
cpu_opcode <= (others => '0');
|
||||
elsif ifetch = '1' then
|
||||
cpu_opcode <= i_cpu_d;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- recognize important opcodes ED 4D CB 45
|
||||
|
||||
process (cpu_opcode)
|
||||
begin
|
||||
|
||||
opcode_ed <= '0';
|
||||
opcode_4d <= '0';
|
||||
opcode_cb <= '0';
|
||||
opcode_45 <= '0';
|
||||
|
||||
case cpu_opcode is
|
||||
when X"ED" => opcode_ed <= '1';
|
||||
when X"4D" => opcode_4d <= '1';
|
||||
when X"CB" => opcode_cb <= '1';
|
||||
when X"45" => opcode_45 <= '1';
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
-- state machine
|
||||
|
||||
process (i_CLK_CPU)
|
||||
begin
|
||||
if rising_edge(i_CLK_CPU) then
|
||||
if i_reset = '1' then
|
||||
state <= S_0;
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (state, ifetch_fe_t3, opcode_ed, opcode_cb, opcode_4d, opcode_45, ifetch_cancel) -- , i_busak_n)
|
||||
begin
|
||||
case state is
|
||||
when S_0 =>
|
||||
if ifetch_fe_t3 = '1' and opcode_ed = '1' then
|
||||
state_next <= S_ED_T4;
|
||||
elsif ifetch_fe_t3 = '1' and opcode_cb = '1' then
|
||||
state_next <= S_CB_T4;
|
||||
else
|
||||
state_next <= S_0;
|
||||
end if;
|
||||
when S_ED_T4 =>
|
||||
if ifetch_cancel = '1' or (ifetch_fe_t3 = '1' and opcode_4d = '0' and opcode_45 = '0') then
|
||||
state_next <= S_0;
|
||||
elsif ifetch_fe_t3 = '1' and opcode_4d = '1' then
|
||||
state_next <= S_ED4D_T4;
|
||||
elsif ifetch_fe_t3 = '1' and opcode_45 = '1' then
|
||||
state_next <= S_ED45_T4;
|
||||
else
|
||||
state_next <= S_ED_T4;
|
||||
end if;
|
||||
when S_ED4D_T4 =>
|
||||
-- state_next <= S_0;
|
||||
state_next <= S_SRL_T1;
|
||||
-- On the zx next, the dma can be interrupted by devices and this
|
||||
-- prevents an accumulation of return addresses on the stack.
|
||||
when S_SRL_T1 =>
|
||||
state_next <= S_SRL_T2;
|
||||
when S_SRL_T2 =>
|
||||
state_next <= S_0;
|
||||
--
|
||||
when S_ED45_T4 =>
|
||||
state_next <= S_0;
|
||||
when S_CB_T4 =>
|
||||
if ifetch_cancel = '1' or ifetch_fe_t3 = '1' then
|
||||
state_next <= S_0;
|
||||
else
|
||||
state_next <= S_CB_T4;
|
||||
end if;
|
||||
when others =>
|
||||
state_next <= S_0;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- output signals
|
||||
|
||||
o_reti_decode <= '1' when state = S_ED_T4 else '0';
|
||||
o_reti_seen <= '1' when state_next = S_ED4D_T4 else '0'; -- zilog peripherals require im2 reset on rising edge of T4
|
||||
|
||||
o_retn_seen <= '1' when state_next = S_ED45_T4 else '0';
|
||||
|
||||
o_dma_delay <= '1' when state = S_ED_T4 or state = S_ED4D_T4 or state = S_SRL_T1 or state = S_SRL_T2 else '0';
|
||||
|
||||
end architecture;
|
||||
164
rtl/device/im2_device.vhd
Normal file
164
rtl/device/im2_device.vhd
Normal file
@@ -0,0 +1,164 @@
|
||||
-- Z80 IM2 DEVICE
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
--
|
||||
-- This module handles the im2 logic for an interrupting peripheral.
|
||||
--
|
||||
-- The input is (i_int) which is active high and indicates that the
|
||||
-- peripheral wants to interrupt. The signal will be seen on the
|
||||
-- rising edge of the cpu clock and could be held high until the module
|
||||
-- indicates that the isr has been serviced (o_isr_serviced).
|
||||
--
|
||||
-- The daisy chain logic is implemented through (i_iei) and (o_ieo).
|
||||
-- The highest priority device should have its iei signal set to '1'
|
||||
-- and lower priority devices should have their iei connected to the
|
||||
-- next higher priority device's ieo.
|
||||
--
|
||||
-- The variable width interrupt vector is output normally as all zeroes
|
||||
-- unless the device must output its vector during an interrupt ack
|
||||
-- cycle. This allows multiple modules to have their vector outputs
|
||||
-- logically ORed together to easily form the correct vector
|
||||
-- presented to the z80. This resulting vector should be output only
|
||||
-- while /m1 and /iorq are both low.
|
||||
--
|
||||
-- The signal (o_isr_serviced) should be used to reset any other
|
||||
-- interrupt logic outside this module. The signal is held high for
|
||||
-- one clock cycle.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity im2_device is
|
||||
generic (
|
||||
constant VEC_BITS : positive := 8
|
||||
);
|
||||
port (
|
||||
i_CLK_CPU : in std_logic;
|
||||
i_reset_n : in std_logic;
|
||||
|
||||
i_m1_n : in std_logic;
|
||||
i_iorq_n : in std_logic;
|
||||
|
||||
i_int_req : in std_logic; -- peripheral wants to generate an interrupt
|
||||
o_int_n : out std_logic; -- interrupt signal for z80
|
||||
|
||||
i_reti_decode : in std_logic;
|
||||
i_reti_seen : in std_logic;
|
||||
o_isr_serviced : out std_logic;
|
||||
|
||||
i_iei : in std_logic; -- im2 daisy chain logic
|
||||
o_ieo : out std_logic; -- im2 daisy chain logic
|
||||
|
||||
i_vec : in std_logic_vector(VEC_BITS-1 downto 0); -- peripheral im2 vector
|
||||
o_vec : out std_logic_vector(VEC_BITS-1 downto 0) -- generated im2 vector, must be qualified by /m1 * /iorq
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of im2_device is
|
||||
|
||||
type state_t is (S_0, S_PEND, S_REQ, S_ACK, S_ISR);
|
||||
signal state : state_t;
|
||||
signal state_next : state_t;
|
||||
|
||||
begin
|
||||
|
||||
-- state machine
|
||||
|
||||
process (i_CLK_CPU)
|
||||
begin
|
||||
if rising_edge(i_CLK_CPU) then
|
||||
if i_reset_n = '0' then
|
||||
state <= S_0;
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (state, i_m1_n, i_iorq_n, i_int_req, i_iei, i_reti_seen)
|
||||
begin
|
||||
case state is
|
||||
when S_0 =>
|
||||
if i_m1_n = '1' and i_int_req = '1' then
|
||||
state_next <= S_REQ;
|
||||
elsif i_int_req = '1' then
|
||||
state_next <= S_PEND;
|
||||
else
|
||||
state_next <= S_0;
|
||||
end if;
|
||||
when S_PEND =>
|
||||
if i_m1_n = '1' then
|
||||
state_next <= S_REQ;
|
||||
else
|
||||
state_next <= S_PEND;
|
||||
end if;
|
||||
when S_REQ =>
|
||||
if i_m1_n = '0' and i_iorq_n = '0' and i_iei = '1' then
|
||||
state_next <= S_ACK;
|
||||
else
|
||||
state_next <= S_REQ;
|
||||
end if;
|
||||
when S_ACK =>
|
||||
if i_m1_n = '1' then
|
||||
state_next <= S_ISR;
|
||||
else
|
||||
state_next <= S_ACK;
|
||||
end if;
|
||||
when S_ISR =>
|
||||
if i_reti_seen = '1' and i_iei = '1' then
|
||||
state_next <= S_0;
|
||||
else
|
||||
state_next <= S_ISR;
|
||||
end if;
|
||||
when others =>
|
||||
state_next <= S_0;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- output daisy chain
|
||||
|
||||
process (state, i_iei, i_reti_decode)
|
||||
begin
|
||||
case state is
|
||||
when S_0 | S_PEND =>
|
||||
o_ieo <= i_iei;
|
||||
when S_REQ =>
|
||||
o_ieo <= i_iei and i_reti_decode;
|
||||
when others =>
|
||||
o_ieo <= '0';
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- output z80 interrupt request
|
||||
|
||||
o_int_n <= '0' when state = S_REQ and i_iei = '1' else '1';
|
||||
|
||||
-- output interrupt vector
|
||||
|
||||
o_vec <= i_vec when state = S_ACK or state_next = S_ACK else (others => '0'); -- qualify with /m1 * /iorq
|
||||
|
||||
-- indicate isr was serviced
|
||||
|
||||
o_isr_serviced <= '1' when state = S_ISR and state_next = S_0 else '0';
|
||||
|
||||
end architecture;
|
||||
153
rtl/device/im2_peripheral.vhd
Normal file
153
rtl/device/im2_peripheral.vhd
Normal file
@@ -0,0 +1,153 @@
|
||||
-- Z80 IM2 DEVICE
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
--
|
||||
-- This module completely handles interrupt logic for zxn peripherals.
|
||||
-- It also implements "pulsed" interrupt logic so is somewhat specific
|
||||
-- to the zx spectrum architecture.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity im2_peripheral is
|
||||
generic (
|
||||
constant VEC_BITS : positive := 4
|
||||
);
|
||||
port (
|
||||
i_CLK_28 : in std_logic;
|
||||
i_CLK_CPU : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_m1_n : in std_logic;
|
||||
i_iorq_n : in std_logic;
|
||||
|
||||
i_mode_pulse_0_im2_1 : in std_logic; -- select standard pulsed zx mode or im2 vector mode
|
||||
|
||||
i_iei : in std_logic; -- im2 daisy chain
|
||||
o_ieo : out std_logic; -- im2 daisy chain
|
||||
|
||||
i_reti_decode : in std_logic; -- reti opcode decode in progress
|
||||
i_reti_seen : in std_logic; -- reti opcode found
|
||||
|
||||
i_int_en : in std_logic; -- enable interrupts from this device
|
||||
i_int_req : in std_logic; -- interrupt request from this device (level active, must not persist through im2_isr_serviced signal)
|
||||
|
||||
i_int_status_clear : in std_logic; -- clear interrupt status bit if 1 (i_CLK_28)
|
||||
o_int_status : out std_logic; -- current state of interrupt status bit (i_CLK_28)
|
||||
|
||||
o_int_n : out std_logic; -- active low interrupt signal to z80 if in im2 mode
|
||||
o_pulse_en : out std_logic; -- active high signal for pulse interrupt, same duration as i_int_req (active regardless of pulse/im2 mode)
|
||||
|
||||
i_vector : in std_logic_vector(VEC_BITS-1 downto 0);
|
||||
o_vector : out std_logic_vector(VEC_BITS-1 downto 0);
|
||||
|
||||
i_dma_int_en : in std_logic;
|
||||
o_dma_int : out std_logic -- set if dma operation should be interrupted, must qualify with im2 mode
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of im2_peripheral is
|
||||
|
||||
signal im2_reset_n : std_logic;
|
||||
|
||||
signal isr_serviced : std_logic;
|
||||
signal isr_serviced_d : std_logic;
|
||||
signal im2_isr_serviced : std_logic;
|
||||
|
||||
signal int_status : std_logic;
|
||||
signal next_int_status : std_logic;
|
||||
|
||||
signal im2_int_req : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
im2_reset_n <= i_mode_pulse_0_im2_1 and i_int_en and not i_reset;
|
||||
|
||||
-- im2 device logic
|
||||
|
||||
im2_logic: entity work.im2_device
|
||||
generic map (
|
||||
VEC_BITS => VEC_BITS
|
||||
)
|
||||
port map (
|
||||
i_CLK_CPU => i_CLK_CPU,
|
||||
i_reset_n => im2_reset_n,
|
||||
|
||||
i_m1_n => i_m1_n,
|
||||
i_iorq_n => i_iorq_n,
|
||||
|
||||
i_int_req => im2_int_req,
|
||||
o_int_n => o_int_n,
|
||||
|
||||
i_reti_decode => i_reti_decode,
|
||||
i_reti_seen => i_reti_seen,
|
||||
o_isr_serviced => isr_serviced,
|
||||
|
||||
i_iei => i_iei,
|
||||
o_ieo => o_ieo,
|
||||
|
||||
i_vec => i_vector,
|
||||
o_vec => o_vector
|
||||
);
|
||||
|
||||
process (i_CLK_28)
|
||||
begin
|
||||
if rising_edge(i_CLK_28) then
|
||||
if i_reset = '1' then
|
||||
isr_serviced_d <= '0';
|
||||
else
|
||||
isr_serviced_d <= isr_serviced;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
im2_isr_serviced <= isr_serviced and not isr_serviced_d;
|
||||
|
||||
-- interrupt status register
|
||||
-- record of whether interrupt occurred, only cleared by write or im2 reset
|
||||
|
||||
next_int_status <= i_int_req or (int_status and (im2_reset_n or not i_int_status_clear) and (not im2_isr_serviced));
|
||||
|
||||
process (i_CLK_28)
|
||||
begin
|
||||
if rising_edge(i_CLK_28) then
|
||||
if i_reset = '1' then
|
||||
int_status <= '0';
|
||||
else
|
||||
int_status <= next_int_status;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_int_status <= int_status;
|
||||
|
||||
-- im2 interrupt logic
|
||||
|
||||
im2_int_req <= int_status; -- im2 device is held in reset if interrupt is not enabled
|
||||
o_dma_int <= int_status and i_int_en and i_dma_int_en; -- should be qualified by im2 mode
|
||||
|
||||
-- pulse interrupt logic
|
||||
|
||||
o_pulse_en <= i_int_req and i_int_en;
|
||||
|
||||
end architecture;
|
||||
197
rtl/device/multiface.vhd
Normal file
197
rtl/device/multiface.vhd
Normal file
@@ -0,0 +1,197 @@
|
||||
|
||||
-- ZXN Multiface
|
||||
-- Copyright 2020 Victor Trucco, Fabio Belavenuto and Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Multiface 1 schematics:
|
||||
-- http://www.worldofspectrum.org/pub/sinclair/technical-docs/Multiface1_Schematics.png
|
||||
-- https://worldofspectrum.net/pub/sinclair/technical-docs/Multiface1_Schematics.gif
|
||||
--
|
||||
-- Port write 1F,9F: NMI_ACTIVE off
|
||||
-- Port read 1F: MF_ENABLE off
|
||||
-- Port read 9F: MF_ENABLE on
|
||||
-- NMI_ACTIVE: 0=on holds /nmi low and prevents further button activations
|
||||
-- MF_ENABLE: 0=on asserts /romcs and pages in multiface memory
|
||||
-- 0x66 instruction fetch: immediate MF_ENABLE on if NMI_ACTIVE on
|
||||
-- NMI_ACTIVE off and button press: NMI_ACTIVE on
|
||||
|
||||
-- Multiface 128 schematics:
|
||||
-- http://projectspeccy.com/wp-content/uploads/2017/09/Spectrum_Multiface_128_v1.00-1.jpg
|
||||
|
||||
-- Multiface 3:
|
||||
--
|
||||
-- Port write BF,3F: NMI_ACTIVE off
|
||||
-- Port write BF: INVISIBLE on
|
||||
-- Port read BF: MF_ENABLE off
|
||||
-- Port read 3F: if INVISIBLE off, MF_ENABLE on else MF_ENABLE off
|
||||
-- Port read 1F3F: if INVISIBLE off, return port 1ffd
|
||||
-- Port read 7F3F: if INVISIBLE off, return port 7ffd
|
||||
-- NMI_ACTIVE: 0=on holds /nmi low and prevents further button activations
|
||||
-- MF_ENABLE: 0=on asserts /romcs and pages in multiface memory
|
||||
-- 0x66 instruction fetch: immediate MF_ENABLE on if NMI_ACTIVE on
|
||||
-- NMI_ACTIVE off and button press: INVISIBLE off, NMI_ACTIVE on
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity multiface is
|
||||
port (
|
||||
reset_i : in std_logic;
|
||||
clock_i : in std_logic;
|
||||
|
||||
cpu_a_0066_i : in std_logic;
|
||||
|
||||
cpu_mreq_n_i : in std_logic;
|
||||
cpu_m1_n_i : in std_logic;
|
||||
cpu_retn_seen_i : in std_logic;
|
||||
|
||||
enable_i : in std_logic;
|
||||
button_i : in std_logic;
|
||||
|
||||
mf_mode_i : in std_logic_vector(1 downto 0); -- 00 = mf +3, 11 = mf 48, else mf 128
|
||||
|
||||
port_mf_enable_rd_i : in std_logic;
|
||||
port_mf_enable_wr_i : in std_logic;
|
||||
port_mf_disable_rd_i : in std_logic;
|
||||
port_mf_disable_wr_i : in std_logic;
|
||||
|
||||
nmi_disable_o : out std_logic;
|
||||
mf_enabled_o : out std_logic;
|
||||
|
||||
mf_port_en_o : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of multiface is
|
||||
|
||||
signal reset : std_logic;
|
||||
|
||||
signal mode_48 : std_logic;
|
||||
signal mode_128 : std_logic;
|
||||
signal mode_p3 : std_logic;
|
||||
|
||||
signal port_io_dly : std_logic;
|
||||
|
||||
signal button_pulse : std_logic;
|
||||
signal nmi_active : std_logic;
|
||||
|
||||
signal invisible : std_logic;
|
||||
signal invisible_eff : std_logic;
|
||||
|
||||
signal fetch_66 : std_logic;
|
||||
signal mf_enable : std_logic;
|
||||
signal mf_enable_eff : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
reset <= reset_i or not enable_i;
|
||||
|
||||
process (mf_mode_i)
|
||||
begin
|
||||
|
||||
mode_48 <= '0';
|
||||
mode_128 <= '0';
|
||||
mode_p3 <= '0';
|
||||
|
||||
case mf_mode_i is
|
||||
when "00" => mode_p3 <= '1';
|
||||
when "11" => mode_48 <= '1';
|
||||
when others => mode_128 <= '1';
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
-- edge detection on port io
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset = '1' then
|
||||
port_io_dly <= '0';
|
||||
else
|
||||
port_io_dly <= port_mf_enable_rd_i or port_mf_enable_wr_i or port_mf_disable_rd_i or port_mf_disable_wr_i;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- nmi_active (1 = nmi asserted)
|
||||
|
||||
button_pulse <= button_i and not nmi_active;
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset = '1' then
|
||||
nmi_active <= '0';
|
||||
elsif button_pulse = '1' then
|
||||
nmi_active <= '1';
|
||||
elsif cpu_retn_seen_i = '1' or ((port_mf_enable_wr_i = '1' or port_mf_disable_wr_i = '1' or (port_mf_disable_rd_i = '1' and mode_p3 = '1')) and port_io_dly = '0') then
|
||||
nmi_active <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- invisible (1 = invisible)
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset = '1' then
|
||||
invisible <= '1';
|
||||
elsif button_pulse = '1' then
|
||||
invisible <= '0';
|
||||
elsif ((port_mf_disable_wr_i = '1' and mode_p3 = '0') or (port_mf_enable_wr_i = '1' and mode_p3 = '1')) and port_io_dly = '0' then
|
||||
invisible <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
invisible_eff <= invisible and not mode_48;
|
||||
|
||||
-- mf_enable (1 = memory paged in)
|
||||
|
||||
fetch_66 <= '1' when cpu_a_0066_i = '1' and cpu_m1_n_i = '0' and nmi_active = '1' else '0';
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset = '1' then
|
||||
mf_enable <= '0';
|
||||
elsif fetch_66 = '1' and cpu_mreq_n_i = '0' then
|
||||
mf_enable <= '1';
|
||||
elsif port_mf_disable_rd_i = '1' or cpu_retn_seen_i = '1' then
|
||||
mf_enable <= '0';
|
||||
elsif port_mf_enable_rd_i = '1' then
|
||||
mf_enable <= not invisible_eff;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
mf_enable_eff <= mf_enable or fetch_66;
|
||||
|
||||
-- multiface memory
|
||||
|
||||
mf_enabled_o <= mf_enable_eff;
|
||||
nmi_disable_o <= nmi_active;
|
||||
|
||||
-- port read
|
||||
|
||||
mf_port_en_o <= '1' when port_mf_enable_rd_i = '1' and invisible_eff = '0' and (mode_128 = '1' or mode_p3 = '1') else '0';
|
||||
|
||||
end architecture;
|
||||
180
rtl/device/peripherals.vhd
Normal file
180
rtl/device/peripherals.vhd
Normal file
@@ -0,0 +1,180 @@
|
||||
-- INTERRUPTING PERIPHERALS
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
--
|
||||
-- Instantiate interrupt handling for all peripherals.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity peripherals is
|
||||
generic (
|
||||
constant NUM_PERIPH : positive := 14;
|
||||
constant VEC_BITS : positive := 4
|
||||
);
|
||||
port (
|
||||
i_CLK_28 : in std_logic;
|
||||
i_CLK_CPU : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_m1_n : in std_logic;
|
||||
i_iorq_n : in std_logic;
|
||||
|
||||
i_mode_pulse_0_im2_1 : in std_logic;
|
||||
|
||||
i_int_req : in std_logic_vector(NUM_PERIPH downto 1);
|
||||
i_int_en : in std_logic_vector(NUM_PERIPH downto 1);
|
||||
|
||||
o_int_status : out std_logic_vector(NUM_PERIPH downto 1);
|
||||
i_int_status_clear : in std_logic_vector(NUM_PERIPH downto 1);
|
||||
|
||||
i_iei : in std_logic;
|
||||
o_ieo : out std_logic;
|
||||
|
||||
i_reti_decode : in std_logic;
|
||||
i_reti_seen : in std_logic;
|
||||
|
||||
o_int_n : out std_logic;
|
||||
o_vector : out std_logic_vector(VEC_BITS-1 downto 0);
|
||||
|
||||
i_dma_int_en : in std_logic_vector(NUM_PERIPH downto 1);
|
||||
o_dma_int : out std_logic;
|
||||
|
||||
o_pulse_en : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of peripherals is
|
||||
|
||||
type vector_t is array (NUM_PERIPH downto 1) of std_logic_vector(VEC_BITS-1 downto 0);
|
||||
signal vec : vector_t;
|
||||
|
||||
signal ie : std_logic_vector(NUM_PERIPH downto 0);
|
||||
signal int_n : std_logic_vector(NUM_PERIPH downto 1);
|
||||
signal pulse_en : std_logic_vector(NUM_PERIPH downto 1);
|
||||
signal dma_int : std_logic_vector(NUM_PERIPH downto 1);
|
||||
|
||||
begin
|
||||
|
||||
ie(0) <= i_iei;
|
||||
|
||||
-- instantiate interrupt handler for each device
|
||||
|
||||
gen_per:
|
||||
for I in 1 to NUM_PERIPH generate
|
||||
|
||||
peripheral: entity work.im2_peripheral
|
||||
generic map (
|
||||
VEC_BITS => VEC_BITS
|
||||
)
|
||||
port map (
|
||||
i_CLK_28 => i_CLK_28,
|
||||
i_CLK_CPU => i_CLK_CPU,
|
||||
i_reset => i_reset,
|
||||
|
||||
i_m1_n => i_m1_n,
|
||||
i_iorq_n => i_iorq_n,
|
||||
|
||||
i_mode_pulse_0_im2_1 => i_mode_pulse_0_im2_1,
|
||||
|
||||
i_iei => ie(I-1),
|
||||
o_ieo => ie(I),
|
||||
|
||||
i_reti_decode => i_reti_decode,
|
||||
i_reti_seen => i_reti_seen,
|
||||
|
||||
i_int_en => i_int_en(I),
|
||||
i_int_req => i_int_req(I),
|
||||
|
||||
i_int_status_clear => i_int_status_clear(I),
|
||||
o_int_status => o_int_status(I),
|
||||
|
||||
o_int_n => int_n(I),
|
||||
o_pulse_en => pulse_en(I),
|
||||
|
||||
i_vector => std_logic_vector(to_unsigned(I-1,VEC_BITS)),
|
||||
o_vector => vec(I),
|
||||
|
||||
i_dma_int_en => i_dma_int_en(I),
|
||||
o_dma_int => dma_int(I)
|
||||
);
|
||||
|
||||
end generate;
|
||||
|
||||
-- im2 signals
|
||||
|
||||
o_ieo <= ie(NUM_PERIPH);
|
||||
|
||||
process (vec)
|
||||
variable tmp_vec : std_logic_vector(VEC_BITS-1 downto 0);
|
||||
begin
|
||||
tmp_vec := vec(1);
|
||||
|
||||
for I in 2 to NUM_PERIPH loop
|
||||
tmp_vec := tmp_vec or vec(I);
|
||||
end loop;
|
||||
|
||||
o_vector <= tmp_vec;
|
||||
end process;
|
||||
|
||||
process (int_n)
|
||||
variable tmp_int_n : std_logic;
|
||||
begin
|
||||
tmp_int_n := int_n(1);
|
||||
|
||||
for I in 2 to NUM_PERIPH loop
|
||||
tmp_int_n := tmp_int_n and int_n(I);
|
||||
end loop;
|
||||
|
||||
o_int_n <= tmp_int_n;
|
||||
end process;
|
||||
|
||||
-- pulse mode
|
||||
|
||||
process (pulse_en)
|
||||
variable tmp_pulse_en : std_logic;
|
||||
begin
|
||||
tmp_pulse_en := pulse_en(1);
|
||||
|
||||
for I in 2 to NUM_PERIPH loop
|
||||
tmp_pulse_en := tmp_pulse_en or pulse_en(I);
|
||||
end loop;
|
||||
|
||||
o_pulse_en <= tmp_pulse_en; -- and not i_mode_pulse_0_im2_1;
|
||||
end process;
|
||||
|
||||
-- interrupt dma operation
|
||||
|
||||
process (dma_int)
|
||||
variable tmp_dma_int : std_logic;
|
||||
begin
|
||||
tmp_dma_int := dma_int(1);
|
||||
|
||||
for I in 2 to NUM_PERIPH loop
|
||||
tmp_dma_int := tmp_dma_int or dma_int(I);
|
||||
end loop;
|
||||
|
||||
o_dma_int <= tmp_dma_int; -- and i_mode_pulse_0_im2_1;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
188
rtl/input/keyboard/keymaps.vhd
Normal file
188
rtl/input/keyboard/keymaps.vhd
Normal file
@@ -0,0 +1,188 @@
|
||||
|
||||
-- PS2 Keymap
|
||||
-- Copyright 2020 Fabio Belavenuto
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity keymaps is
|
||||
port (
|
||||
clock_i : in std_logic;
|
||||
addr_wr_i : in std_logic_vector(8 downto 0);
|
||||
data_i : in std_logic_vector(8 downto 0);
|
||||
we_i : in std_logic;
|
||||
addr_rd_i : in std_logic_vector(8 downto 0);
|
||||
data_o : out std_logic_vector(8 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture Behavior of keymaps is
|
||||
|
||||
-- Speccy keymaps
|
||||
-- col 0 1 2 3 4 5 6
|
||||
-- row ------------------------------------------
|
||||
-- 0 | CAPS Z X C V EXTEND UP
|
||||
-- 1 | A S D F G CAPS LOCK GRAPH
|
||||
-- 2 | Q W E R T TRUE VID INV VID
|
||||
-- 3 | 1 2 3 4 5 BREAK EDIT
|
||||
-- 4 | 0 9 8 7 6 ; "
|
||||
-- 5 | P O I U Y , .
|
||||
-- 6 | RET L K J H DELETE RIGHT
|
||||
-- 7 | SPC SYM M N B LEFT DOWN
|
||||
|
||||
type ram_t is array (0 to 511) of std_logic_vector(8 downto 0);
|
||||
-- keycode set 2 us keyboard
|
||||
signal ram_q : ram_t := (
|
||||
-- Format:
|
||||
-- bit 8 = (reserved)
|
||||
-- bit 7 = SYMBOL
|
||||
-- bit 6 = CAPS
|
||||
-- bits 5-3 = row
|
||||
-- bits 2-0 = col (only 0-6)
|
||||
-- No extended
|
||||
|
||||
-- Left / Right Shift = CAPS SHIFT
|
||||
-- Left / Right Ctl = SYM SHIFT
|
||||
-- Left Alt = EXTEND
|
||||
-- Right Alt = GRAPH
|
||||
-- ;",. mapped to appropriate keys
|
||||
-- Arrows mapped to ARROWS
|
||||
-- Caps lock to CAPS LOCK
|
||||
-- Backspace to DELETE
|
||||
-- Esc = BREAK
|
||||
-- ` = EDIT (to left of 1)
|
||||
-- Tab = TRUE VIDEO
|
||||
-- \ = INV VIDEO (right side of same row as tab)
|
||||
|
||||
-- F9 F5 F3 F1 F2 F12
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 00..07
|
||||
-- F10 F8 F6 F4 Tab ` ~
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000010101", "000011110", "000000111", -- 08..0F
|
||||
-- LAlt LShft LCtrl Q 1 !
|
||||
"000000111", "000000101", "001000111", "000000111", "010000111", "000010000", "000011000", "000000111", -- 10..17
|
||||
-- Z S A W 2 @
|
||||
"000000111", "000000111", "000000001", "000001001", "000001000", "000010001", "000011001", "000000111", -- 18..1F
|
||||
-- C X D E 4 $ 3 #
|
||||
"000000111", "000000011", "000000010", "000001010", "000010010", "000011011", "000011010", "000000111", -- 20..27
|
||||
-- Space V F T R 5 %
|
||||
"000000111", "000111000", "000000100", "000001011", "000010100", "000010011", "000011100", "000000111", -- 28..2F
|
||||
-- N B H G Y 6 ¨
|
||||
"000000111", "000111011", "000111100", "000110100", "000001100", "000101100", "000100100", "000000111", -- 30..37
|
||||
-- M J U 7 & 8 *
|
||||
"000000111", "000000111", "000111010", "000110011", "000101011", "000100011", "000100010", "000000111", -- 38..3F
|
||||
-- , < K I O 0 ) 9 (
|
||||
"000000111", "000101101", "000110010", "000101010", "000101001", "000100000", "000100001", "000000111", -- 40..47
|
||||
-- . > / ? L ; : P - _
|
||||
"000000111", "000101110", "010000100", "000110001", "000100101", "000101000", "010110011", "000000111", -- 48..4F
|
||||
-- ' " [ { = +
|
||||
"000000111", "000000111", "000100110", "000000111", "000000111", "010110001", "000000111", "000000111", -- 50..57
|
||||
-- CapsLock R Shift Enter ] } \ |
|
||||
"000001101", "001000111", "000110000", "000000111", "000000111", "000010110", "000000111", "000000111", -- 58..5F
|
||||
-- BackSpace
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000110101", "000000111", -- 60..67
|
||||
-- [1] [4] [7]
|
||||
"000000111", "000011000", "000000111", "000011011", "000100011", "000000111", "000000111", "000000111", -- 68..6F
|
||||
-- [0] [.] [2] [5] [6] [8] Esc NumLock
|
||||
"000100000", "000101110", "000011001", "000011100", "000100100", "000100010", "000011101", "000000111", -- 70..77
|
||||
-- F11 [+] [3] [-] [*] [9] ScrLk
|
||||
"000000111", "010110010", "000011010", "010110011", "010111100", "000100001", "000000111", "000000111", -- 78..7F
|
||||
-- F7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 80..87
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 88..8F
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 90..97
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 98..9F
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- A0..A7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- A8..AF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- B0..B7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- B8..BF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- C0..C7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- C8..CF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- D0..D7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- D8..DF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- E0..E7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- E8..EF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- F0..F7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- F8..FF
|
||||
|
||||
-- Extended
|
||||
|
||||
--
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 00..07
|
||||
--
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 08..0F
|
||||
-- RAlt PrtSc RCtrl
|
||||
"000000111", "000001110", "000000111", "000000111", "010000111", "000000111", "000000111", "000000111", -- 10..17
|
||||
-- LWin
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 18..1F
|
||||
-- RWin
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 20..27
|
||||
-- Menu
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 28..2F
|
||||
-- Power
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 30..37
|
||||
-- Sleep
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 38..3F
|
||||
--
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 40..47
|
||||
-- [/]
|
||||
"000000111", "000000111", "010000100", "000000111", "000000111", "000000111", "000000111", "000000111", -- 48..4F
|
||||
--
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 50..57
|
||||
-- [Enter] Wake
|
||||
"000000111", "000000111", "000110000", "000000111", "000000111", "000000111", "000000111", "000000111", -- 58..5F
|
||||
--
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 60..67
|
||||
-- End Left Home
|
||||
"000000111", "000000111", "000000111", "000111101", "000000111", "000000111", "000000111", "000000111", -- 68..6F
|
||||
-- Ins Delete Down Right Up
|
||||
"000000111", "000000111", "000111110", "000000111", "000110110", "000000110", "000000111", "000000111", -- 70..77
|
||||
-- PDown PUp
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 78..7F
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 80..87
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 88..8F
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 90..97
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- 98..9F
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- A0..A7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- A8..AF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- B0..B7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- B8..BF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- C0..C7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- C8..CF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- D0..D7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- D8..DF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- E0..E7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- E8..EF
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", -- F0..F7
|
||||
"000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111", "000000111" -- F8..FF
|
||||
);
|
||||
begin
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if we_i = '1' then
|
||||
ram_q(to_integer(unsigned(addr_wr_i))) <= data_i;
|
||||
end if;
|
||||
data_o <= ram_q(to_integer(unsigned(addr_rd_i)));
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
282
rtl/input/keyboard/ps2_iobase.vhd
Normal file
282
rtl/input/keyboard/ps2_iobase.vhd
Normal file
@@ -0,0 +1,282 @@
|
||||
|
||||
-- Copyright 2010 Thiago Borges Abdnur
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Original file traced to:
|
||||
-- https://github.com/tiagochst/cmp613/blob/master/Lab4/Doc/ps2_iobase.vhd
|
||||
--
|
||||
-- License traced to:
|
||||
-- https://code.google.com/archive/p/cmp613/source/default/source?page=20
|
||||
-- https://code.google.com/archive/p/cmp613/
|
||||
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
-- Title : MC613
|
||||
-- Project : PS2 Basic Protocol
|
||||
-- Details : www.ic.unicamp.br/~corte/mc613/
|
||||
-- www.computer-engineering.org/ps2protocol/
|
||||
-------------------------------------------------------------------------------
|
||||
-- File : ps2_base.vhd
|
||||
-- Author : Thiago Borges Abdnur
|
||||
-- Company : IC - UNICAMP
|
||||
-- Last update: 2010/04/12
|
||||
-------------------------------------------------------------------------------
|
||||
-- Description:
|
||||
-- PS2 basic control
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
USE ieee.numeric_std.all;
|
||||
|
||||
entity ps2_iobase is
|
||||
generic (
|
||||
clkfreq_g : integer -- This is the system clock value in kHz
|
||||
);
|
||||
port(
|
||||
clock_i : in std_logic; -- system clock (same frequency as defined in 'clkfreq_g' generic)
|
||||
reset_i : in std_logic; -- Reset when '1'
|
||||
enable_i : in std_logic; -- Enable
|
||||
|
||||
ps2_data_i : in std_logic; -- PS2 data pin
|
||||
ps2_clk_i : in std_logic; -- PS2 clock pin
|
||||
ps2_data_o : out std_logic; -- PS2 data pin
|
||||
ps2_clk_o : out std_logic; -- PS2 clock pin
|
||||
ps2_data_out : out std_logic; -- "1" when data is set
|
||||
ps2_clk_out : out std_logic; -- "1" when clock is set
|
||||
|
||||
data_rdy_i : in std_logic; -- Rise this to signal data is ready to be sent to device
|
||||
data_i : in std_logic_vector(7 downto 0); -- Data to be sent to device
|
||||
send_rdy_o : out std_logic; -- '1' if data can be sent to device (wait for this before rising 'data_rdy_i'
|
||||
data_rdy_o : out std_logic; -- '1' when data from device has arrived
|
||||
data_o : out std_logic_vector(7 downto 0); -- Data from device
|
||||
sigsending_o : out std_logic
|
||||
);
|
||||
end;
|
||||
|
||||
architecture rtl of ps2_iobase is
|
||||
|
||||
constant CLKSSTABLE : integer := clkfreq_g / 150;
|
||||
|
||||
signal sdata, hdata : std_logic_vector(7 downto 0);
|
||||
signal sigtrigger : std_logic;
|
||||
signal parchecked : std_logic;
|
||||
signal sigsending : std_logic;
|
||||
signal sigsendend : std_logic;
|
||||
signal sigclkreleased : std_logic;
|
||||
signal sigclkheld : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
-- Trigger for state change to eliminate noise
|
||||
process(clock_i, ps2_clk_i, enable_i, reset_i)
|
||||
variable fcount, rcount : integer range CLKSSTABLE downto 0;
|
||||
begin
|
||||
if(rising_edge(clock_i) and enable_i = '1') then
|
||||
if reset_i = '1' then
|
||||
fcount := 0;
|
||||
rcount := 0;
|
||||
sigtrigger <= '0';
|
||||
-- Falling edge noise
|
||||
elsif ps2_clk_i = '0' then
|
||||
rcount := 0;
|
||||
if fcount >= CLKSSTABLE then
|
||||
sigtrigger <= '1';
|
||||
else
|
||||
fcount := fcount + 1;
|
||||
end if;
|
||||
-- Rising edge noise
|
||||
elsif ps2_clk_i = '1' then
|
||||
fcount := 0;
|
||||
if rcount >= CLKSSTABLE then
|
||||
sigtrigger <= '0';
|
||||
else
|
||||
rcount := rcount + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
FROMPS2:
|
||||
process(sigtrigger, sigsending, reset_i)
|
||||
variable count : integer range 0 to 11;
|
||||
begin
|
||||
if reset_i = '1' or sigsending = '1' then
|
||||
sdata <= (others => '0');
|
||||
parchecked <= '0';
|
||||
count := 0;
|
||||
elsif rising_edge(sigtrigger) then
|
||||
if count = 0 then
|
||||
-- Idle state, check for start bit (0) only and don't
|
||||
-- start counting bits until we get it
|
||||
if ps2_data_i = '0' then
|
||||
-- This is a start bit
|
||||
count := count + 1;
|
||||
end if;
|
||||
else
|
||||
-- Running. 8-bit data comes in LSb first followed by
|
||||
-- a single stop bit (1)
|
||||
if count < 9 then
|
||||
sdata(count - 1) <= ps2_data_i;
|
||||
end if;
|
||||
if count = 9 then
|
||||
if (not (sdata(0) xor sdata(1) xor sdata(2) xor sdata(3)
|
||||
xor sdata(4) xor sdata(5) xor sdata(6) xor sdata(7))) = ps2_data_i then
|
||||
parchecked <= '1';
|
||||
else
|
||||
parchecked <= '0';
|
||||
end if;
|
||||
end if;
|
||||
count := count + 1;
|
||||
if count = 11 then
|
||||
count := 0;
|
||||
parchecked <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
data_rdy_o <= enable_i and parchecked;
|
||||
data_o <= sdata;
|
||||
|
||||
-- Edge triggered send register
|
||||
process(data_rdy_i, sigsendend, reset_i)
|
||||
begin
|
||||
if(rising_edge(data_rdy_i)) then
|
||||
sigsending <= '1';
|
||||
end if;
|
||||
if reset_i = '1' or sigsendend = '1' then
|
||||
sigsending <= '0';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Wait for at least 11ms before allowing to send again
|
||||
process(clock_i, sigsending, reset_i)
|
||||
-- clkfreq_g is the number of clocks within a milisecond
|
||||
variable countclk : integer range 0 to (12 * clkfreq_g);
|
||||
begin
|
||||
if(rising_edge(clock_i) and sigsending = '0') then
|
||||
if countclk = (11 * clkfreq_g) then
|
||||
send_rdy_o <= '1';
|
||||
else
|
||||
countclk := countclk + 1;
|
||||
end if;
|
||||
end if;
|
||||
if sigsending = '1' then
|
||||
send_rdy_o <= '0';
|
||||
countclk := 0;
|
||||
end if;
|
||||
if reset_i = '1' then
|
||||
send_rdy_o <= '1';
|
||||
countclk := 0;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Host input data register
|
||||
process(data_rdy_i, sigsendend, reset_i)
|
||||
begin
|
||||
if(rising_edge(data_rdy_i)) then
|
||||
hdata <= data_i;
|
||||
end if;
|
||||
if reset_i = '1' or sigsendend = '1' then
|
||||
hdata <= (others => '0');
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- PS2 clock control
|
||||
process(enable_i, clock_i, sigsendend, reset_i, sigsending)
|
||||
constant US100CNT : integer := clkfreq_g / 10;
|
||||
variable count : integer range 0 to US100CNT + 101;
|
||||
begin
|
||||
if(rising_edge(clock_i) and sigsending = '1') then
|
||||
if count < US100CNT + 50 then
|
||||
count := count + 1;
|
||||
ps2_clk_o <= '0';
|
||||
ps2_clk_out <= '1';
|
||||
sigclkreleased <= '0';
|
||||
sigclkheld <= '0';
|
||||
elsif count < US100CNT + 100 then
|
||||
count := count + 1;
|
||||
ps2_clk_o <= '0';
|
||||
ps2_clk_out <= '1';
|
||||
sigclkreleased <= '0';
|
||||
sigclkheld <= '1';
|
||||
else
|
||||
ps2_clk_o <= '1';
|
||||
ps2_clk_out <= '0';
|
||||
sigclkreleased <= '1';
|
||||
sigclkheld <= '0';
|
||||
end if;
|
||||
end if;
|
||||
if enable_i = '0' or reset_i = '1' or sigsendend = '1' then
|
||||
ps2_clk_o <= '1';
|
||||
ps2_clk_out <= '0';
|
||||
sigclkreleased <= '1';
|
||||
sigclkheld <= '0';
|
||||
count := 0;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Sending control
|
||||
TOPS2:
|
||||
process(enable_i, sigtrigger, sigsending, sigclkheld, sigclkreleased, reset_i)
|
||||
variable count : integer range 0 to 11;
|
||||
begin
|
||||
if(rising_edge(sigtrigger) and sigclkreleased = '1' and sigsending = '1') then
|
||||
if count >= 0 and count < 8 then
|
||||
ps2_data_o <= hdata(count);
|
||||
sigsendend <= '0';
|
||||
ps2_data_out <= '1';
|
||||
end if;
|
||||
if count = 8 then
|
||||
ps2_data_o <= (not (hdata(0) xor hdata(1) xor hdata(2) xor hdata(3)
|
||||
xor hdata(4) xor hdata(5) xor hdata(6) xor hdata(7)));
|
||||
sigsendend <= '0';
|
||||
ps2_data_out <= '1';
|
||||
end if;
|
||||
if count = 9 then
|
||||
ps2_data_o <= '1';
|
||||
ps2_data_out <= '0';
|
||||
sigsendend <= '0';
|
||||
end if;
|
||||
if count = 10 then
|
||||
ps2_data_o <= '1';
|
||||
ps2_data_out <= '0';
|
||||
sigsendend <= '1';
|
||||
count := 0;
|
||||
end if;
|
||||
count := count + 1;
|
||||
end if;
|
||||
if sigclkheld = '1' then
|
||||
ps2_data_o <= '0';
|
||||
ps2_data_out <= '1';
|
||||
sigsendend <= '0';
|
||||
count := 0;
|
||||
end if;
|
||||
if enable_i = '0' or reset_i = '1' or sigsending = '0' then
|
||||
ps2_data_o <= '1';
|
||||
ps2_data_out <= '0';
|
||||
sigsendend <= '0';
|
||||
count := 0;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sigsending_o <= sigsending;
|
||||
|
||||
end rtl;
|
||||
364
rtl/input/keyboard/ps2_keyb.vhd
Normal file
364
rtl/input/keyboard/ps2_keyb.vhd
Normal file
@@ -0,0 +1,364 @@
|
||||
-- PS2 Keyboard
|
||||
-- Copyright 2020 Fabio Belavenuto
|
||||
-- Copyright 2021 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- ps2 button state is represented in an 8x7 matrix
|
||||
-- when the physical membrane is scanned, the ps2 inserts column data
|
||||
-- caps + sym shift presses are counted; shifts are not lost in multiple keys
|
||||
-- typematic filtered so that shift counts remain accurate
|
||||
-- F11 = multiface nmi button, F12 = divmmc nmi button
|
||||
-- function keys work as on membrane: F11 + number
|
||||
-- pause/break resets the ps2 matrix state
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity ps2_keyb is
|
||||
generic
|
||||
(
|
||||
CLK_KHZ : integer
|
||||
);
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_CLK_n : in std_logic;
|
||||
i_CLK_PS2 : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
-- ps2 interface
|
||||
i_ps2_clk_in : in std_logic;
|
||||
i_ps2_data_in : in std_logic;
|
||||
o_ps2_clk_out_en : out std_logic;
|
||||
o_ps2_clk_out : out std_logic;
|
||||
o_ps2_data_out_en : out std_logic;
|
||||
o_ps2_data_out : out std_logic;
|
||||
-- membrane interaction
|
||||
o_mf_nmi_n : out std_logic;
|
||||
o_divmmc_nmi_n : out std_logic;
|
||||
i_membrane_row : in std_logic_vector(2 downto 0);
|
||||
o_membrane_col : out std_logic_vector(6 downto 0);
|
||||
-- programmable keymap
|
||||
i_keymap_addr : in std_logic_vector(8 downto 0);
|
||||
i_keymap_data : in std_logic_vector(7 downto 0);
|
||||
i_keymap_we : in std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of ps2_keyb is
|
||||
|
||||
signal capshift_count_zero : std_logic;
|
||||
signal capshift_count : std_logic_vector(2 downto 0);
|
||||
|
||||
signal symshift_count_zero : std_logic;
|
||||
signal symshift_count : std_logic_vector(2 downto 0);
|
||||
|
||||
type key_matrix_t is array (7 downto 0) of std_logic_vector(6 downto 0);
|
||||
signal matrix_state : key_matrix_t := ((others => (others => '1')));
|
||||
|
||||
signal row_0_n : std_logic;
|
||||
signal row_7_n : std_logic;
|
||||
|
||||
signal ps2_keymap_data : std_logic_vector(8 downto 0);
|
||||
|
||||
signal ps2_current_keycode : std_logic_vector(9 downto 0);
|
||||
signal ps2_last_keycode : std_logic_vector(9 downto 0);
|
||||
|
||||
signal ps2_key_valid : std_logic;
|
||||
signal ps2_matrix_reset : std_logic;
|
||||
|
||||
signal ps2_receive_valid : std_logic;
|
||||
signal ps2_receive_valid_d : std_logic;
|
||||
signal ps2_receive_valid_re : std_logic;
|
||||
signal ps2_receive_data : std_logic_vector(7 downto 0);
|
||||
signal ps2_send_valid : std_logic;
|
||||
|
||||
signal ps2_data_07 : std_logic;
|
||||
signal ps2_data_78 : std_logic;
|
||||
signal ps2_data_aa : std_logic;
|
||||
signal ps2_data_e0 : std_logic;
|
||||
signal ps2_data_e1 : std_logic;
|
||||
signal ps2_data_f0 : std_logic;
|
||||
|
||||
signal clk_ps2_d : std_logic;
|
||||
signal clk_ps2_re : std_logic;
|
||||
|
||||
type state_t is (KM_IDLE, KM_READ, KM_END);
|
||||
signal state : state_t;
|
||||
signal state_next : state_t;
|
||||
|
||||
signal ps2_key_extend : std_logic;
|
||||
signal ps2_key_release : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
-- nmi buttons simulated via F11 and F12
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
o_mf_nmi_n <= '1';
|
||||
elsif ps2_key_valid = '1' and ps2_key_extend = '0' and ps2_data_78 = '1' then
|
||||
o_mf_nmi_n <= ps2_key_release;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
o_divmmc_nmi_n <= '1';
|
||||
elsif ps2_key_valid = '1' and ps2_key_extend = '0' and ps2_data_07 = '1' then
|
||||
o_divmmc_nmi_n <= ps2_key_release;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- matrix representation
|
||||
|
||||
capshift_count_zero <= '1' when capshift_count = std_logic_vector(to_unsigned(0,capshift_count'length)) else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
capshift_count <= (others => '0');
|
||||
elsif ps2_key_valid = '1' and ps2_keymap_data(6) = '1' then
|
||||
if ps2_key_release = '0' then
|
||||
capshift_count <= capshift_count + 1;
|
||||
elsif capshift_count_zero = '0' then
|
||||
capshift_count <= capshift_count - 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
symshift_count_zero <= '1' when symshift_count = std_logic_vector(to_unsigned(0,symshift_count'length)) else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
symshift_count <= (others => '0');
|
||||
elsif ps2_key_valid = '1' and ps2_keymap_data(7) = '1' then
|
||||
if ps2_key_release = '0' then
|
||||
symshift_count <= symshift_count + 1;
|
||||
elsif symshift_count_zero = '0' then
|
||||
symshift_count <= symshift_count - 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
matrix_state <= ((others => (others => '1')));
|
||||
elsif ps2_key_valid = '1' and ps2_keymap_data(2 downto 0) /= "111" then
|
||||
matrix_state(to_integer(unsigned(ps2_keymap_data(5 downto 3))))(to_integer(unsigned(ps2_keymap_data(2 downto 0)))) <= ps2_key_release;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- membrane scan
|
||||
|
||||
row_0_n <= '0' when i_membrane_row = "000" else '1';
|
||||
row_7_n <= '0' when i_membrane_row = "111" else '1';
|
||||
|
||||
o_membrane_col <= (matrix_state(to_integer(unsigned(i_membrane_row)))(6 downto 2)) &
|
||||
(matrix_state(to_integer(unsigned(i_membrane_row)))(1) and (row_7_n or symshift_count_zero)) &
|
||||
(matrix_state(to_integer(unsigned(i_membrane_row)))(0) and (row_0_n or capshift_count_zero));
|
||||
|
||||
-- ps2 keymap
|
||||
|
||||
keymap: entity work.keymaps
|
||||
port map
|
||||
(
|
||||
clock_i => i_CLK_n,
|
||||
addr_wr_i => i_keymap_addr,
|
||||
data_i => '0' & i_keymap_data,
|
||||
we_i => i_keymap_we,
|
||||
--
|
||||
addr_rd_i => ps2_key_extend & ps2_receive_data,
|
||||
data_o => ps2_keymap_data
|
||||
);
|
||||
|
||||
ps2_current_keycode <= ps2_key_release & ps2_key_extend & ps2_receive_data;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
ps2_last_keycode <= (others => '1');
|
||||
elsif ps2_key_valid = '1' then
|
||||
ps2_last_keycode <= ps2_current_keycode; -- eliminate typematic
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
ps2_key_valid <= '1' when (state = KM_READ) and ((ps2_last_keycode /= ps2_current_keycode) or ps2_key_release = '1') else '0';
|
||||
ps2_matrix_reset <= ps2_key_valid and ps2_data_e1;
|
||||
|
||||
-- ps2 interface
|
||||
|
||||
-- The reset may not be seen inside this module because it operates on a much slower clock.
|
||||
-- The module needs to be rewritten and replaced, possibly merging keyboard and mouse.
|
||||
|
||||
ps2_alt0: entity work.ps2_iobase
|
||||
generic map (
|
||||
clkfreq_g => CLK_KHZ
|
||||
)
|
||||
port map (
|
||||
clock_i => i_CLK_PS2,
|
||||
reset_i => i_reset,
|
||||
enable_i => '1',
|
||||
ps2_clk_i => i_ps2_clk_in,
|
||||
ps2_data_i => i_ps2_data_in,
|
||||
ps2_clk_o => o_ps2_clk_out,
|
||||
ps2_data_o => o_ps2_data_out,
|
||||
ps2_data_out => o_ps2_data_out_en,
|
||||
ps2_clk_out => o_ps2_clk_out_en,
|
||||
data_rdy_i => ps2_send_valid,
|
||||
data_i => X"55",
|
||||
send_rdy_o => open,
|
||||
data_rdy_o => ps2_receive_valid,
|
||||
data_o => ps2_receive_data,
|
||||
sigsending_o => open
|
||||
);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or (clk_ps2_re = '1' and ps2_send_valid = '1') then
|
||||
ps2_send_valid <= '0';
|
||||
elsif ps2_receive_valid_re = '1' and ps2_data_aa = '1' then
|
||||
ps2_send_valid <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
clk_ps2_d <= '1';
|
||||
else
|
||||
clk_ps2_d <= i_CLK_PS2;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
clk_ps2_re <= i_CLK_PS2 and not clk_ps2_d;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
ps2_receive_valid_d <= '0';
|
||||
else
|
||||
ps2_receive_valid_d <= ps2_receive_valid;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
ps2_receive_valid_re <= ps2_receive_valid and not ps2_receive_valid_d;
|
||||
|
||||
process (ps2_receive_data)
|
||||
begin
|
||||
ps2_data_07 <= '0';
|
||||
ps2_data_78 <= '0';
|
||||
ps2_data_aa <= '0';
|
||||
ps2_data_e0 <= '0';
|
||||
ps2_data_e1 <= '0';
|
||||
ps2_data_f0 <= '0';
|
||||
case ps2_receive_data is
|
||||
when X"07" => ps2_data_07 <= '1';
|
||||
when X"78" => ps2_data_78 <= '1';
|
||||
when X"AA" => ps2_data_aa <= '1';
|
||||
when X"E0" => ps2_data_e0 <= '1';
|
||||
when X"E1" => ps2_data_e1 <= '1';
|
||||
when X"F0" => ps2_data_f0 <= '1';
|
||||
when others => null;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- ps2 state machine
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
state <= KM_IDLE;
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (state, ps2_receive_valid_re, ps2_data_aa, ps2_data_e0, ps2_data_f0)
|
||||
begin
|
||||
case state is
|
||||
when KM_IDLE =>
|
||||
if ps2_receive_valid_re = '1' then
|
||||
if ps2_data_aa = '1' then
|
||||
state_next <= KM_END;
|
||||
elsif ps2_data_e0 = '1' or ps2_data_f0 = '1' then
|
||||
state_next <= KM_IDLE;
|
||||
else
|
||||
state_next <= KM_READ;
|
||||
end if;
|
||||
else
|
||||
state_next <= KM_IDLE;
|
||||
end if;
|
||||
when KM_READ =>
|
||||
state_next <= KM_END;
|
||||
when KM_END =>
|
||||
state_next <= KM_IDLE;
|
||||
when others =>
|
||||
state_next <= KM_IDLE;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or state = KM_END then
|
||||
ps2_key_extend <= '0';
|
||||
elsif ps2_receive_valid_re = '1' and ps2_data_e0 = '1' then
|
||||
ps2_key_extend <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or state = KM_END then
|
||||
ps2_key_release <= '0';
|
||||
elsif ps2_receive_valid_re = '1' and ps2_data_f0 = '1' then
|
||||
ps2_key_release <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
198
rtl/input/md6_joystick_connector_x2.vhd
Normal file
198
rtl/input/md6_joystick_connector_x2.vhd
Normal file
@@ -0,0 +1,198 @@
|
||||
|
||||
-- Sega Mega Drive Pads x 2
|
||||
-- Copyright 2020 Victor Trucco and Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity md6_joystick_connector_x2 is
|
||||
port
|
||||
(
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_CLK_28 : in std_logic;
|
||||
i_CLK_EN : in std_logic; -- every ~4.57us
|
||||
|
||||
i_joy_1_n : in std_logic;
|
||||
i_joy_2_n : in std_logic;
|
||||
i_joy_3_n : in std_logic;
|
||||
i_joy_4_n : in std_logic;
|
||||
i_joy_6_n : in std_logic;
|
||||
i_joy_9_n : in std_logic;
|
||||
|
||||
i_io_mode_en : in std_logic;
|
||||
i_io_mode_pin_7 : in std_logic;
|
||||
|
||||
o_joy_7 : out std_logic;
|
||||
o_joy_select : out std_logic; -- 0 = left connector, 1 = right connector
|
||||
|
||||
o_joy_left : out std_logic_vector(10 downto 0); -- active high X Z Y START A C B U D L R
|
||||
o_joy_right : out std_logic_vector(10 downto 0) -- active high X Z Y START A C B U D L R
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of md6_joystick_connector_x2 is
|
||||
|
||||
signal io_mode : std_logic := '0';
|
||||
signal io_mode_change : std_logic;
|
||||
|
||||
-- https://github.com/jonthysell/SegaController/wiki/How-To-Read-Sega-Controllers
|
||||
|
||||
-- The state machine consists of 512 states for a period of ~2.34ms
|
||||
-- 496 states are padding to allow the md controllers time to reset between reads ~2.26ms
|
||||
|
||||
-- Pulse width of the select signal must be < ~15us otherwise 6-button controllers won't work
|
||||
-- Here it's ~9.14us
|
||||
|
||||
signal state : std_logic_vector(8 downto 0);
|
||||
signal state_next : std_logic_vector(8 downto 0);
|
||||
|
||||
-- X X X X X S S 7 J
|
||||
--
|
||||
-- X = padding for md pad reset
|
||||
-- SS7 = eight states in state machine, 7 = select on pin 7
|
||||
-- J = connector being read: left = 0, right = 1
|
||||
|
||||
signal state_rest : std_logic;
|
||||
|
||||
signal joy_left_six_button_n : std_logic;
|
||||
signal joy_left_n : std_logic_vector(10 downto 0);
|
||||
|
||||
signal joy_right_six_button_n : std_logic;
|
||||
signal joy_right_n : std_logic_vector(10 downto 0);
|
||||
|
||||
signal joy_raw : std_logic_vector(5 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- io mode
|
||||
|
||||
process (i_CLK_28)
|
||||
begin
|
||||
if rising_edge(i_CLK_28) then
|
||||
io_mode <= i_io_mode_en;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
io_mode_change <= io_mode xor i_io_mode_en;
|
||||
|
||||
-- md pad state machine
|
||||
|
||||
state_rest <= state(8) or state(7) or state(6) or state(5) or state(4);
|
||||
state_next <= state + 1;
|
||||
|
||||
process (i_CLK_28)
|
||||
begin
|
||||
if rising_edge(i_CLK_28) then
|
||||
if i_reset = '1' or io_mode_change = '1' then
|
||||
state <= "111110000";
|
||||
elsif io_mode = '1' then
|
||||
state <= "1111100" & state_next(1 downto 0);
|
||||
elsif i_CLK_EN = '1' then
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_joy_7 <= (state_rest or state(1)) when io_mode = '0' else i_io_mode_pin_7;
|
||||
o_joy_select <= state(0) when io_mode = '0' else state(1);
|
||||
|
||||
-- build md pad state
|
||||
|
||||
joy_raw <= i_joy_9_n & i_joy_6_n & i_joy_1_n & i_joy_2_n & i_joy_3_n & i_joy_4_n;
|
||||
|
||||
process (i_CLK_28)
|
||||
begin
|
||||
if rising_edge(i_CLK_28) then
|
||||
if i_reset = '1' or io_mode_change = '1' then
|
||||
|
||||
joy_left_n <= (others => '1');
|
||||
joy_right_n <= (others => '1');
|
||||
|
||||
elsif i_CLK_EN = '1' and state_rest = '0' then
|
||||
|
||||
case state(3 downto 0) is
|
||||
|
||||
when "000" & '0' =>
|
||||
joy_left_six_button_n <= '1';
|
||||
joy_left_n <= (others => '1');
|
||||
joy_right_six_button_n <= '1';
|
||||
joy_right_n <= (others => '1');
|
||||
|
||||
when "010" & '0' =>
|
||||
if i_joy_3_n = '0' and i_joy_4_n = '0' then
|
||||
joy_left_n(7 downto 6) <= i_joy_9_n & i_joy_6_n;
|
||||
end if;
|
||||
|
||||
when "010" & '1' =>
|
||||
if i_joy_3_n = '0' and i_joy_4_n = '0' then
|
||||
joy_right_n(7 downto 6) <= i_joy_9_n & i_joy_6_n;
|
||||
end if;
|
||||
|
||||
when "011" & '0' =>
|
||||
joy_left_n(5 downto 0) <= joy_raw;
|
||||
|
||||
when "011" & '1' =>
|
||||
joy_right_n(5 downto 0) <= joy_raw;
|
||||
|
||||
when "100" & '0' =>
|
||||
joy_left_six_button_n <= i_joy_1_n or i_joy_2_n;
|
||||
|
||||
when "100" & '1' =>
|
||||
joy_right_six_button_n <= i_joy_1_n or i_joy_2_n;
|
||||
|
||||
when "101" & '0' =>
|
||||
if joy_left_six_button_n = '0' then
|
||||
joy_left_n(10 downto 8) <= i_joy_3_n & i_joy_1_n & i_joy_2_n;
|
||||
end if;
|
||||
|
||||
when "101" & '1' =>
|
||||
if joy_right_six_button_n = '0' then
|
||||
joy_right_n(10 downto 8) <= i_joy_3_n & i_joy_1_n & i_joy_2_n;
|
||||
end if;
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK_28)
|
||||
begin
|
||||
if rising_edge(i_CLK_28) then
|
||||
if i_reset = '1' or io_mode_change = '1' then
|
||||
o_joy_left <= (others => '0');
|
||||
o_joy_right <= (others => '0');
|
||||
elsif io_mode = '1' and state(1 downto 0) = "01" then
|
||||
o_joy_left <= "00000" & not joy_raw;
|
||||
elsif io_mode = '1' and state(1 downto 0) = "11" then
|
||||
o_joy_right <= "00000" & not joy_raw;
|
||||
elsif io_mode = '0' and state_rest = '1' then
|
||||
o_joy_left <= not joy_left_n;
|
||||
o_joy_right <= not joy_right_n;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
238
rtl/input/membrane/emu_fnkeys.vhd
Normal file
238
rtl/input/membrane/emu_fnkeys.vhd
Normal file
@@ -0,0 +1,238 @@
|
||||
|
||||
-- Function Keys Emulation
|
||||
-- Copyright 2020 Fabio Belavenuto and Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity emu_fnkeys is
|
||||
generic
|
||||
(
|
||||
CLOCK_EN_PERIOD_MS : natural;
|
||||
BUTTON_PERIOD_MS : natural
|
||||
);
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_CLK_EN : in std_logic;
|
||||
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_rows : in std_logic_vector(7 downto 0);
|
||||
o_rows_filtered : out std_logic_vector(7 downto 0);
|
||||
|
||||
i_cols : in std_logic_vector(4 downto 0);
|
||||
o_cols_filtered : out std_logic_vector(4 downto 0);
|
||||
|
||||
i_button_m1_n : in std_logic;
|
||||
i_button_reset_n : in std_logic;
|
||||
|
||||
o_fnkeys : out std_logic_vector(10 downto 1)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of emu_fnkeys is
|
||||
|
||||
constant PERIOD : natural := BUTTON_PERIOD_MS / CLOCK_EN_PERIOD_MS;
|
||||
signal timer_count : natural range 0 to PERIOD := 0;
|
||||
|
||||
signal timer_set : std_logic;
|
||||
signal timer_expired : std_logic;
|
||||
|
||||
signal button_m1_n_edge : std_logic_vector(1 downto 0) := "00";
|
||||
signal button_m1_n_assert : std_logic;
|
||||
|
||||
signal button_reset_n_edge : std_logic_vector(1 downto 0) := "00";
|
||||
signal button_reset_n_assert : std_logic;
|
||||
|
||||
type state_t is (S_IDLE, S_MF_ROW_A11, S_MF_ROW_A12, S_MF_CHECK, S_MF_DONE, S_RESET_CHECK, S_RESET_DONE);
|
||||
|
||||
signal state : state_t;
|
||||
signal next_state : state_t;
|
||||
|
||||
signal local_rows : std_logic_vector(7 downto 0);
|
||||
signal local_cols : std_logic_vector(4 downto 0);
|
||||
|
||||
signal cancel_nmi : std_logic := '0';
|
||||
signal local_fnkeys : std_logic_vector(10 downto 1) := (others => '0');
|
||||
|
||||
begin
|
||||
|
||||
o_rows_filtered <= local_rows;
|
||||
o_cols_filtered <= local_cols;
|
||||
|
||||
o_fnkeys <= local_fnkeys;
|
||||
|
||||
--
|
||||
-- timer
|
||||
--
|
||||
|
||||
timer_set <= '1' when state = S_IDLE and (button_reset_n_assert = '1' or button_m1_n_assert = '1') else '0';
|
||||
timer_expired <= '1' when timer_count = 0 else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
timer_count <= 0;
|
||||
elsif timer_set = '1' then
|
||||
timer_count <= PERIOD;
|
||||
elsif i_CLK_EN = '1' and timer_expired = '0' then
|
||||
timer_count <= timer_count - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--
|
||||
-- button edge detection
|
||||
--
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
button_m1_n_edge <= (others => '0');
|
||||
else
|
||||
button_m1_n_edge <= button_m1_n_edge(0) & i_button_m1_n;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
button_m1_n_assert <= '1' when button_m1_n_edge = "10" else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
button_reset_n_edge <= (others => '0');
|
||||
else
|
||||
button_reset_n_edge <= button_reset_n_edge(0) & i_button_reset_n;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
button_reset_n_assert <= '1' when button_reset_n_edge = "10" else '0';
|
||||
|
||||
--
|
||||
-- state machine
|
||||
--
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
state <= S_IDLE;
|
||||
else
|
||||
state <= next_state;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (state, button_m1_n_assert, button_m1_n_edge, button_reset_n_assert, button_reset_n_edge)
|
||||
begin
|
||||
case state is
|
||||
|
||||
when S_IDLE =>
|
||||
if button_reset_n_assert = '1' then
|
||||
next_state <= S_RESET_CHECK;
|
||||
elsif button_m1_n_assert = '1' then
|
||||
next_state <= S_MF_ROW_A11;
|
||||
else
|
||||
next_state <= S_IDLE;
|
||||
end if;
|
||||
|
||||
when S_MF_ROW_A11 =>
|
||||
next_state <= S_MF_ROW_A12;
|
||||
|
||||
when S_MF_ROW_A12 =>
|
||||
next_state <= S_MF_CHECK;
|
||||
|
||||
when S_MF_CHECK =>
|
||||
if button_m1_n_edge(0) = '1' then
|
||||
next_state <= S_MF_DONE;
|
||||
else
|
||||
next_state <= S_MF_ROW_A11;
|
||||
end if;
|
||||
|
||||
when S_MF_DONE =>
|
||||
next_state <= S_IDLE;
|
||||
|
||||
when S_RESET_CHECK =>
|
||||
if button_reset_n_edge(0) = '1' then
|
||||
next_state <= S_RESET_DONE;
|
||||
else
|
||||
next_state <= S_RESET_CHECK;
|
||||
end if;
|
||||
|
||||
when S_RESET_DONE =>
|
||||
next_state <= S_IDLE;
|
||||
|
||||
when others =>
|
||||
next_state <= S_IDLE;
|
||||
|
||||
end case;
|
||||
end process;
|
||||
|
||||
local_rows <= i_rows when state = S_IDLE else "11110111" when state = S_MF_ROW_A11 else "11101111";
|
||||
local_cols <= i_cols when state = S_IDLE else (others => '1');
|
||||
|
||||
--
|
||||
-- function keys
|
||||
--
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
cancel_nmi <= '0';
|
||||
elsif state = S_IDLE then
|
||||
cancel_nmi <= '0';
|
||||
else
|
||||
cancel_nmi <= cancel_nmi or not (i_cols(4) and i_cols(3) and i_cols(2) and i_cols(1) and i_cols(0));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
local_fnkeys <= (others => '0');
|
||||
elsif state = S_MF_ROW_A11 then
|
||||
local_fnkeys(5 downto 1) <= not i_cols(4 downto 0);
|
||||
elsif state = S_MF_ROW_A12 then
|
||||
local_fnkeys(10 downto 6) <= not (i_cols(0) & i_cols(1) & i_cols(2) & i_cols(3) & i_cols(4));
|
||||
elsif state = S_MF_DONE then
|
||||
local_fnkeys <= '0' & (not timer_expired and not cancel_nmi) & "00000000"; -- F9 = multiface nmi on short press
|
||||
elsif state = S_RESET_DONE then
|
||||
if timer_expired = '1' then
|
||||
local_fnkeys <= "0000000001"; -- F1 = hard reset on long press
|
||||
else
|
||||
local_fnkeys <= "0000001000"; -- F4 = soft reset on short press
|
||||
end if;
|
||||
elsif state = S_IDLE then
|
||||
local_fnkeys <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
256
rtl/input/membrane/membrane.vhd
Normal file
256
rtl/input/membrane/membrane.vhd
Normal file
@@ -0,0 +1,256 @@
|
||||
|
||||
-- Keyboard Membrane Scan
|
||||
-- Copyright 2020 Victor Trucco and Alvin Albrecht
|
||||
--
|
||||
-- Membrane state machine - Victor Trucco
|
||||
-- Refactor & modify for 8x7 matrix - Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity membrane is
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_CLK_EN : in std_logic;
|
||||
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_rows : in std_logic_vector(7 downto 0); -- key rows being read
|
||||
o_cols : out std_logic_vector(4 downto 0); -- key cols returned for read
|
||||
|
||||
o_membrane_rows : out std_logic_vector(7 downto 0); -- physical membrane rows 0 = active, 1 = Z
|
||||
o_membrane_ridx : out std_logic_vector(2 downto 0); -- physical membrane row by number 0-7
|
||||
i_membrane_cols : in std_logic_vector(6 downto 0); -- physical membrane cols returned, 6:5 are extra columns
|
||||
|
||||
i_cancel_extended_entries : in std_logic; -- cancel making entries in the standard 8x5 matrix for the extra keys
|
||||
o_extended_keys : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of membrane is
|
||||
|
||||
type key_matrix_t is array (7 downto 0) of std_logic_vector(6 downto 0);
|
||||
|
||||
signal state : std_logic_vector(8 downto 0) := '1' & X"FE";
|
||||
signal index : natural range 0 to 7;
|
||||
|
||||
signal matrix_state : key_matrix_t := ((others => (others => '1')));
|
||||
signal matrix_work : key_matrix_t := ((others => (others => '1')));
|
||||
|
||||
signal matrix_state_ex : std_logic_vector(16 downto 0);
|
||||
signal matrix_work_ex : std_logic_vector(16 downto 0);
|
||||
|
||||
signal matrix_state_ex_0 : std_logic_vector(18 downto 0);
|
||||
signal matrix_state_ex_1 : std_logic_vector(18 downto 0);
|
||||
|
||||
signal matrix_state_0 : std_logic_vector(4 downto 0);
|
||||
signal matrix_state_3 : std_logic_vector(4 downto 0);
|
||||
signal matrix_state_4 : std_logic_vector(4 downto 0);
|
||||
signal matrix_state_5 : std_logic_vector(4 downto 0);
|
||||
signal matrix_state_7 : std_logic_vector(4 downto 0);
|
||||
|
||||
signal r0 : std_logic_vector(4 downto 0);
|
||||
signal r1 : std_logic_vector(4 downto 0);
|
||||
signal r2 : std_logic_vector(4 downto 0);
|
||||
signal r3 : std_logic_vector(4 downto 0);
|
||||
signal r4 : std_logic_vector(4 downto 0);
|
||||
signal r5 : std_logic_vector(4 downto 0);
|
||||
signal r6 : std_logic_vector(4 downto 0);
|
||||
signal r7 : std_logic_vector(4 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
--
|
||||
-- physical membrane row scan
|
||||
--
|
||||
|
||||
-- one-hot state machine
|
||||
|
||||
-- 0 = START
|
||||
-- 1 = A8
|
||||
-- 2 = A9
|
||||
-- 3 = A10
|
||||
-- 4 = A11
|
||||
-- 5 = A12
|
||||
-- 6 = A13
|
||||
-- 7 = A14
|
||||
-- 8 = A15
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
state <= '1' & X"FE";
|
||||
elsif i_CLK_EN = '1' then
|
||||
state <= state(7 downto 0) & state(8);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_membrane_rows <= state(8 downto 1);
|
||||
|
||||
-- store physical membrane scan into matrix
|
||||
|
||||
process (state)
|
||||
begin
|
||||
if state(1) = '0' then
|
||||
index <= 0;
|
||||
elsif state(2) = '0' then
|
||||
index <= 1;
|
||||
elsif state(3) = '0' then
|
||||
index <= 2;
|
||||
elsif state(4) = '0' then
|
||||
index <= 3;
|
||||
elsif state(5) = '0' then
|
||||
index <= 4;
|
||||
elsif state(6) = '0' then
|
||||
index <= 5;
|
||||
elsif state(7) = '0' then
|
||||
index <= 6;
|
||||
else
|
||||
index <= 7;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_membrane_ridx <= std_logic_vector(to_unsigned(index,3));
|
||||
|
||||
-- 8 x 5
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
matrix_state <= ((others => (others => '1')));
|
||||
matrix_work <= ((others => (others => '1')));
|
||||
elsif i_CLK_EN = '1' then
|
||||
if state(0) = '0' then
|
||||
for I in 0 to 7 loop
|
||||
matrix_state(I) <= matrix_work(I);
|
||||
end loop;
|
||||
else
|
||||
matrix_work(index) <= i_membrane_cols;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- extra two columns
|
||||
|
||||
-- ex registers contain keypresses for:
|
||||
--
|
||||
-- key CPR SMR | N M SYM SPC O P 6 7 8 9 0 5 4 3 2 1 CAP
|
||||
-- bit 18 17 | 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
|
||||
-- column bits 6:5 arranged on rows as follows:
|
||||
--
|
||||
-- bit 6 bit 5
|
||||
--
|
||||
-- row 0 UP EXTEND
|
||||
-- row 1 GRAPH CAPS LOCK
|
||||
-- row 2 INV VIDEO TRUE VIDEO
|
||||
-- row 3 EDIT BREAK
|
||||
-- row 4 " ;
|
||||
-- row 5 . ,
|
||||
-- row 6 RIGHT DELETE
|
||||
-- row 7 DOWN LEFT
|
||||
|
||||
-- Make it harder for naive software to incorrectly read composite keys by
|
||||
-- advancing shift key state one scan and holding shift key state an extra scan.
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or i_cancel_extended_entries = '1' then
|
||||
matrix_state_ex_1 <= (others => '1');
|
||||
matrix_state_ex_0 <= (others => '1');
|
||||
matrix_work_ex <= (others => '1');
|
||||
elsif i_CLK_EN = '1' then
|
||||
if state(0) = '0' then
|
||||
matrix_state_ex_1 <= matrix_state_ex_0;
|
||||
matrix_state_ex_0 <= matrix_work_ex(0) & matrix_work_ex(14) & matrix_work_ex(16 downto 15) & (matrix_work_ex(14) and matrix_state_ex_1(17)) & matrix_work_ex(13 downto 1) & (matrix_work_ex(0) and matrix_state_ex_1(18));
|
||||
matrix_work_ex <= (others => '1');
|
||||
else
|
||||
case index is
|
||||
when 0 =>
|
||||
matrix_work_ex(0) <= matrix_work_ex(0) and i_membrane_cols(6) and i_membrane_cols(5);
|
||||
matrix_work_ex(9) <= i_membrane_cols(6);
|
||||
matrix_work_ex(14) <= matrix_work_ex(14) and i_membrane_cols(5);
|
||||
when 1 =>
|
||||
matrix_work_ex(0) <= matrix_work_ex(0) and i_membrane_cols(6) and i_membrane_cols(5);
|
||||
matrix_work_ex(7) <= i_membrane_cols(6);
|
||||
matrix_work_ex(2) <= i_membrane_cols(5);
|
||||
when 2 =>
|
||||
matrix_work_ex(0) <= matrix_work_ex(0) and i_membrane_cols(6) and i_membrane_cols(5);
|
||||
matrix_work_ex(4) <= i_membrane_cols(6);
|
||||
matrix_work_ex(3) <= i_membrane_cols(5);
|
||||
when 3 =>
|
||||
matrix_work_ex(0) <= matrix_work_ex(0) and i_membrane_cols(6) and i_membrane_cols(5);
|
||||
matrix_work_ex(1) <= i_membrane_cols(6);
|
||||
matrix_work_ex(13) <= i_membrane_cols(5);
|
||||
when 4 =>
|
||||
matrix_work_ex(14) <= matrix_work_ex(14) and i_membrane_cols(6) and i_membrane_cols(5);
|
||||
matrix_work_ex(11) <= i_membrane_cols(6);
|
||||
matrix_work_ex(12) <= i_membrane_cols(5);
|
||||
when 5 =>
|
||||
matrix_work_ex(14) <= matrix_work_ex(14) and i_membrane_cols(6) and i_membrane_cols(5);
|
||||
matrix_work_ex(15) <= i_membrane_cols(6);
|
||||
matrix_work_ex(16) <= i_membrane_cols(5);
|
||||
when 6 =>
|
||||
matrix_work_ex(0) <= matrix_work_ex(0) and i_membrane_cols(6) and i_membrane_cols(5);
|
||||
matrix_work_ex(8) <= i_membrane_cols(6);
|
||||
matrix_work_ex(6) <= i_membrane_cols(5);
|
||||
when others =>
|
||||
matrix_work_ex(0) <= matrix_work_ex(0) and i_membrane_cols(6) and i_membrane_cols(5);
|
||||
matrix_work_ex(10) <= i_membrane_cols(6);
|
||||
matrix_work_ex(5) <= i_membrane_cols(5);
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
matrix_state_ex <= matrix_state_ex_1(16 downto 15) & (matrix_state_ex_1(14) and matrix_state_ex_0(14)) & matrix_state_ex_1(13 downto 1) & (matrix_state_ex_1(0) and matrix_state_ex_0(0));
|
||||
|
||||
-- read matrix state
|
||||
|
||||
matrix_state_0 <= matrix_state(0)(4 downto 1) & (matrix_state(0)(0) and matrix_state_ex(0));
|
||||
matrix_state_3 <= matrix_state(3)(4 downto 0) and matrix_state_ex(5 downto 1);
|
||||
matrix_state_4 <= matrix_state(4)(4 downto 0) and matrix_state_ex(10 downto 6);
|
||||
matrix_state_5 <= matrix_state(5)(4 downto 2) & (matrix_state(5)(1 downto 0) and matrix_state_ex(12 downto 11));
|
||||
matrix_state_7 <= matrix_state(7)(4) & (matrix_state(7)(3 downto 0) and matrix_state_ex(16 downto 13));
|
||||
|
||||
r0 <= matrix_state_0 when i_rows(0) = '0' else (others => '1');
|
||||
r1 <= matrix_state(1)(4 downto 0) when i_rows(1) = '0' else (others => '1');
|
||||
r2 <= matrix_state(2)(4 downto 0) when i_rows(2) = '0' else (others => '1');
|
||||
r3 <= matrix_state_3 when i_rows(3) = '0' else (others => '1');
|
||||
r4 <= matrix_state_4 when i_rows(4) = '0' else (others => '1');
|
||||
r5 <= matrix_state_5 when i_rows(5) = '0' else (others => '1');
|
||||
r6 <= matrix_state(6)(4 downto 0) when i_rows(6) = '0' else (others => '1');
|
||||
r7 <= matrix_state_7 when i_rows(7) = '0' else (others => '1');
|
||||
|
||||
o_cols <= r0 and r1 and r2 and r3 and r4 and r5 and r6 and r7;
|
||||
|
||||
o_extended_keys <= not (matrix_state(7)(6 downto 5) & matrix_state(6)(6 downto 5) & matrix_state(5)(6 downto 5) & matrix_state(4)(6 downto 5) &
|
||||
matrix_state(3)(6 downto 5) & matrix_state(2)(6 downto 5) & matrix_state(1)(6 downto 5) & matrix_state(0)(6 downto 5));
|
||||
|
||||
end architecture;
|
||||
200
rtl/input/membrane/membrane_stick.vhd
Normal file
200
rtl/input/membrane/membrane_stick.vhd
Normal file
@@ -0,0 +1,200 @@
|
||||
|
||||
-- User Definable Keyboard Joystick
|
||||
-- Copyright 2021 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity membrane_stick is
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_CLK_EN : in std_logic; -- scanning a new keyboard row, at least 25x slower than clock
|
||||
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_joy_en_n : in std_logic;
|
||||
|
||||
i_joy_left : in std_logic_vector(10 downto 0);
|
||||
i_joy_left_type : in std_logic_vector(2 downto 0);
|
||||
|
||||
i_joy_right : in std_logic_vector(10 downto 0);
|
||||
i_joy_right_type : in std_logic_vector(2 downto 0);
|
||||
|
||||
i_membrane_row : in std_logic_vector(2 downto 0);
|
||||
o_membrane_col : out std_logic_vector(6 downto 0);
|
||||
|
||||
i_keymap_addr : in std_logic_vector(4 downto 0); -- left/right (4), button number (3:0)
|
||||
i_keymap_data : in std_logic_vector(5 downto 0); -- membrane row (5:3), membrane col (2:0)
|
||||
i_keymap_we : in std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of membrane_stick is
|
||||
|
||||
component keyjoy_sdpram_64_6 is
|
||||
PORT (
|
||||
DPRA : IN STD_LOGIC_VECTOR(6-1 downto 0) := (OTHERS => '0');
|
||||
CLK : IN STD_LOGIC;
|
||||
WE : IN STD_LOGIC;
|
||||
DPO : OUT STD_LOGIC_VECTOR(6-1 downto 0);
|
||||
A : IN STD_LOGIC_VECTOR(6-1-(4*0*boolean'pos(7>4)) downto 0) := (OTHERS => '0');
|
||||
D : IN STD_LOGIC_VECTOR(6-1 downto 0) := (OTHERS => '0')
|
||||
);
|
||||
end component;
|
||||
|
||||
signal state : std_logic := '0';
|
||||
signal state_next : std_logic;
|
||||
|
||||
signal joy_state : std_logic_vector(10 downto 0);
|
||||
signal joy_type : std_logic_vector(2 downto 0);
|
||||
signal joy_addr_start : std_logic_vector(4 downto 0);
|
||||
signal joy_bit_count_start : std_logic_vector(3 downto 0);
|
||||
signal joy_bit_count_end : std_logic_vector(3 downto 0);
|
||||
|
||||
signal bit_count_end : std_logic;
|
||||
signal joy_sel : std_logic;
|
||||
signal sram_addr : std_logic_vector(4 downto 0);
|
||||
signal bit_count : std_logic_vector(3 downto 0);
|
||||
signal bit_count_max : std_logic_vector(3 downto 0);
|
||||
|
||||
signal joy_keymap_do : std_logic_vector(5 downto 0);
|
||||
signal membrane_col : std_logic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- state machine
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
state <= '0';
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (state, i_CLK_EN, joy_sel, bit_count_end)
|
||||
begin
|
||||
case state is
|
||||
when '0' =>
|
||||
if i_CLK_EN = '1' then
|
||||
state_next <= '1';
|
||||
else
|
||||
state_next <= '0';
|
||||
end if;
|
||||
when others =>
|
||||
if joy_sel = '1' and bit_count_end = '1' then
|
||||
state_next <= '0';
|
||||
else
|
||||
state_next <= '1';
|
||||
end if;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- joystick parameter selection
|
||||
|
||||
joy_state <= i_joy_left when joy_sel = '0' else i_joy_right;
|
||||
joy_type <= i_joy_left_type when bit_count_end = '0' else i_joy_right_type;
|
||||
|
||||
process (joy_type)
|
||||
begin
|
||||
case joy_type is
|
||||
when "011" => -- Sinclair 1
|
||||
joy_addr_start <= "00000";
|
||||
joy_bit_count_start <= "0000";
|
||||
joy_bit_count_end <= "0100";
|
||||
when "000" => -- Sinclair 2
|
||||
joy_addr_start <= "00101";
|
||||
joy_bit_count_start <= "0000";
|
||||
joy_bit_count_end <= "0100";
|
||||
when "010" => -- Cursor
|
||||
joy_addr_start <= "01010";
|
||||
joy_bit_count_start <= "0000";
|
||||
joy_bit_count_end <= "0100";
|
||||
when "111" => -- User Defined
|
||||
joy_addr_start <= "10000";
|
||||
joy_bit_count_start <= "0000";
|
||||
joy_bit_count_end <= "1010";
|
||||
when "001" | "100" => -- Kempston
|
||||
joy_addr_start <= "10101";
|
||||
joy_bit_count_start <= "0101";
|
||||
joy_bit_count_end <= "1010";
|
||||
when others => -- MD Pad
|
||||
joy_addr_start <= "11000";
|
||||
joy_bit_count_start <= "1000";
|
||||
joy_bit_count_end <= "1010";
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- joystick address generation
|
||||
|
||||
bit_count_end <= '1' when bit_count = bit_count_max else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if state = '0' or bit_count_end = '1' then
|
||||
joy_sel <= bit_count_end;
|
||||
sram_addr <= joy_addr_start;
|
||||
bit_count <= joy_bit_count_start;
|
||||
bit_count_max <= joy_bit_count_end;
|
||||
elsif state = '1' then
|
||||
sram_addr <= sram_addr + 1;
|
||||
bit_count <= bit_count + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- joystick bit to key assignment lookup
|
||||
|
||||
udk_map: keyjoy_sdpram_64_6 -- initialized with sinclair / cursor mappings
|
||||
port map -- src/ram/init/keyjoy_64_6.coe
|
||||
(
|
||||
-- async read (keymap)
|
||||
DPRA => joy_sel & sram_addr,
|
||||
DPO => joy_keymap_do,
|
||||
-- sync write (cpu)
|
||||
CLK => i_CLK,
|
||||
WE => i_keymap_we,
|
||||
A => i_keymap_addr(4) & '1' & i_keymap_addr(3 downto 0),
|
||||
D => i_keymap_data
|
||||
);
|
||||
|
||||
-- membrane column bits computation
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or (state = '0' and state_next = '1') or i_joy_en_n = '1' then
|
||||
membrane_col <= (others => '1');
|
||||
elsif state = '1' and joy_keymap_do(5 downto 3) = i_membrane_row and joy_state(to_integer(unsigned(bit_count))) = '1' then
|
||||
membrane_col(to_integer(unsigned(joy_keymap_do(2 downto 0)))) <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_membrane_col <= membrane_col(6 downto 0);
|
||||
|
||||
end architecture;
|
||||
351
rtl/input/ps2_mouse.v
Normal file
351
rtl/input/ps2_mouse.v
Normal file
@@ -0,0 +1,351 @@
|
||||
|
||||
// PS2 Mouse
|
||||
// Copyright 2006, 2007 Dennis van Weeren
|
||||
//
|
||||
// This file is part of the ZX Spectrum Next Project
|
||||
// <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
//
|
||||
// The ZX Spectrum Next FPGA source code 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.
|
||||
//
|
||||
// The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
// <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Original:
|
||||
// https://github.com/rkrajnc/minimig-mist/blob/master/rtl/minimig/userio_ps2mouse.v
|
||||
|
||||
// Modifed for the zx next project by Alvin Albrecht
|
||||
// * Add controls to adjust dpi and mouse button swap (operate on returned result)
|
||||
|
||||
//PS2 mouse controller.
|
||||
//This module decodes the standard 3 byte packet of an PS/2 compatible 2 or 3 button mouse.
|
||||
//The module also automatically handles power-up initailzation of the mouse.
|
||||
module ps2_mouse
|
||||
(
|
||||
input clk, //bus clock
|
||||
input reset, //reset
|
||||
|
||||
input ps2mdat_i, //mouse PS/2 data
|
||||
input ps2mclk_i, //mouse PS/2 clk
|
||||
|
||||
output ps2mdat_o, //mouse PS/2 data
|
||||
output ps2mclk_o, //mouse PS/2 clk
|
||||
|
||||
input [2:0] control_i, // button reverse, dpi
|
||||
|
||||
// input [5:0] mou_emu,
|
||||
// input sof,
|
||||
output reg [7:0]zcount, // mouse Z counter
|
||||
output reg [7:0]ycount, //mouse Y counter
|
||||
output reg [7:0]xcount, //mouse X counter
|
||||
output reg mleft, //left mouse button output
|
||||
output reg mthird, //third(middle) mouse button output
|
||||
output reg mright //right mouse button output
|
||||
// input test_load, //load test value to mouse counter
|
||||
// input [15:0] test_data //mouse counter test value
|
||||
);
|
||||
|
||||
reg mclkout;
|
||||
wire mdatout;
|
||||
reg [ 2-1:0] mdatr;
|
||||
reg [ 3-1:0] mclkr;
|
||||
|
||||
reg [11-1:0] mreceive;
|
||||
reg [12-1:0] msend;
|
||||
reg [16-1:0] mtimer;
|
||||
reg [ 3-1:0] mstate;
|
||||
reg [ 3-1:0] mnext;
|
||||
|
||||
reg mreverse;
|
||||
reg [1:0] mdpi;
|
||||
|
||||
reg [7:0] xydelta;
|
||||
reg [2:0] mbutton;
|
||||
|
||||
wire mclkneg;
|
||||
reg mrreset;
|
||||
wire mrready;
|
||||
reg msreset;
|
||||
wire msready;
|
||||
reg mtreset;
|
||||
wire mtready;
|
||||
wire mthalf;
|
||||
reg [ 3-1:0] mpacket;
|
||||
reg intellimouse=0;
|
||||
wire mcmd_done;
|
||||
reg [ 4-1:0] mcmd_cnt=1;
|
||||
reg mcmd_inc=0;
|
||||
reg [12-1:0] mcmd;
|
||||
|
||||
|
||||
// bidirectional open collector IO buffers
|
||||
//assign ps2mdat_o = (mdatout) ? 1'b1 : 1'b0;
|
||||
//assign ps2mclk_o = (mclkout) ? 1'b1 : 1'b0;
|
||||
|
||||
assign ps2mdat_o = mdatout;
|
||||
assign ps2mclk_o = mclkout;
|
||||
|
||||
|
||||
// input synchronization of external signals
|
||||
always @ (posedge clk) begin
|
||||
mdatr[1:0] <= #1 {mdatr[0], ps2mdat_i};
|
||||
mclkr[2:0] <= #1 {mclkr[1:0], ps2mclk_i};
|
||||
end
|
||||
|
||||
// detect mouse clock negative edge
|
||||
assign mclkneg = mclkr[2] & !mclkr[1];
|
||||
|
||||
// PS2 mouse input shifter
|
||||
always @ (posedge clk) begin
|
||||
if (mrreset)
|
||||
mreceive[10:0] <= #1 11'b11111111111;
|
||||
else if (mclkneg)
|
||||
mreceive[10:0] <= #1 {mdatr[1],mreceive[10:1]};
|
||||
end
|
||||
|
||||
assign mrready = !mreceive[0];
|
||||
|
||||
// PS2 mouse data counter
|
||||
always @ (posedge clk) begin
|
||||
if (reset)
|
||||
mcmd_cnt <= #1 4'd0;
|
||||
else if (mcmd_inc && !mcmd_done)
|
||||
mcmd_cnt <= #1 mcmd_cnt + 4'd1;
|
||||
end
|
||||
|
||||
assign mcmd_done = (mcmd_cnt == 4'd9);
|
||||
|
||||
// mouse init commands
|
||||
always @ (*) begin
|
||||
case (mcmd_cnt)
|
||||
// GUARD STOP PARITY DATA START
|
||||
4'h0 : mcmd = {1'b1, 1'b1, 1'b1, 8'hff, 1'b0}; // reset
|
||||
4'h1 : mcmd = {1'b1, 1'b1, 1'b1, 8'hf3, 1'b0}; // set sample rate
|
||||
4'h2 : mcmd = {1'b1, 1'b1, 1'b0, 8'hc8, 1'b0}; // sample rate = 200
|
||||
4'h3 : mcmd = {1'b1, 1'b1, 1'b1, 8'hf3, 1'b0}; // set sample rate
|
||||
4'h4 : mcmd = {1'b1, 1'b1, 1'b0, 8'h64, 1'b0}; // sample rate = 100
|
||||
4'h5 : mcmd = {1'b1, 1'b1, 1'b1, 8'hf3, 1'b0}; // set sample rate
|
||||
4'h6 : mcmd = {1'b1, 1'b1, 1'b1, 8'h50, 1'b0}; // sample rate = 80
|
||||
4'h7 : mcmd = {1'b1, 1'b1, 1'b0, 8'hf2, 1'b0}; // read device type
|
||||
4'h8 : mcmd = {1'b1, 1'b1, 1'b0, 8'hf4, 1'b0}; // enable data reporting
|
||||
default : mcmd = {1'b1, 1'b1, 1'b0, 8'hf4, 1'b0}; // enable data reporting
|
||||
endcase
|
||||
end
|
||||
|
||||
// PS2 mouse send shifter
|
||||
always @ (posedge clk) begin
|
||||
if (msreset)
|
||||
msend[11:0] <= #1 mcmd;
|
||||
else if (!msready && mclkneg)
|
||||
msend[11:0] <= #1 {1'b0,msend[11:1]};
|
||||
end
|
||||
|
||||
assign msready = (msend[11:0]==12'b000000000001);
|
||||
assign mdatout = msend[0];
|
||||
|
||||
// PS2 mouse timer
|
||||
always @(posedge clk) begin
|
||||
if (mtreset)
|
||||
mtimer[15:0] <= #1 16'h0000;
|
||||
else
|
||||
mtimer[15:0] <= #1 mtimer[15:0] + 16'd1;
|
||||
end
|
||||
|
||||
assign mtready = (mtimer[15:0]==16'hffff);
|
||||
assign mthalf = mtimer[11];
|
||||
|
||||
always @ (posedge clk) begin
|
||||
mreverse <= #1 control_i[2];
|
||||
mdpi <= #1 control_i[1:0];
|
||||
end
|
||||
|
||||
always @ (*) begin
|
||||
case(mdpi)
|
||||
2'b00 : xydelta = {mreceive[7:1],1'b0};
|
||||
2'b01 : xydelta = mreceive[8:1];
|
||||
2'b10 : xydelta = {mreceive[8],mreceive[8:2]};
|
||||
default : xydelta = {mreceive[8],mreceive[8],mreceive[8:3]};
|
||||
endcase
|
||||
end
|
||||
|
||||
always @ (*) begin
|
||||
if (mreverse)
|
||||
mbutton = {mreceive[3],mreceive[1],mreceive[2]};
|
||||
else
|
||||
mbutton = {mreceive[3],mreceive[2],mreceive[1]};
|
||||
end
|
||||
|
||||
// PS2 mouse packet decoding and handling
|
||||
always @ (posedge clk) begin
|
||||
if (reset) begin
|
||||
{mthird,mright,mleft} <= #1 3'b000;
|
||||
xcount[7:0] <= #1 8'h00;
|
||||
ycount[7:0] <= #1 8'h00;
|
||||
zcount[7:0] <= #1 8'h00;
|
||||
end else begin
|
||||
// if (test_load) // test value preload
|
||||
// {ycount[7:2],xcount[7:2]} <= #1 {test_data[15:10],test_data[7:2]};
|
||||
if (mpacket == 3'd1) // buttons
|
||||
{mthird,mright,mleft} <= #1 mbutton;
|
||||
else if (mpacket == 3'd2) // delta X movement
|
||||
xcount[7:0] <= #1 xcount[7:0] + xydelta;
|
||||
else if (mpacket == 3'd3) // delta Y movement
|
||||
ycount[7:0] <= #1 ycount[7:0] + xydelta;
|
||||
else if (mpacket == 3'd4) // delta Z movement
|
||||
zcount[7:0] <= #1 zcount[7:0] + {{4{mreceive[4]}}, mreceive[4:1]};
|
||||
// else if (sof) begin
|
||||
// if (mou_emu[3]) ycount <= #1 ycount - 1'b1;
|
||||
// else if (mou_emu[2]) ycount <= #1 ycount + 1'b1;
|
||||
// if (mou_emu[1]) xcount <= #1 xcount - 1'b1;
|
||||
// else if (mou_emu[0]) xcount <= #1 xcount + 1'b1;
|
||||
// end
|
||||
end
|
||||
end
|
||||
|
||||
// PS2 intellimouse flag
|
||||
always @ (posedge clk) begin
|
||||
if (reset)
|
||||
intellimouse <= #1 1'b0;
|
||||
else if ((mpacket==3'd5) && (mreceive[2:1] == 2'b11))
|
||||
intellimouse <= #1 1'b1;
|
||||
end
|
||||
|
||||
// PS2 mouse state machine
|
||||
always @ (posedge clk) begin
|
||||
if (reset || mtready)
|
||||
mstate <= #1 0;
|
||||
else
|
||||
mstate <= #1 mnext;
|
||||
end
|
||||
|
||||
always @ (*) begin
|
||||
mclkout = 1'b1;
|
||||
mtreset = 1'b1;
|
||||
mrreset = 1'b0;
|
||||
msreset = 1'b0;
|
||||
mpacket = 3'd0;
|
||||
mcmd_inc = 1'b0;
|
||||
case(mstate)
|
||||
|
||||
0 : begin
|
||||
// initialize mouse phase 0, start timer
|
||||
mtreset=1;
|
||||
mnext=1;
|
||||
end
|
||||
|
||||
1 : begin
|
||||
//initialize mouse phase 1, hold clk low and reset send logic
|
||||
mclkout=0;
|
||||
mtreset=0;
|
||||
msreset=1;
|
||||
if (mthalf) begin
|
||||
// clk was low long enough, go to next state
|
||||
mnext=2;
|
||||
end else begin
|
||||
mnext=1;
|
||||
end
|
||||
end
|
||||
|
||||
2 : begin
|
||||
// initialize mouse phase 2, send command/data to mouse
|
||||
mrreset=1;
|
||||
mtreset=0;
|
||||
if (msready) begin
|
||||
// command sent
|
||||
mcmd_inc = 1;
|
||||
case (mcmd_cnt)
|
||||
0 : mnext = 4;
|
||||
1 : mnext = 6;
|
||||
2 : mnext = 6;
|
||||
3 : mnext = 6;
|
||||
4 : mnext = 6;
|
||||
5 : mnext = 6;
|
||||
6 : mnext = 6;
|
||||
7 : mnext = 5;
|
||||
8 : mnext = 6;
|
||||
default : mnext = 6;
|
||||
endcase
|
||||
end else begin
|
||||
mnext=2;
|
||||
end
|
||||
end
|
||||
|
||||
3 : begin
|
||||
// get first packet byte
|
||||
mtreset=1;
|
||||
if (mrready) begin
|
||||
// we got our first packet byte
|
||||
mpacket=1;
|
||||
mrreset=1;
|
||||
mnext=4;
|
||||
end else begin
|
||||
// we are still waiting
|
||||
mnext=3;
|
||||
end
|
||||
end
|
||||
|
||||
4 : begin
|
||||
// get second packet byte
|
||||
mtreset=1;
|
||||
if (mrready) begin
|
||||
// we got our second packet byte
|
||||
mpacket=2;
|
||||
mrreset=1;
|
||||
mnext=5;
|
||||
end else begin
|
||||
// we are still waiting
|
||||
mnext=4;
|
||||
end
|
||||
end
|
||||
|
||||
5 : begin
|
||||
// get third packet byte
|
||||
mtreset=1;
|
||||
if (mrready) begin
|
||||
// we got our third packet byte
|
||||
mpacket=3;
|
||||
mrreset=1;
|
||||
mnext = (intellimouse || !mcmd_done) ? 6 : 3;
|
||||
end else begin
|
||||
// we are still waiting
|
||||
mnext=5;
|
||||
end
|
||||
end
|
||||
|
||||
6 : begin
|
||||
// get fourth packet byte
|
||||
mtreset=1;
|
||||
if (mrready) begin
|
||||
// we got our fourth packet byte
|
||||
mpacket = (mcmd_cnt == 8) ? 5 : 4;
|
||||
mrreset=1;
|
||||
mnext = !mcmd_done ? 0 : 3;
|
||||
end else begin
|
||||
// we are still waiting
|
||||
mnext=6;
|
||||
end
|
||||
end
|
||||
|
||||
default : begin
|
||||
//we should never come here
|
||||
mclkout=1'bx;
|
||||
mrreset=1'bx;
|
||||
mtreset=1'bx;
|
||||
msreset=1'bx;
|
||||
mpacket=3'bxxx;
|
||||
mnext=0;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
84
rtl/misc/asymmetrical_debounce.vhd
Normal file
84
rtl/misc/asymmetrical_debounce.vhd
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
-- Asymmetrical Button Debounce
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Allow an immediate transtion to the not initial state but the input must
|
||||
-- hold the initial state for the time to transition back to the initial state.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity asymmetrical_debounce is
|
||||
generic
|
||||
(
|
||||
INITIAL_STATE : std_logic := '0';
|
||||
COUNTER_SIZE : positive := 4
|
||||
);
|
||||
port
|
||||
(
|
||||
clk_i : in std_logic;
|
||||
clk_en_i : in std_logic;
|
||||
reset_i : in std_logic;
|
||||
button_i : in std_logic;
|
||||
button_o : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of asymmetrical_debounce is
|
||||
|
||||
signal counter : std_logic_vector(COUNTER_SIZE downto 0) := (others => '0');
|
||||
signal button_db : std_logic := INITIAL_STATE;
|
||||
|
||||
begin
|
||||
|
||||
-- counter
|
||||
|
||||
process (clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
if reset_i = '1' or button_i /= INITIAL_STATE or button_db = INITIAL_STATE then
|
||||
counter <= (others => '0');
|
||||
elsif clk_en_i = '1' and counter(COUNTER_SIZE) = '0' then
|
||||
counter <= counter + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- output
|
||||
|
||||
process (clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
if reset_i = '1' then
|
||||
button_db <= INITIAL_STATE;
|
||||
else
|
||||
if button_db = INITIAL_STATE then
|
||||
button_db <= button_i;
|
||||
elsif counter(COUNTER_SIZE) = '1' then
|
||||
button_db <= INITIAL_STATE;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
button_o <= button_db;
|
||||
|
||||
end architecture;
|
||||
87
rtl/misc/debounce.vhd
Normal file
87
rtl/misc/debounce.vhd
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
-- Button Debounce
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity debounce is
|
||||
generic
|
||||
(
|
||||
INITIAL_STATE : std_logic := '0';
|
||||
COUNTER_SIZE : positive := 4
|
||||
);
|
||||
port
|
||||
(
|
||||
clk_i : in std_logic;
|
||||
clk_en_i : in std_logic;
|
||||
button_i : in std_logic;
|
||||
button_o : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of debounce is
|
||||
|
||||
signal button : std_logic_vector(1 downto 0) := "10";
|
||||
signal button_noise : std_logic;
|
||||
signal counter : std_logic_vector(COUNTER_SIZE downto 0) := (others => '0');
|
||||
signal button_db : std_logic := INITIAL_STATE;
|
||||
|
||||
begin
|
||||
|
||||
-- button
|
||||
|
||||
process (clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
button <= button(0) & button_i;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
button_noise <= button(0) xor button(1);
|
||||
|
||||
-- counter
|
||||
|
||||
process (clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
if button_noise = '1' then
|
||||
counter <= (others => '0');
|
||||
elsif clk_en_i = '1' and counter(COUNTER_SIZE) = '0' then
|
||||
counter <= counter + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- output
|
||||
|
||||
process (clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
if counter(COUNTER_SIZE) = '1' then
|
||||
button_db <= button(1);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
button_o <= button_db;
|
||||
|
||||
end architecture;
|
||||
182
rtl/misc/flashboot.vhd
Normal file
182
rtl/misc/flashboot.vhd
Normal file
@@ -0,0 +1,182 @@
|
||||
-- Flashboot
|
||||
-- Copyright 2020 Fabio Belavenuto and Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
entity flashboot is
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
i_start : in std_logic;
|
||||
|
||||
i_coreid : in std_logic_vector(4 downto 0);
|
||||
i_failid : in std_logic_vector(4 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of flashboot is
|
||||
|
||||
-- icap program
|
||||
|
||||
type command_list_t is array(0 to 13) of std_logic_vector(17 downto 0);
|
||||
constant command_list : command_list_t := (
|
||||
"11" & X"FFFF", -- dummy word (looped, inactive)
|
||||
"00" & X"AA99", -- sync word
|
||||
"00" & X"5566", -- sync word
|
||||
"00" & X"30A1", -- type 1 write one word to CMD
|
||||
"00" & X"0000", -- null
|
||||
-- "00" & X"31E1", -- type 1 write one word to CWDT
|
||||
-- "00" & X"FFFF", -- wait 64K cycles for sync
|
||||
"00" & X"3261", -- type 1 write one word to GENERAL_1
|
||||
"10" & X"0000", -- multiboot start address 15:0
|
||||
"00" & X"3281", -- type 1 write one word to GENERAL_2
|
||||
"10" & X"0001", -- multiboot opcode and start address 23:16
|
||||
-- "00" & X"32A1", -- type 1 write one word to GENERAL_3
|
||||
-- "10" & X"0002", -- multiboot fallback start address 15:0
|
||||
-- "00" & X"32C1", -- type 1 write one word to GENERAL_4
|
||||
-- "10" & X"0003", -- multiboot fallback opcode and start address 23:16
|
||||
-- "00" & X"30A1", -- type 1 write one word to CMD
|
||||
-- "00" & X"0000", -- null
|
||||
"00" & X"3301", -- type 1 write one word to MODE
|
||||
"00" & X"3100", -- bitstream spi x 4
|
||||
-- "00" & X"3201", -- type 1 write one word to HC_OPT_REG
|
||||
-- "00" & X"001F", -- do not skip initialization
|
||||
"00" & X"30A1", -- type 1 write one word to CMD
|
||||
"00" & X"000E", -- IPROG
|
||||
"00" & X"2000" -- type 1 nop (looped)
|
||||
);
|
||||
|
||||
-- ^ ce_n,wr_n = 10 indicates data comes from source other than command 15:0
|
||||
|
||||
signal command_res : std_logic_vector(15 downto 0);
|
||||
signal swizzle : std_logic_vector(15 downto 0);
|
||||
|
||||
signal coreid : std_logic_vector(4 downto 0);
|
||||
signal spi_address : std_logic_vector(31 downto 0);
|
||||
|
||||
type state_t is (S_0, S_1, S_LOAD);
|
||||
signal state : state_t := S_0;
|
||||
signal state_next : state_t;
|
||||
|
||||
signal ip : std_logic_vector(3 downto 0) := (others => '0'); -- command_list'length
|
||||
signal command : std_logic_vector(17 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- ICAP Configuration Functions
|
||||
|
||||
icap: ICAP_SPARTAN6
|
||||
port map
|
||||
(
|
||||
CLK => i_CLK, -- input clock < 20 MHz
|
||||
CE => command(17) and command(16), -- active low select
|
||||
WRITE => command(16), -- 0 = write, 1 = read
|
||||
I => swizzle -- 16-bit input
|
||||
);
|
||||
|
||||
process (command, spi_address)
|
||||
begin
|
||||
case command(17 downto 16) is
|
||||
when "10" =>
|
||||
if command(0) = '0' then
|
||||
command_res <= spi_address(15 downto 0);
|
||||
else
|
||||
command_res <= spi_address(31 downto 16);
|
||||
end if;
|
||||
when others =>
|
||||
command_res <= command(15 downto 0);
|
||||
end case;
|
||||
end process;
|
||||
|
||||
process (command_res)
|
||||
begin
|
||||
for I in 0 to 7 loop
|
||||
swizzle(I) <= command_res(7-I);
|
||||
swizzle(I+8) <= command_res(7-I+8);
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
-- SPI Offsets
|
||||
|
||||
-- coreid <= i_coreid when command(1) = '0' else i_failid;
|
||||
coreid <= i_coreid;
|
||||
|
||||
spi_address <= X"6B" & coreid & "000" & X"0000"; -- core images every 512K
|
||||
-- spi_address <= X"0B" & coreid & "000" & X"0000"; -- core images every 512K
|
||||
|
||||
-- State Machine
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
state <= S_0;
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (state, i_start)
|
||||
begin
|
||||
case state is
|
||||
when S_0 =>
|
||||
if i_start = '0' then
|
||||
state_next <= S_1;
|
||||
else
|
||||
state_next <= S_0;
|
||||
end if;
|
||||
when S_1 =>
|
||||
if i_start = '1' then
|
||||
state_next <= S_LOAD;
|
||||
else
|
||||
state_next <= S_1;
|
||||
end if;
|
||||
when S_LOAD =>
|
||||
state_next <= S_LOAD;
|
||||
when others =>
|
||||
state_next <= S_0;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- instruction pointer
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if (state /= S_LOAD) then
|
||||
ip <= (others => '0');
|
||||
elsif ip /= (command_list'length - 1) then
|
||||
ip <= ip + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
command <= command_list(to_integer(unsigned(ip))); -- ce_n, wr_n, command
|
||||
|
||||
end architecture;
|
||||
228
rtl/misc/flashboot_old.vhd
Normal file
228
rtl/misc/flashboot_old.vhd
Normal file
@@ -0,0 +1,228 @@
|
||||
|
||||
-- Flashboot
|
||||
-- Copyright 2020 Fabio Belavenuto
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
entity flashboot is
|
||||
port(
|
||||
reset_i : in std_logic;
|
||||
clock_i : in std_logic;
|
||||
start_i : in std_logic;
|
||||
spiaddr_i : in std_logic_vector(31 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture Behavioral of flashboot is
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- ICAP configuration data codes
|
||||
----------------------------------------------------------------------------
|
||||
-- For custom data codes like the ones for reading back, take a look to:
|
||||
-- [OPCODES] UG380 page 88 table 5-23
|
||||
-- [CFG PACKETS] UG380 page 89 tables 5-{24, 25}
|
||||
-- [CG REGISTERS] UG380 page 90 table 5-30
|
||||
----------------------------------------------------------------------------
|
||||
constant DUMMY_C : std_logic_vector(15 downto 0) := X"FFFF"; --
|
||||
constant NOOP_C : std_logic_vector(15 downto 0) := X"2000"; --
|
||||
constant NULL1_C : std_logic_vector(15 downto 0) := X"0000"; --
|
||||
constant NULL2_C : std_logic_vector(15 downto 0) := X"1111"; --
|
||||
constant SYNCH_C : std_logic_vector(15 downto 0) := X"AA99"; --
|
||||
constant SYNCL_C : std_logic_vector(15 downto 0) := X"5566"; --
|
||||
constant CMD_WR_GEN1_C : std_logic_vector(15 downto 0) := X"3261"; --
|
||||
constant CMD_WR_GEN2_C : std_logic_vector(15 downto 0) := X"3281"; --
|
||||
constant CMD_WR_CMD_C : std_logic_vector(15 downto 0) := X"30A1"; --
|
||||
constant CMD_WR_MOD_C : std_logic_vector(15 downto 0) := X"3301"; --
|
||||
constant CMD_IPROG_C : std_logic_vector(15 downto 0) := X"000E"; --
|
||||
constant BIT4X_C : std_logic_vector(15 downto 0) := X"3100"; --
|
||||
|
||||
type states_t is (IDLE, SYNC_H, SYNC_L, GEN1_H, GEN1_L, GEN2_H, GEN2_L, NUL_H,
|
||||
NUL_L, MOD_H, MOD_L, RBT_H, RBT_L, NOOP_0, NOOP_1, NOOP_2, NOOP_3);
|
||||
|
||||
signal state_s : states_t;
|
||||
signal next_state_s : states_t;
|
||||
|
||||
signal icap_ce_r_s : std_logic;
|
||||
signal icap_wr_r_s : std_logic;
|
||||
signal icap_ce_s : std_logic;
|
||||
signal icap_wr_s : std_logic;
|
||||
signal icap_i_r_s : std_logic_vector(15 downto 0);
|
||||
signal icap_i_s : std_logic_vector(15 downto 0);
|
||||
|
||||
-- signal spi_addr_s : std_logic_vector(31 downto 0) := X"6B000000"; -- 0B = Fast Read, 3B = Dual Fast Read, 6B = Quad Fast Read
|
||||
|
||||
begin
|
||||
|
||||
ICAP_SPARTAN6_inst : ICAP_SPARTAN6
|
||||
port map (
|
||||
CLK => clock_i, -- 1-bit input: Clock input
|
||||
CE => icap_ce_s, -- 1-bit input: Active-Low ICAP Enable input
|
||||
I => icap_i_s, -- 16-bit input: Configuration data input bus
|
||||
WRITE => icap_wr_s -- 1-bit input: Read/Write control input
|
||||
);
|
||||
|
||||
-- assign values
|
||||
process(clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
-- First we order the bits according to UG380 Table2-5 page 37, as specified in page 126
|
||||
icap_i_s(0) <= icap_i_r_s(7);
|
||||
icap_i_s(1) <= icap_i_r_s(6);
|
||||
icap_i_s(2) <= icap_i_r_s(5);
|
||||
icap_i_s(3) <= icap_i_r_s(4);
|
||||
icap_i_s(4) <= icap_i_r_s(3);
|
||||
icap_i_s(5) <= icap_i_r_s(2);
|
||||
icap_i_s(6) <= icap_i_r_s(1);
|
||||
icap_i_s(7) <= icap_i_r_s(0);
|
||||
icap_i_s(8) <= icap_i_r_s(15);
|
||||
icap_i_s(9) <= icap_i_r_s(14);
|
||||
icap_i_s(10) <= icap_i_r_s(13);
|
||||
icap_i_s(11) <= icap_i_r_s(12);
|
||||
icap_i_s(12) <= icap_i_r_s(11);
|
||||
icap_i_s(13) <= icap_i_r_s(10);
|
||||
icap_i_s(14) <= icap_i_r_s(9);
|
||||
icap_i_s(15) <= icap_i_r_s(8);
|
||||
icap_wr_s <= icap_wr_r_s;
|
||||
icap_ce_s <= icap_ce_r_s;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- next state
|
||||
process(clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_i = '1' then
|
||||
state_s <= IDLE;
|
||||
else
|
||||
state_s <= next_state_s;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- FSM
|
||||
process (state_s, start_i, spiaddr_i)
|
||||
begin
|
||||
case state_s is
|
||||
when IDLE =>
|
||||
if start_i = '1' then
|
||||
next_state_s <= SYNC_H;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= SYNCH_C;
|
||||
else
|
||||
next_state_s <= IDLE;
|
||||
icap_ce_r_s <= '1';
|
||||
icap_wr_r_s <= '1';
|
||||
icap_i_r_s <= DUMMY_C;
|
||||
end if;
|
||||
when SYNC_H =>
|
||||
next_state_s <= SYNC_L;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= SYNCL_C;
|
||||
when SYNC_L =>
|
||||
next_state_s <= NUL_H;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= CMD_WR_CMD_C;
|
||||
when NUL_H =>
|
||||
next_state_s <= GEN1_H;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= NULL1_C;
|
||||
when GEN1_H =>
|
||||
next_state_s <= GEN1_L;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= CMD_WR_GEN1_C;
|
||||
when GEN1_L =>
|
||||
next_state_s <= GEN2_H;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= spiaddr_i(15 downto 0);
|
||||
when GEN2_H =>
|
||||
next_state_s <= GEN2_L;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= CMD_WR_GEN2_C;
|
||||
when GEN2_L =>
|
||||
next_state_s <= MOD_H;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= spiaddr_i(31 downto 16);
|
||||
when MOD_H =>
|
||||
next_state_s <= MOD_L;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= CMD_WR_MOD_C;
|
||||
when MOD_L =>
|
||||
next_state_s <= NUL_L;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= BIT4X_C;
|
||||
when NUL_L =>
|
||||
next_state_s <= RBT_H;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= CMD_WR_CMD_C;
|
||||
when RBT_H =>
|
||||
next_state_s <= RBT_L;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= CMD_IPROG_C;
|
||||
when RBT_L =>
|
||||
next_state_s <= NOOP_0;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= NOOP_C;
|
||||
when NOOP_0 =>
|
||||
next_state_s <= NOOP_1;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= NOOP_C;
|
||||
when NOOP_1 =>
|
||||
next_state_s <= NOOP_2;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= NOOP_C;
|
||||
when NOOP_2 =>
|
||||
next_state_s <= NOOP_3;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= NOOP_C;
|
||||
when NOOP_3 =>
|
||||
next_state_s <= IDLE;
|
||||
icap_ce_r_s <= '0';
|
||||
icap_wr_r_s <= '0';
|
||||
icap_i_r_s <= NULL2_C;
|
||||
when others =>
|
||||
next_state_s <= IDLE;
|
||||
icap_ce_r_s <= '1';
|
||||
icap_wr_r_s <= '1';
|
||||
icap_i_r_s <= NULL2_C;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
55
rtl/misc/synchronize.vhd
Normal file
55
rtl/misc/synchronize.vhd
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
-- Async Input Synchronization
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity synchronize is
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_signal : in std_logic;
|
||||
o_signal : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of synchronize is
|
||||
|
||||
signal sig : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if falling_edge(i_CLK) then
|
||||
sig <= i_signal;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
o_signal <= sig;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
496
rtl/mister/bram.vhd
Normal file
496
rtl/mister/bram.vhd
Normal file
@@ -0,0 +1,496 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity keyjoy_sdpram_64_6 is
|
||||
port
|
||||
(
|
||||
DPRA : in std_logic_vector(5 downto 0);
|
||||
DPO : out std_logic_vector(5 downto 0);
|
||||
CLK : in std_logic;
|
||||
WE : in std_logic;
|
||||
A : in std_logic_vector(5 downto 0);
|
||||
D : in std_logic_vector(5 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of keyjoy_sdpram_64_6 is
|
||||
begin
|
||||
|
||||
ram: work.dpram
|
||||
generic map
|
||||
(
|
||||
addr_width_a => 6,
|
||||
data_width_a => 6,
|
||||
addr_width_b => 6,
|
||||
data_width_b => 6,
|
||||
mem_init_file => "rtl/mister/keyjoy_sdpram_64_6.mif"
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock0 => CLK,
|
||||
address_a => DPRA,
|
||||
q_a => DPO,
|
||||
|
||||
clock1 => CLK,
|
||||
wren_b => WE,
|
||||
address_b => A,
|
||||
data_b => D
|
||||
);
|
||||
|
||||
end rtl;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity sdpram_128_8 is
|
||||
port
|
||||
(
|
||||
DPRA : in std_logic_vector(6 downto 0);
|
||||
DPO : out std_logic_vector(7 downto 0);
|
||||
CLK : in std_logic;
|
||||
WE : in std_logic;
|
||||
A : in std_logic_vector(6 downto 0);
|
||||
D : in std_logic_vector(7 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of sdpram_128_8 is
|
||||
begin
|
||||
|
||||
ram : work.mlab
|
||||
generic map
|
||||
(
|
||||
addr_width => 7,
|
||||
data_width => 8
|
||||
)
|
||||
port map
|
||||
(
|
||||
clk => CLK,
|
||||
rdaddress => DPRA,
|
||||
q => DPO,
|
||||
wraddress => A,
|
||||
data => D,
|
||||
wren => WE
|
||||
);
|
||||
|
||||
end rtl;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity spram_320_9 is
|
||||
port
|
||||
(
|
||||
CLK : in std_logic;
|
||||
WE : in std_logic;
|
||||
SPO : out std_logic_vector(8 downto 0);
|
||||
A : in std_logic_vector(8 downto 0);
|
||||
D : in std_logic_vector(8 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of spram_320_9 is
|
||||
begin
|
||||
|
||||
ram : work.mlab
|
||||
generic map
|
||||
(
|
||||
addr_width => 9,
|
||||
data_width => 9
|
||||
)
|
||||
port map
|
||||
(
|
||||
clk => CLK,
|
||||
rdaddress => A,
|
||||
q => SPO,
|
||||
wraddress => A,
|
||||
data => D,
|
||||
wren => WE
|
||||
);
|
||||
|
||||
end rtl;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity sdpbram_16k_8 is
|
||||
port
|
||||
(
|
||||
WEA : in std_logic;
|
||||
ADDRA : in std_logic_vector(13 downto 0);
|
||||
DINA : in std_logic_vector(7 downto 0);
|
||||
CLKA : in std_logic;
|
||||
--
|
||||
ENB : in std_logic;
|
||||
ADDRB : in std_logic_vector(13 downto 0);
|
||||
DOUTB : out std_logic_vector(7 downto 0);
|
||||
CLKB : in std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of sdpbram_16k_8 is
|
||||
begin
|
||||
|
||||
ram: work.dpram
|
||||
generic map (
|
||||
addr_width_a => 14,
|
||||
data_width_a => 8,
|
||||
addr_width_b => 14,
|
||||
data_width_b => 8
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock0 => CLKA,
|
||||
clock1 => CLKB,
|
||||
|
||||
address_a => ADDRA,
|
||||
data_a => DINA,
|
||||
wren_a => WEA,
|
||||
|
||||
address_b => ADDRB,
|
||||
q_b => DOUTB
|
||||
);
|
||||
|
||||
end rtl;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity sdpram_16_9 is
|
||||
port
|
||||
(
|
||||
DPRA : in std_logic_vector(3 downto 0);
|
||||
DPO : out std_logic_vector(8 downto 0);
|
||||
CLK : in std_logic;
|
||||
WE : in std_logic;
|
||||
A : in std_logic_vector(3 downto 0);
|
||||
D : in std_logic_vector(8 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of sdpram_16_9 is
|
||||
begin
|
||||
|
||||
ram : work.mlab
|
||||
generic map
|
||||
(
|
||||
addr_width => 4,
|
||||
data_width => 9
|
||||
)
|
||||
port map
|
||||
(
|
||||
clk => CLK,
|
||||
rdaddress => DPRA,
|
||||
q => DPO,
|
||||
wraddress => A,
|
||||
data => D,
|
||||
wren => WE
|
||||
);
|
||||
|
||||
end rtl;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity sdpram_64_9 is
|
||||
port
|
||||
(
|
||||
DPRA : IN STD_LOGIC_VECTOR(5 downto 0);
|
||||
CLK : IN STD_LOGIC;
|
||||
WE : IN STD_LOGIC;
|
||||
DPO : OUT STD_LOGIC_VECTOR(8 downto 0);
|
||||
A : IN STD_LOGIC_VECTOR(5 downto 0);
|
||||
D : IN STD_LOGIC_VECTOR(8 downto 0)
|
||||
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of sdpram_64_9 is
|
||||
begin
|
||||
|
||||
ram : work.mlab
|
||||
generic map
|
||||
(
|
||||
addr_width => 6,
|
||||
data_width => 9
|
||||
)
|
||||
port map
|
||||
(
|
||||
clk => CLK,
|
||||
rdaddress => DPRA,
|
||||
q => DPO,
|
||||
wraddress => A,
|
||||
data => D,
|
||||
wren => WE
|
||||
);
|
||||
|
||||
end rtl;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity tdpram is
|
||||
generic (
|
||||
addr_width_g : integer := 8;
|
||||
data_width_g : integer := 8
|
||||
);
|
||||
port (
|
||||
clk_a_i : in std_logic;
|
||||
we_a_i : in std_logic;
|
||||
addr_a_i : in std_logic_vector(addr_width_g-1 downto 0);
|
||||
data_a_i : in std_logic_vector(data_width_g-1 downto 0);
|
||||
data_a_o : out std_logic_vector(data_width_g-1 downto 0);
|
||||
--
|
||||
clk_b_i : in std_logic;
|
||||
we_b_i : in std_logic;
|
||||
addr_b_i : in std_logic_vector(addr_width_g-1 downto 0);
|
||||
data_b_i : in std_logic_vector(data_width_g-1 downto 0);
|
||||
data_b_o : out std_logic_vector(data_width_g-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of tdpram is
|
||||
begin
|
||||
|
||||
ram: work.dpram
|
||||
generic map (
|
||||
addr_width_a => addr_width_g,
|
||||
data_width_a => data_width_g,
|
||||
addr_width_b => addr_width_g,
|
||||
data_width_b => data_width_g
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock0 => clk_a_i,
|
||||
clock1 => clk_b_i,
|
||||
|
||||
address_a => addr_a_i,
|
||||
data_a => data_a_i,
|
||||
wren_a => we_a_i,
|
||||
q_a => data_a_o,
|
||||
|
||||
address_b => addr_b_i,
|
||||
data_b => data_b_i,
|
||||
wren_b => we_b_i,
|
||||
q_b => data_b_o
|
||||
);
|
||||
|
||||
end architecture;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity dpram2 is
|
||||
generic (
|
||||
addr_width_g : integer := 8;
|
||||
data_width_g : integer := 8;
|
||||
init_file_g : string := " "
|
||||
);
|
||||
port (
|
||||
clk_a_i : in std_logic;
|
||||
we_i : in std_logic;
|
||||
addr_a_i : in std_logic_vector(addr_width_g-1 downto 0);
|
||||
data_a_i : in std_logic_vector(data_width_g-1 downto 0);
|
||||
data_a_o : out std_logic_vector(data_width_g-1 downto 0);
|
||||
--
|
||||
clk_b_i : in std_logic;
|
||||
addr_b_i : in std_logic_vector(addr_width_g-1 downto 0);
|
||||
data_b_o : out std_logic_vector(data_width_g-1 downto 0)
|
||||
);
|
||||
|
||||
end entity;
|
||||
|
||||
architecture rtl of dpram2 is
|
||||
begin
|
||||
|
||||
ram: work.dpram
|
||||
generic map (
|
||||
addr_width_a => addr_width_g,
|
||||
data_width_a => data_width_g,
|
||||
addr_width_b => addr_width_g,
|
||||
data_width_b => data_width_g,
|
||||
mem_init_file => init_file_g
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock0 => clk_a_i,
|
||||
clock1 => clk_b_i,
|
||||
|
||||
address_a => addr_a_i,
|
||||
data_a => data_a_i,
|
||||
wren_a => we_i,
|
||||
q_a => data_a_o,
|
||||
|
||||
address_b => addr_b_i,
|
||||
q_b => data_b_o
|
||||
);
|
||||
|
||||
end rtl;
|
||||
|
||||
----------------------
|
||||
-- Dual port Block RAM different parameters and clocks on ports
|
||||
--------------------------------------------------------------
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
entity dpram is
|
||||
generic (
|
||||
addr_width_a : integer := 8;
|
||||
data_width_a : integer := 8;
|
||||
addr_width_b : integer := 8;
|
||||
data_width_b : integer := 8;
|
||||
mem_init_file : string := " "
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clock0 : in STD_LOGIC;
|
||||
clock1 : in STD_LOGIC;
|
||||
|
||||
address_a : in STD_LOGIC_VECTOR (addr_width_a-1 DOWNTO 0);
|
||||
data_a : in STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0) := (others => '0');
|
||||
enable_a : in STD_LOGIC := '1';
|
||||
wren_a : in STD_LOGIC := '0';
|
||||
q_a : out STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0);
|
||||
cs_a : in std_logic := '1';
|
||||
|
||||
address_b : in STD_LOGIC_VECTOR (addr_width_b-1 DOWNTO 0) := (others => '0');
|
||||
data_b : in STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0) := (others => '0');
|
||||
enable_b : in STD_LOGIC := '1';
|
||||
wren_b : in STD_LOGIC := '0';
|
||||
q_b : out STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0);
|
||||
cs_b : in std_logic := '1'
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dpram IS
|
||||
|
||||
signal q0 : std_logic_vector((data_width_a - 1) downto 0);
|
||||
signal q1 : std_logic_vector((data_width_b - 1) downto 0);
|
||||
|
||||
BEGIN
|
||||
q_a<= q0 when cs_a = '1' else (others => '1');
|
||||
q_b<= q1 when cs_b = '1' else (others => '1');
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
address_reg_b => "CLOCK1",
|
||||
clock_enable_input_a => "NORMAL",
|
||||
clock_enable_input_b => "NORMAL",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
clock_enable_output_b => "BYPASS",
|
||||
indata_reg_b => "CLOCK1",
|
||||
intended_device_family => "Cyclone V",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**addr_width_a,
|
||||
numwords_b => 2**addr_width_b,
|
||||
operation_mode => "BIDIR_DUAL_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_aclr_b => "NONE",
|
||||
outdata_reg_a => "UNREGISTERED",
|
||||
outdata_reg_b => "UNREGISTERED",
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
|
||||
init_file => mem_init_file,
|
||||
widthad_a => addr_width_a,
|
||||
widthad_b => addr_width_b,
|
||||
width_a => data_width_a,
|
||||
width_b => data_width_b,
|
||||
width_byteena_a => 1,
|
||||
width_byteena_b => 1,
|
||||
wrcontrol_wraddress_reg_b => "CLOCK1"
|
||||
)
|
||||
PORT MAP (
|
||||
address_a => address_a,
|
||||
address_b => address_b,
|
||||
clock0 => clock0,
|
||||
clock1 => clock1,
|
||||
clocken0 => enable_a,
|
||||
clocken1 => enable_b,
|
||||
data_a => data_a,
|
||||
data_b => data_b,
|
||||
wren_a => wren_a and cs_a,
|
||||
wren_b => wren_b and cs_b,
|
||||
q_a => q0,
|
||||
q_b => q1
|
||||
);
|
||||
|
||||
END SYN;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity mlab is
|
||||
generic (
|
||||
addr_width : integer := 8;
|
||||
data_width : integer := 8
|
||||
);
|
||||
port
|
||||
(
|
||||
clk : in std_logic;
|
||||
rdaddress : in std_logic_vector(addr_width-1 downto 0);
|
||||
q : out std_logic_vector(data_width-1 downto 0);
|
||||
wraddress : in std_logic_vector(addr_width-1 downto 0);
|
||||
data : in std_logic_vector(data_width-1 downto 0);
|
||||
wren : in std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
architecture rtl of mlab is
|
||||
begin
|
||||
|
||||
altdpram_component : altdpram
|
||||
GENERIC MAP (
|
||||
indata_aclr => "OFF",
|
||||
indata_reg => "INCLOCK",
|
||||
intended_device_family => "Cyclone V",
|
||||
lpm_type => "altdpram",
|
||||
outdata_aclr => "OFF",
|
||||
outdata_reg => "UNREGISTERED",
|
||||
ram_block_type => "MLAB",
|
||||
rdaddress_aclr => "OFF",
|
||||
rdaddress_reg => "UNREGISTERED",
|
||||
rdcontrol_aclr => "OFF",
|
||||
rdcontrol_reg => "UNREGISTERED",
|
||||
width => data_width,
|
||||
widthad => addr_width,
|
||||
width_byteena => 1,
|
||||
wraddress_aclr => "OFF",
|
||||
wraddress_reg => "INCLOCK",
|
||||
wrcontrol_aclr => "OFF",
|
||||
wrcontrol_reg => "INCLOCK"
|
||||
)
|
||||
PORT MAP (
|
||||
data => data,
|
||||
inclock => clk,
|
||||
rdaddress => rdaddress,
|
||||
wraddress => wraddress,
|
||||
wren => wren,
|
||||
q => q
|
||||
);
|
||||
|
||||
end rtl;
|
||||
16
rtl/mister/keyjoy_sdpram_64_6.mif
Normal file
16
rtl/mister/keyjoy_sdpram_64_6.mif
Normal file
@@ -0,0 +1,16 @@
|
||||
DEPTH = 64;
|
||||
WIDTH = 6;
|
||||
ADDRESS_RADIX = UNS;
|
||||
DATA_RADIX = BIN;
|
||||
CONTENT BEGIN
|
||||
|
||||
0: 100011 100100 100010 100001 100000 011001 011000 011010;
|
||||
8: 011011 011100 100010 011100 100100 100011 100000 111111;
|
||||
16: 000111 000111 000111 000111 000111 000111 000111 000111;
|
||||
24: 000111 000111 000111 000111 000111 000111 000111 000111;
|
||||
32: 100011 100100 100010 100001 100000 011001 011000 011010;
|
||||
40: 011011 011100 100010 011100 100100 100011 100000 111111;
|
||||
48: 000111 000111 000111 000111 000111 000111 000111 000111;
|
||||
56: 000111 000111 000111 000111 000111 000111 000111 000111;
|
||||
|
||||
END;
|
||||
208
rtl/mister/ps2_keyb.vhd
Normal file
208
rtl/mister/ps2_keyb.vhd
Normal file
@@ -0,0 +1,208 @@
|
||||
-- PS2 Keyboard
|
||||
-- Copyright 2020 Fabio Belavenuto
|
||||
-- Copyright 2021 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- ps2 button state is represented in an 8x7 matrix
|
||||
-- when the physical membrane is scanned, the ps2 inserts column data
|
||||
-- caps + sym shift presses are counted; shifts are not lost in multiple keys
|
||||
-- typematic filtered so that shift counts remain accurate
|
||||
-- F11 = multiface nmi button, F12 = divmmc nmi button
|
||||
-- function keys work as on membrane: F11 + number
|
||||
-- pause/break resets the ps2 matrix state
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity ps2_keyb is
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
-- ps2 interface
|
||||
ps2_key : in std_logic_vector(10 downto 0);
|
||||
|
||||
-- membrane interaction
|
||||
i_membrane_row : in std_logic_vector(2 downto 0);
|
||||
o_membrane_col : out std_logic_vector(6 downto 0);
|
||||
|
||||
-- programmable keymap
|
||||
i_keymap_addr : in std_logic_vector(8 downto 0);
|
||||
i_keymap_data : in std_logic_vector(7 downto 0);
|
||||
i_keymap_we : in std_logic;
|
||||
|
||||
fn : out std_logic_vector(11 downto 1)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of ps2_keyb is
|
||||
|
||||
signal capshift_count_zero : std_logic;
|
||||
signal capshift_count : std_logic_vector(2 downto 0);
|
||||
|
||||
signal symshift_count_zero : std_logic;
|
||||
signal symshift_count : std_logic_vector(2 downto 0);
|
||||
|
||||
type key_matrix_t is array (7 downto 0) of std_logic_vector(6 downto 0);
|
||||
signal matrix_state : key_matrix_t := ((others => (others => '1')));
|
||||
|
||||
signal row_0_n : std_logic;
|
||||
signal row_7_n : std_logic;
|
||||
|
||||
signal ps2_keymap_data : std_logic_vector(8 downto 0);
|
||||
|
||||
signal ps2_current_keycode : std_logic_vector(9 downto 0);
|
||||
|
||||
signal ps2_key_valid : std_logic;
|
||||
signal ps2_matrix_reset : std_logic;
|
||||
|
||||
signal ps2_stb1, ps2_stb2 : std_logic;
|
||||
signal ps2_receive_data : std_logic_vector(7 downto 0);
|
||||
|
||||
signal ps2_key_extend : std_logic;
|
||||
signal ps2_key_release : std_logic;
|
||||
begin
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
ps2_stb1 <= ps2_key(10);
|
||||
ps2_stb2 <= ps2_stb1;
|
||||
ps2_key_valid <= ps2_stb2 xor ps2_stb1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
ps2_key_release <= not ps2_key(9);
|
||||
ps2_key_extend <= ps2_key(8);
|
||||
ps2_receive_data <= ps2_key(7 downto 0);
|
||||
|
||||
ps2_current_keycode <= ps2_key_release & ps2_key_extend & ps2_receive_data;
|
||||
ps2_matrix_reset <= '1' when ps2_key_valid = '1' and ps2_key_extend = '1' and ps2_receive_data = X"77" else '0';
|
||||
|
||||
|
||||
-- F1..F11
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
fn <= (others => '0');
|
||||
elsif ps2_key_valid = '1' and ps2_key_extend = '0' then
|
||||
if ps2_receive_data = X"05" then -- F1
|
||||
fn(1) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"06" then -- F2
|
||||
fn(2) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"04" then -- F3
|
||||
fn(3) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"0C" then -- F4
|
||||
fn(4) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"03" then -- F5
|
||||
fn(5) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"0B" then -- F6
|
||||
fn(6) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"83" then -- F7
|
||||
fn(7) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"0A" then -- F8
|
||||
fn(8) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"01" then -- F9
|
||||
fn(9) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"09" then -- F10
|
||||
fn(10) <= not ps2_key_release;
|
||||
elsif ps2_receive_data = X"78" then -- F11
|
||||
fn(11) <= not ps2_key_release;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-- matrix representation
|
||||
|
||||
capshift_count_zero <= '1' when capshift_count = std_logic_vector(to_unsigned(0,capshift_count'length)) else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
capshift_count <= (others => '0');
|
||||
elsif ps2_key_valid = '1' and ps2_keymap_data(6) = '1' then
|
||||
if ps2_key_release = '0' then
|
||||
capshift_count <= capshift_count + 1;
|
||||
elsif capshift_count_zero = '0' then
|
||||
capshift_count <= capshift_count - 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
symshift_count_zero <= '1' when symshift_count = std_logic_vector(to_unsigned(0,symshift_count'length)) else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
symshift_count <= (others => '0');
|
||||
elsif ps2_key_valid = '1' and ps2_keymap_data(7) = '1' then
|
||||
if ps2_key_release = '0' then
|
||||
symshift_count <= symshift_count + 1;
|
||||
elsif symshift_count_zero = '0' then
|
||||
symshift_count <= symshift_count - 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or ps2_matrix_reset = '1' then
|
||||
matrix_state <= ((others => (others => '1')));
|
||||
elsif ps2_key_valid = '1' and ps2_keymap_data(2 downto 0) /= "111" then
|
||||
matrix_state(to_integer(unsigned(ps2_keymap_data(5 downto 3))))(to_integer(unsigned(ps2_keymap_data(2 downto 0)))) <= ps2_key_release;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- membrane scan
|
||||
|
||||
row_0_n <= '0' when i_membrane_row = "000" else '1';
|
||||
row_7_n <= '0' when i_membrane_row = "111" else '1';
|
||||
|
||||
o_membrane_col <= (matrix_state(to_integer(unsigned(i_membrane_row)))(6 downto 2)) &
|
||||
(matrix_state(to_integer(unsigned(i_membrane_row)))(1) and (row_7_n or symshift_count_zero)) &
|
||||
(matrix_state(to_integer(unsigned(i_membrane_row)))(0) and (row_0_n or capshift_count_zero));
|
||||
|
||||
-- ps2 keymap
|
||||
|
||||
keymap: entity work.keymaps
|
||||
port map
|
||||
(
|
||||
clock_i => i_CLK,
|
||||
addr_wr_i => i_keymap_addr,
|
||||
data_i => '0' & i_keymap_data,
|
||||
we_i => i_keymap_we,
|
||||
--
|
||||
addr_rd_i => ps2_key_extend & ps2_receive_data,
|
||||
data_o => ps2_keymap_data
|
||||
);
|
||||
|
||||
end architecture;
|
||||
244
rtl/mister/sdram.sv
Normal file
244
rtl/mister/sdram.sv
Normal file
@@ -0,0 +1,244 @@
|
||||
//============================================================================
|
||||
//
|
||||
// SDRAM controller
|
||||
// Copyright (C) 2021 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; 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 sdram
|
||||
(
|
||||
input clk,
|
||||
input init,
|
||||
|
||||
output reg [12:0] SDRAM_A,
|
||||
inout reg [15:0] SDRAM_DQ,
|
||||
output reg [1:0] SDRAM_BA,
|
||||
output reg SDRAM_DQML,
|
||||
output reg SDRAM_DQMH,
|
||||
output reg SDRAM_nWE,
|
||||
output reg SDRAM_nCAS,
|
||||
output reg SDRAM_nRAS,
|
||||
output SDRAM_nCS,
|
||||
output SDRAM_CKE,
|
||||
output SDRAM_CLK,
|
||||
|
||||
input [20:0] RAM_A_ADDR,
|
||||
input RAM_A_REQ,
|
||||
input RAM_A_RD_n,
|
||||
input [7:0] RAM_A_DI,
|
||||
output reg [7:0] RAM_A_DO,
|
||||
output reg RAM_A_WAIT,
|
||||
|
||||
input [20:0] RAM_B_ADDR,
|
||||
input RAM_B_REQ,
|
||||
output reg [7:0] RAM_B_DO
|
||||
);
|
||||
|
||||
assign SDRAM_nCS = 0;
|
||||
assign SDRAM_CKE = 1;
|
||||
assign {SDRAM_DQMH,SDRAM_DQML} = SDRAM_A[12:11];
|
||||
|
||||
localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@85MHz
|
||||
localparam BURST_LENGTH = 3'd0; // 0=1, 1=2, 2=4, 3=8, 7=full page
|
||||
localparam ACCESS_TYPE = 1'd0; // 0=sequential, 1=interleaved
|
||||
localparam CAS_LATENCY = 3'd2; // 2/3 allowed
|
||||
localparam OP_MODE = 2'd0; // only 0 (standard operation) allowed
|
||||
localparam NO_WRITE_BURST = 1'd1; // 0=write burst enabled, 1=only single access write
|
||||
|
||||
localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
|
||||
|
||||
localparam STATE_IDLE = 3'd0; // state to check the requests
|
||||
localparam STATE_START = STATE_IDLE+1'd1; // state in which a new command is started
|
||||
localparam STATE_CONT = STATE_START+RASCAS_DELAY;
|
||||
localparam STATE_READY = STATE_CONT+CAS_LATENCY+2'd2;
|
||||
localparam STATE_LAST = STATE_READY; // last state in cycle
|
||||
|
||||
reg [2:0] state;
|
||||
reg [22:0] a;
|
||||
reg [1:0] bank;
|
||||
reg [15:0] data;
|
||||
reg we;
|
||||
reg ram_req=0;
|
||||
|
||||
// access manager
|
||||
always @(posedge clk) begin
|
||||
reg old_ref;
|
||||
reg old_req;
|
||||
reg [20:1] last_a[2] = '{'1,'1};
|
||||
reg [15:0] last_data[2];
|
||||
reg [15:0] data_reg;
|
||||
reg ch0_busy;
|
||||
reg ch1_busy;
|
||||
reg [8:0] rfsh_cnt;
|
||||
|
||||
data_reg <= SDRAM_DQ;
|
||||
|
||||
if(RAM_A_REQ) RAM_A_WAIT <= 1;
|
||||
if(~&rfsh_cnt) rfsh_cnt <= rfsh_cnt + 1'd1;
|
||||
|
||||
if((old_req ^ RAM_B_REQ) && (last_a[1] == RAM_B_ADDR[20:1])) begin
|
||||
old_req <= RAM_B_REQ;
|
||||
RAM_B_DO <= RAM_B_ADDR[0] ? last_data[1][15:8] : last_data[1][7:0];
|
||||
end
|
||||
|
||||
if(state == STATE_IDLE && mode == MODE_NORMAL) begin
|
||||
ram_req <= 0;
|
||||
we <= 0;
|
||||
ch0_busy <= 0;
|
||||
ch1_busy <= 0;
|
||||
|
||||
if((old_req ^ RAM_B_REQ) && (last_a[1] != RAM_B_ADDR[20:1])) begin
|
||||
old_req <= RAM_B_REQ;
|
||||
{bank,a} <= RAM_B_ADDR;
|
||||
ram_req <= 1;
|
||||
last_a[1] <= RAM_B_ADDR[20:1];
|
||||
ch1_busy <= 1;
|
||||
state <= STATE_START;
|
||||
end
|
||||
else if(RAM_A_REQ | RAM_A_WAIT) begin
|
||||
we <= RAM_A_RD_n;
|
||||
{bank,a} <= RAM_A_ADDR;
|
||||
data <= {RAM_A_DI,RAM_A_DI};
|
||||
ram_req <= RAM_A_RD_n || (last_a[0] != RAM_A_ADDR[20:1]);
|
||||
last_a[0] <= RAM_A_RD_n ? '1 : RAM_A_ADDR[20:1];
|
||||
ch0_busy <= 1;
|
||||
state <= STATE_START;
|
||||
end
|
||||
else if(&rfsh_cnt) begin
|
||||
state <= STATE_START;
|
||||
end
|
||||
end
|
||||
|
||||
if(state == STATE_READY) begin
|
||||
if(~ram_req) rfsh_cnt <= 0;
|
||||
if(ch0_busy) begin
|
||||
ch0_busy <= 0;
|
||||
RAM_A_WAIT <= 0;
|
||||
if(ram_req) begin
|
||||
if(we) RAM_A_DO <= data[7:0];
|
||||
else begin
|
||||
RAM_A_DO <= a[0] ? data_reg[15:8] : data_reg[7:0];
|
||||
last_data[0] <= data_reg;
|
||||
end
|
||||
end
|
||||
else RAM_A_DO <= a[0] ? last_data[0][15:8] : last_data[0][7:0];
|
||||
end
|
||||
if(ch1_busy) begin
|
||||
ch1_busy <= 0;
|
||||
RAM_B_DO <= a[0] ? data_reg[15:8] : data_reg[7:0];
|
||||
last_data[1] <= data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
if(mode != MODE_NORMAL || state != STATE_IDLE || reset) begin
|
||||
state <= state + 1'd1;
|
||||
if(state == STATE_LAST) state <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
localparam MODE_NORMAL = 2'b00;
|
||||
localparam MODE_RESET = 2'b01;
|
||||
localparam MODE_LDM = 2'b10;
|
||||
localparam MODE_PRE = 2'b11;
|
||||
|
||||
initial reset = 5'h1f;
|
||||
|
||||
// initialization
|
||||
reg [1:0] mode;
|
||||
reg [4:0] reset=5'h1f;
|
||||
always @(posedge clk) begin
|
||||
reg init_old=0;
|
||||
init_old <= init;
|
||||
|
||||
if(init_old & ~init) reset <= 5'h1f;
|
||||
else if(state == STATE_LAST) begin
|
||||
if(reset != 0) begin
|
||||
reset <= reset - 5'd1;
|
||||
if(reset == 14) mode <= MODE_PRE;
|
||||
else if(reset == 3) mode <= MODE_LDM;
|
||||
else mode <= MODE_RESET;
|
||||
end
|
||||
else mode <= MODE_NORMAL;
|
||||
end
|
||||
end
|
||||
|
||||
localparam CMD_NOP = 3'b111;
|
||||
localparam CMD_ACTIVE = 3'b011;
|
||||
localparam CMD_READ = 3'b101;
|
||||
localparam CMD_WRITE = 3'b100;
|
||||
localparam CMD_BURST_TERMINATE = 3'b110;
|
||||
localparam CMD_PRECHARGE = 3'b010;
|
||||
localparam CMD_AUTO_REFRESH = 3'b001;
|
||||
localparam CMD_LOAD_MODE = 3'b000;
|
||||
|
||||
// SDRAM state machines
|
||||
always @(posedge clk) begin
|
||||
if(state == STATE_START) SDRAM_BA <= (mode == MODE_NORMAL) ? bank : 2'b00;
|
||||
|
||||
SDRAM_DQ <= 'Z;
|
||||
casex({ram_req,we,mode,state})
|
||||
{2'b1X, MODE_NORMAL, STATE_START}: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_ACTIVE;
|
||||
{2'b11, MODE_NORMAL, STATE_CONT }: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE, SDRAM_DQ} <= {CMD_WRITE, data};
|
||||
{2'b10, MODE_NORMAL, STATE_CONT }: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_READ;
|
||||
{2'b0X, MODE_NORMAL, STATE_START}: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_AUTO_REFRESH;
|
||||
|
||||
// init
|
||||
{2'bXX, MODE_LDM, STATE_START}: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_LOAD_MODE;
|
||||
{2'bXX, MODE_PRE, STATE_START}: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_PRECHARGE;
|
||||
|
||||
default: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_NOP;
|
||||
endcase
|
||||
|
||||
casex({ram_req,mode,state})
|
||||
{1'b1, MODE_NORMAL, STATE_START}: SDRAM_A <= a[13:1];
|
||||
{1'b1, MODE_NORMAL, STATE_CONT }: SDRAM_A <= {we & ~a[0], we & a[0], 2'b10, a[22:14]};
|
||||
|
||||
// init
|
||||
{1'bX, MODE_LDM, STATE_START}: SDRAM_A <= MODE;
|
||||
{1'bX, MODE_PRE, STATE_START}: SDRAM_A <= 13'b0010000000000;
|
||||
|
||||
default: SDRAM_A <= 13'b0000000000000;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
altddio_out
|
||||
#(
|
||||
.extend_oe_disable("OFF"),
|
||||
.intended_device_family("Cyclone V"),
|
||||
.invert_output("OFF"),
|
||||
.lpm_hint("UNUSED"),
|
||||
.lpm_type("altddio_out"),
|
||||
.oe_reg("UNREGISTERED"),
|
||||
.power_up_high("OFF"),
|
||||
.width(1)
|
||||
)
|
||||
sdramclk_ddr
|
||||
(
|
||||
.datain_h(1'b0),
|
||||
.datain_l(1'b1),
|
||||
.outclock(clk),
|
||||
.dataout(SDRAM_CLK),
|
||||
.aclr(1'b0),
|
||||
.aset(1'b0),
|
||||
.oe(1'b1),
|
||||
.outclocken(1'b1),
|
||||
.sclr(1'b0),
|
||||
.sset(1'b0)
|
||||
);
|
||||
|
||||
endmodule
|
||||
539
rtl/mister/zxnext_top.vhd
Normal file
539
rtl/mister/zxnext_top.vhd
Normal file
@@ -0,0 +1,539 @@
|
||||
|
||||
-- ZX Spectrum Next Issue 2 FPGA Top Level
|
||||
-- Copyright 2020 Alvin Albrecht and Fabio Belavenuto
|
||||
--
|
||||
-- TBBLUE Issue 2 Top - Fabio Belavenuto
|
||||
-- ZXNext Refactor - Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity zxnext_top is
|
||||
generic (
|
||||
g_machine_id : unsigned(7 downto 0) := X"DA"; -- MiSTer
|
||||
g_version : unsigned(7 downto 0) := X"31"; -- 3.01
|
||||
g_sub_version : unsigned(7 downto 0) := X"0A" -- .10
|
||||
);
|
||||
port (
|
||||
-- Clocks
|
||||
CLK_28 : in std_logic;
|
||||
CLK_14 : in std_logic;
|
||||
CLK_7 : in std_logic;
|
||||
|
||||
HW_RESET : in std_logic;
|
||||
|
||||
RAM_A_ADDR : out std_logic_vector(20 downto 0); -- 2MB memory space
|
||||
RAM_A_REQ : out std_logic; -- '1' indicates memory request on next rising edge
|
||||
RAM_A_RD_n : out std_logic; -- '0' for read, '1' for write
|
||||
RAM_A_DI : in std_logic_vector(7 downto 0); -- data read from memory
|
||||
RAM_A_DO : out std_logic_vector(7 downto 0); -- data written to memory
|
||||
RAM_A_WAIT : in std_logic := '0';
|
||||
|
||||
RAM_B_ADDR : out std_logic_vector(20 downto 0); -- 2MB memory space
|
||||
RAM_B_REQ : out std_logic; -- toggle indicates memory request
|
||||
RAM_B_DI : in std_logic_vector(7 downto 0); -- data read from memory
|
||||
|
||||
-- PS2
|
||||
ps2_key : in std_logic_vector(10 downto 0);
|
||||
ps2_mouse : in std_logic_vector(24 downto 0);
|
||||
ps2_mouse_ext : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- SD Card
|
||||
sd_cs0_n_o : out std_logic;
|
||||
sd_cs1_n_o : out std_logic;
|
||||
sd_sclk_o : out std_logic;
|
||||
sd_mosi_o : out std_logic;
|
||||
sd_miso_i : in std_logic := '1';
|
||||
|
||||
-- Joystick
|
||||
joy_left : in std_logic_vector(10 downto 0); -- active high X Z Y START A C B U D L R
|
||||
joy_right : in std_logic_vector(10 downto 0); -- active high X Z Y START A C B U D L R
|
||||
|
||||
-- Audio
|
||||
audio_L : out std_logic_vector(11 downto 0);
|
||||
audio_R : out std_logic_vector(11 downto 0);
|
||||
|
||||
-- K7
|
||||
ear_port_i : in std_logic := '1';
|
||||
mic_port_o : out std_logic;
|
||||
|
||||
-- VGA
|
||||
RGB : out std_logic_vector(8 downto 0); -- RGB333
|
||||
RGB_VS_n : out std_logic; -- vsync
|
||||
RGB_HS_n : out std_logic; -- hsync
|
||||
RGB_VB_n : out std_logic; -- vblank
|
||||
RGB_HB_n : out std_logic; -- hblank
|
||||
RGB_NTSC : out std_logic;
|
||||
|
||||
-- I2C (RTC)
|
||||
i2c_scl_o : out std_logic;
|
||||
i2c_sda_o : out std_logic;
|
||||
i2c_sda_i : in std_logic := '1';
|
||||
|
||||
uart_rx_i : in std_logic;
|
||||
uart_tx_o : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of zxnext_top is
|
||||
|
||||
-- resets
|
||||
|
||||
signal zxn_video_mode : std_logic_vector(2 downto 0);
|
||||
signal actual_video_mode : std_logic_vector(2 downto 0) := "000";
|
||||
|
||||
signal reset_counter : std_logic_vector(9 downto 0);
|
||||
signal reset : std_logic;
|
||||
|
||||
signal zxn_reset_hard : std_logic;
|
||||
signal zxn_reset_soft : std_logic;
|
||||
|
||||
-- clocks
|
||||
|
||||
signal CLK_i0 : std_logic;
|
||||
signal CLK_CPU : std_logic;
|
||||
signal q0 : std_logic;
|
||||
signal q0_enable : std_logic;
|
||||
signal q1 : std_logic;
|
||||
signal q1_enable : std_logic;
|
||||
|
||||
signal clk_28_div : std_logic_vector(17 downto 0);
|
||||
|
||||
signal CLK_28_PSG_EN : std_logic;
|
||||
signal CLK_28_JOY_EN : std_logic;
|
||||
signal CLK_28_MEMBRANE_EN : std_logic;
|
||||
|
||||
signal zxn_clock_contend : std_logic;
|
||||
signal zxn_clock_lsb : std_logic;
|
||||
signal zxn_cpu_speed : std_logic_vector(1 downto 0);
|
||||
signal zxn_cpu_speed2 : std_logic_vector(1 downto 0);
|
||||
|
||||
-- serial communication
|
||||
|
||||
signal zxn_i2c_scl : std_logic;
|
||||
|
||||
-- audio
|
||||
|
||||
signal zxn_audio_L_pre : std_logic_vector(12 downto 0);
|
||||
signal zxn_audio_R_pre : std_logic_vector(12 downto 0);
|
||||
|
||||
-- buttons, joystick, mouse, keyboard
|
||||
|
||||
signal zxn_joy_io_mode_en : std_logic;
|
||||
signal zxn_joy_io_mode_pin_7 : std_logic;
|
||||
|
||||
signal zxn_joy_left_type : std_logic_vector(2 downto 0);
|
||||
signal zxn_joy_right_type : std_logic_vector(2 downto 0);
|
||||
|
||||
signal zxn_mouse_control : std_logic_vector(2 downto 0);
|
||||
signal zxn_mouse_x : std_logic_vector(7 downto 0);
|
||||
signal zxn_mouse_y : std_logic_vector(7 downto 0);
|
||||
signal zxn_mouse_wheel : std_logic_vector(7 downto 0);
|
||||
signal zxn_mouse_button : std_logic_vector(2 downto 0);
|
||||
signal zxn_mouse_stb : std_logic;
|
||||
|
||||
signal ps2_kbd_col : std_logic_vector(6 downto 0);
|
||||
signal ps2_kbd_fn : std_logic_vector(11 downto 1);
|
||||
|
||||
signal zxn_keymap_addr : std_logic_vector(8 downto 0);
|
||||
signal zxn_keymap_dat : std_logic_vector(7 downto 0);
|
||||
signal zxn_keymap_we : std_logic;
|
||||
signal zxn_joymap_we : std_logic;
|
||||
|
||||
signal zxn_key_row : std_logic_vector(7 downto 0);
|
||||
signal zxn_key_col : std_logic_vector(4 downto 0);
|
||||
|
||||
signal zxn_cancel_extended_entries : std_logic;
|
||||
signal zxn_extended_keys : std_logic_vector(15 downto 0);
|
||||
|
||||
signal membrane_index : std_logic_vector(2 downto 0);
|
||||
signal membrane_stick_col : std_logic_vector(6 downto 0);
|
||||
|
||||
function mouse_scale(off : std_logic_vector(7 downto 0); scale : std_logic_vector(1 downto 0)) return std_logic_vector is
|
||||
begin
|
||||
-- avoid -1 value if negative off is less than scale
|
||||
case(scale) is
|
||||
when "00" =>
|
||||
return off;
|
||||
|
||||
when "01" =>
|
||||
if off <= X"FE" then
|
||||
return off(7) & off(7 downto 1);
|
||||
end if;
|
||||
|
||||
when "10" =>
|
||||
if off <= X"FC" then
|
||||
return off(7) & off(7) & off(7 downto 2);
|
||||
end if;
|
||||
|
||||
when "11" =>
|
||||
if off <= X"F8" then
|
||||
return off(7) & off(7) & off(7) & off(7 downto 3);
|
||||
end if;
|
||||
end case;
|
||||
|
||||
return (others => '0');
|
||||
end function;
|
||||
|
||||
begin
|
||||
|
||||
------------------------------------------------------------
|
||||
-- RESETS --------------------------------------------------
|
||||
------------------------------------------------------------
|
||||
|
||||
process (CLK_28)
|
||||
begin
|
||||
if rising_edge(CLK_28) then
|
||||
if zxn_video_mode /= actual_video_mode or (zxn_reset_soft or zxn_reset_hard or HW_RESET) = '1' then
|
||||
actual_video_mode <= zxn_video_mode;
|
||||
reset_counter <= (others => '1');
|
||||
reset <= '1';
|
||||
elsif reset_counter /= "0000000000" then
|
||||
reset_counter <= reset_counter - 1;
|
||||
else
|
||||
reset <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- CLOCKS --------------------------------------------------
|
||||
------------------------------------------------------------
|
||||
|
||||
-- cpu clock selection
|
||||
process (CLK_28)
|
||||
begin
|
||||
if rising_edge(CLK_28) then
|
||||
case(zxn_cpu_speed2) is
|
||||
when "00" =>
|
||||
if clk_28_div(1 downto 0) = "00" then
|
||||
if zxn_clock_lsb = '1' and zxn_clock_contend = '0' then
|
||||
CLK_i0 <= '0';
|
||||
elsif zxn_clock_lsb = '0' then
|
||||
CLK_i0 <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when "01" =>
|
||||
CLK_i0 <= clk_28_div(1);
|
||||
|
||||
when others =>
|
||||
CLK_i0 <= clk_28_div(0);
|
||||
end case;
|
||||
|
||||
if clk_28_div(1 downto 0) = "11" and zxn_cpu_speed /= "11" then
|
||||
zxn_cpu_speed2 <= zxn_cpu_speed;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(q1, CLK_i0)
|
||||
begin
|
||||
if (q1 = '1') then
|
||||
q0_enable <= '0';
|
||||
elsif falling_edge(CLK_i0) then
|
||||
q0_enable <= '1';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(q0, CLK_28)
|
||||
begin
|
||||
if (q0 = '1') then
|
||||
q1_enable <= '0';
|
||||
elsif falling_edge(CLK_28) then
|
||||
q1_enable <= '1';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
q0 <= not (zxn_cpu_speed(1) and zxn_cpu_speed(0)) and q0_enable when rising_edge(CLK_i0);
|
||||
q1 <= (zxn_cpu_speed(1) and zxn_cpu_speed(0)) and q1_enable when rising_edge(CLK_28);
|
||||
|
||||
CLK_CPU <= CLK_i0 when q0 = '1' else CLK_28 when q1 = '1' else '1';
|
||||
|
||||
-- Clock Enables
|
||||
clk_28_div <= clk_28_div + 1 when rising_edge(CLK_28);
|
||||
|
||||
CLK_28_PSG_EN <= '1' when clk_28_div(3 downto 0) = "1110" else '0'; -- AY clock enable @ 1.75MHz
|
||||
CLK_28_JOY_EN <= '1' when clk_28_div(6 downto 0) = ("111" & X"F") else '0'; -- stick step every 4.57us (pulse width = 9.14us for each side)
|
||||
CLK_28_MEMBRANE_EN <= '1' when clk_28_div(8 downto 7) = "11" and CLK_28_JOY_EN = '1' else '0'; -- complete scan every 2.5 scanlines (0.018ms per row)
|
||||
|
||||
------------------------------------------------------------
|
||||
-- BUTTONS, JOYSTICKS, MOUSE, KEYBOARD ---------------------
|
||||
------------------------------------------------------------
|
||||
|
||||
-- ps2 mouse
|
||||
|
||||
process (CLK_28)
|
||||
begin
|
||||
if rising_edge(CLK_28) then
|
||||
|
||||
zxn_mouse_stb <= ps2_mouse(24);
|
||||
if (zxn_mouse_stb xor ps2_mouse(24)) = '1' then
|
||||
zxn_mouse_x <= zxn_mouse_x + mouse_scale(ps2_mouse(15 downto 8), zxn_mouse_control(1 downto 0));
|
||||
zxn_mouse_y <= zxn_mouse_y + mouse_scale(ps2_mouse(23 downto 16), zxn_mouse_control(1 downto 0));
|
||||
zxn_mouse_wheel<= zxn_mouse_wheel + ps2_mouse_ext;
|
||||
end if;
|
||||
|
||||
if zxn_mouse_control(2) = '0' then
|
||||
zxn_mouse_button <= ps2_mouse(2 downto 0);
|
||||
else
|
||||
zxn_mouse_button <= (ps2_mouse(2) & ps2_mouse(0) & ps2_mouse(1));
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- ps2 keyboard
|
||||
|
||||
ps2_kbd_mod : entity work.ps2_keyb
|
||||
port map
|
||||
(
|
||||
i_CLK => CLK_28,
|
||||
i_reset => reset,
|
||||
|
||||
ps2_key => ps2_key,
|
||||
|
||||
-- membrane interaction
|
||||
i_membrane_row => membrane_index,
|
||||
o_membrane_col => ps2_kbd_col,
|
||||
|
||||
-- programmable keymap
|
||||
i_keymap_addr => zxn_keymap_addr,
|
||||
i_keymap_data => zxn_keymap_dat,
|
||||
i_keymap_we => zxn_keymap_we,
|
||||
|
||||
fn => ps2_kbd_fn -- F11:F1
|
||||
);
|
||||
|
||||
-- membrane keyboard
|
||||
|
||||
membrane_mod : entity work.membrane
|
||||
port map
|
||||
(
|
||||
i_CLK => CLK_28,
|
||||
i_CLK_EN => CLK_28_MEMBRANE_EN,
|
||||
|
||||
i_reset => reset,
|
||||
|
||||
i_rows => zxn_key_row,
|
||||
o_cols => zxn_key_col,
|
||||
|
||||
o_membrane_ridx => membrane_index,
|
||||
i_membrane_cols => membrane_stick_col and ps2_kbd_col,
|
||||
|
||||
i_cancel_extended_entries => zxn_cancel_extended_entries,
|
||||
o_extended_keys => zxn_extended_keys
|
||||
);
|
||||
|
||||
-- membrane joystick
|
||||
|
||||
membrane_stick_mod : entity work.membrane_stick
|
||||
port map
|
||||
(
|
||||
i_CLK => CLK_28,
|
||||
i_CLK_EN => CLK_28_MEMBRANE_EN,
|
||||
|
||||
i_reset => reset,
|
||||
|
||||
i_joy_en_n => zxn_joy_io_mode_en,
|
||||
|
||||
i_joy_left => joy_left,
|
||||
i_joy_left_type => zxn_joy_left_type,
|
||||
|
||||
i_joy_right => joy_right,
|
||||
i_joy_right_type => zxn_joy_right_type,
|
||||
|
||||
i_membrane_row => membrane_index,
|
||||
o_membrane_col => membrane_stick_col,
|
||||
|
||||
i_keymap_addr => zxn_keymap_addr(4 downto 0),
|
||||
i_keymap_data => zxn_keymap_dat(5 downto 0),
|
||||
i_keymap_we => zxn_joymap_we
|
||||
);
|
||||
|
||||
------------------------------------------------------------
|
||||
-- SERIAL COMMUNICATION ------------------------------------
|
||||
------------------------------------------------------------
|
||||
|
||||
-- i2c
|
||||
|
||||
i2c_scl_o <= zxn_i2c_scl;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- TBBLUE / ZXNEXT -----------------------------------------
|
||||
------------------------------------------------------------
|
||||
|
||||
-- F1 = hard reset (it seems removed and acts as soft reset now)
|
||||
-- F2 =
|
||||
-- F3 = toggle 50Hz / 60Hz display
|
||||
-- F4 =
|
||||
-- F5 =
|
||||
-- F6 =
|
||||
-- F7 =
|
||||
-- F8 = change cpu speed
|
||||
-- F9 =
|
||||
-- F10 = drive button (divmmc nmi)
|
||||
-- F11 = m1 button (multiface nmi)
|
||||
|
||||
zxnext : entity work.zxnext
|
||||
generic map
|
||||
(
|
||||
g_machine_id => g_machine_id,
|
||||
g_version => g_version,
|
||||
g_sub_version => g_sub_version
|
||||
)
|
||||
port map
|
||||
(
|
||||
-- CLOCK
|
||||
|
||||
i_CLK_28 => CLK_28,
|
||||
i_CLK_28_n => not CLK_28,
|
||||
i_CLK_14 => CLK_14,
|
||||
i_CLK_7 => CLK_7,
|
||||
i_CLK_CPU => CLK_CPU,
|
||||
i_CLK_PSG_EN => CLK_28_PSG_EN,
|
||||
|
||||
o_CPU_SPEED => zxn_cpu_speed,
|
||||
o_CPU_CONTEND => zxn_clock_contend,
|
||||
o_CPU_CLK_LSB => zxn_clock_lsb,
|
||||
|
||||
-- RESET
|
||||
|
||||
i_RESET => reset,
|
||||
|
||||
o_RESET_HARD => zxn_reset_hard,
|
||||
o_RESET_SOFT => zxn_reset_soft,
|
||||
|
||||
-- SPECIAL KEYS
|
||||
|
||||
i_SPKEY_FUNCTION => ps2_kbd_fn(10) & ps2_kbd_fn(11) & ps2_kbd_fn(8) & "0000" & ps2_kbd_fn(3) & '0' & ps2_kbd_fn(1),
|
||||
i_SPKEY_BUTTONS => ps2_kbd_fn(10) & ps2_kbd_fn(11),
|
||||
|
||||
-- MEMBRANE KEYBOARD
|
||||
|
||||
o_KBD_CANCEL => zxn_cancel_extended_entries,
|
||||
o_KBD_ROW => zxn_key_row,
|
||||
i_KBD_COL => zxn_key_col,
|
||||
i_KBD_EXTENDED_KEYS => zxn_extended_keys,
|
||||
|
||||
-- PS/2 KEYBOARD AND KEY JOYSTICK SETUP
|
||||
|
||||
o_KEYMAP_ADDR => zxn_keymap_addr,
|
||||
o_KEYMAP_DATA => zxn_keymap_dat,
|
||||
o_KEYMAP_WE => zxn_keymap_we,
|
||||
o_JOYMAP_WE => zxn_joymap_we,
|
||||
|
||||
-- JOYSTICK
|
||||
|
||||
i_JOY_LEFT => joy_left,
|
||||
i_JOY_RIGHT => joy_right,
|
||||
o_JOY_IO_MODE_EN => zxn_joy_io_mode_en,
|
||||
o_JOY_LEFT_TYPE => zxn_joy_left_type,
|
||||
o_JOY_RIGHT_TYPE => zxn_joy_right_type,
|
||||
|
||||
-- MOUSE
|
||||
|
||||
i_MOUSE_X => zxn_mouse_x,
|
||||
i_MOUSE_Y => zxn_mouse_y,
|
||||
i_MOUSE_BUTTON => zxn_mouse_button,
|
||||
i_MOUSE_WHEEL => zxn_mouse_wheel(3 downto 0),
|
||||
o_MOUSE_CONTROL => zxn_mouse_control,
|
||||
|
||||
-- I2C
|
||||
|
||||
i_I2C_SCL_n => zxn_i2c_scl,
|
||||
i_I2C_SDA_n => i2c_sda_i,
|
||||
o_I2C_SCL_n => zxn_i2c_scl,
|
||||
o_I2C_SDA_n => i2c_sda_o,
|
||||
|
||||
-- SPI
|
||||
|
||||
o_SPI_SS_SD1_n => sd_cs1_n_o,
|
||||
o_SPI_SS_SD0_n => sd_cs0_n_o,
|
||||
o_SPI_SCK => sd_sclk_o,
|
||||
o_SPI_MOSI => sd_mosi_o,
|
||||
i_SPI_SD_MISO => sd_miso_i,
|
||||
i_SPI_FLASH_MISO => '1',
|
||||
|
||||
-- UART
|
||||
|
||||
i_UART0_RX => uart_rx_i,
|
||||
o_UART0_TX => uart_tx_o,
|
||||
|
||||
-- VIDEO
|
||||
-- synchronized to i_CLK_14
|
||||
|
||||
o_RGB => RGB,
|
||||
o_RGB_VS_n => RGB_VS_n,
|
||||
o_RGB_HS_n => RGB_HS_n,
|
||||
o_RGB_VB_n => RGB_VB_n,
|
||||
o_RGB_HB_n => RGB_HB_n,
|
||||
o_VIDEO_MODE => zxn_video_mode,
|
||||
o_VIDEO_50_60 => RGB_NTSC,
|
||||
|
||||
-- AUDIO
|
||||
|
||||
i_AUDIO_EAR => ear_port_i,
|
||||
o_AUDIO_MIC => mic_port_o,
|
||||
o_AUDIO_L => zxn_audio_L_pre,
|
||||
o_AUDIO_R => zxn_audio_R_pre,
|
||||
|
||||
-- EXTERNAL SRAM (synchronized to i_CLK_28)
|
||||
-- memory transactions complete in one cycle, data read is registered but available asap
|
||||
|
||||
o_RAM_A_ADDR => RAM_A_ADDR,
|
||||
o_RAM_A_REQ => RAM_A_REQ,
|
||||
o_RAM_A_RD_n => RAM_A_RD_n,
|
||||
i_RAM_A_DI => RAM_A_DI,
|
||||
o_RAM_A_DO => RAM_A_DO,
|
||||
i_RAM_A_WAIT => RAM_A_WAIT,
|
||||
o_RAM_B_ADDR => RAM_B_ADDR,
|
||||
o_RAM_B_REQ_T => RAM_B_REQ,
|
||||
i_RAM_B_DI => RAM_B_DI,
|
||||
|
||||
-- EXPANSION BUS
|
||||
|
||||
i_BUS_DI => (others => '1'),
|
||||
i_BUS_WAIT_n => '1',
|
||||
i_BUS_NMI_n => '1',
|
||||
i_BUS_INT_n => '1',
|
||||
i_BUS_BUSREQ_n => '1',
|
||||
i_BUS_ROMCS_n => '1',
|
||||
i_BUS_IORQULA_n => '1',
|
||||
|
||||
-- ESP GPIO
|
||||
|
||||
i_ESP_GPIO_20 => (others => '1'),
|
||||
o_ESP_GPIO_0 => open,
|
||||
o_ESP_GPIO_0_EN => open,
|
||||
|
||||
-- PI GPIO
|
||||
|
||||
i_GPIO => (others => '1'),
|
||||
o_GPIO => open,
|
||||
o_GPIO_EN => open
|
||||
);
|
||||
|
||||
audio_L <= (others => '1') when zxn_audio_L_pre(12) = '1' else zxn_audio_L_pre(11 downto 0);
|
||||
audio_R <= (others => '1') when zxn_audio_R_pre(12) = '1' else zxn_audio_R_pre(11 downto 0);
|
||||
|
||||
end architecture;
|
||||
337
rtl/pll.qip
Normal file
337
rtl/pll.qip
Normal file
@@ -0,0 +1,337 @@
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_NAME "altera_pll"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_VERSION "17.0"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim"
|
||||
set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"]
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_QSYS_MODE "UNKNOWN"
|
||||
set_global_assignment -name SYNTHESIS_ONLY_QIP ON
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_NAME "cGxs"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA=="
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_INTERNAL "Off"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_VERSION "MTcuMA=="
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_NAME "cGxsXzAwMDI="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_INTERNAL "Off"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_VERSION "MTcuMA=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::SW50ZWdlci1OIFBMTA==::UExMIE1vZGU="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::ZmFsc2U=::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::dHJ1ZQ==::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::NQ==::TnVtYmVyIE9mIENsb2Nrcw=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::NQ==::bnVtYmVyX29mX2Nsb2Nrcw=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MjguMA==::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::NTY=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::MTAw::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::NTYuMA==::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::NTY=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::NTA=::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MTgwLjA=::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MTQuMA==::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::NTY=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MjAw::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MTgwLjA=::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::Ny4w::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::NTY=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::NDAw::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTEyLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::NTY=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MjU=::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::NTYuMA==::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTEyLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTEyLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::ZGVncmVlcw==::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::LTQzNTA=::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::LTkwLjA=::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MjguMDAwMDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::NTYuMDAwMDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MTQuMDAwMDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::Ny4wMDAwMDAgTUh6::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MTEyLjAwMDAwMCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTIgSGkgRGl2aWRlLEMtQ291bnRlci0yIExvdyBEaXZpZGUsQy1Db3VudGVyLTIgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0yIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTIgSW5wdXQgU291cmNlLEMtQ291bnRlci0yIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTMgSGkgRGl2aWRlLEMtQ291bnRlci0zIExvdyBEaXZpZGUsQy1Db3VudGVyLTMgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0zIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTMgSW5wdXQgU291cmNlLEMtQ291bnRlci0zIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTMgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTQgSGkgRGl2aWRlLEMtQ291bnRlci00IExvdyBEaXZpZGUsQy1Db3VudGVyLTQgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci00IFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTQgSW5wdXQgU291cmNlLEMtQ291bnRlci00IEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTQgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::MjgsMjgsMywyLGZhbHNlLGZhbHNlLGZhbHNlLHRydWUsMTAsMTAsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsNSw1LDEsMCxwaF9tdXhfY2xrLGZhbHNlLGZhbHNlLDIwLDIwLDEsMCxwaF9tdXhfY2xrLGZhbHNlLGZhbHNlLDQwLDQwLDEsMCxwaF9tdXhfY2xrLGZhbHNlLGZhbHNlLDMsMiwxLDAscGhfbXV4X2NsayxmYWxzZSx0cnVlLDIsMjAsMTAwMDAsNTYwLjAgTUh6LDEsbm9uZSxnbGIsbV9jbnQscGhfbXV4X2Nsayx0cnVl::UGFyYW1ldGVyIFZhbHVlcw=="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw="
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw="
|
||||
|
||||
set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"]
|
||||
set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll/pll_0002.v"]
|
||||
set_global_assignment -library "pll" -name QIP_FILE [file join $::quartus(qip_path) "pll/pll_0002.qip"]
|
||||
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "17.0"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_ENV "mwpim"
|
||||
261
rtl/pll.v
Normal file
261
rtl/pll.v
Normal file
@@ -0,0 +1,261 @@
|
||||
// megafunction wizard: %Altera PLL v17.0%
|
||||
// GENERATION: XML
|
||||
// pll.v
|
||||
|
||||
// Generated using ACDS version 17.0 602
|
||||
|
||||
`timescale 1 ps / 1 ps
|
||||
module 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 outclk_4, // outclk4.clk
|
||||
output wire locked // locked.export
|
||||
);
|
||||
|
||||
pll_0002 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
|
||||
.outclk_4 (outclk_4), // outclk4.clk
|
||||
.locked (locked) // locked.export
|
||||
);
|
||||
|
||||
endmodule
|
||||
// Retrieval info: <?xml version="1.0"?>
|
||||
//<!--
|
||||
// Generated by Altera MegaWizard Launcher Utility version 1.0
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
// ************************************************************
|
||||
// Copyright (C) 1991-2021 Altera Corporation
|
||||
// Any megafunction design, and related net list (encrypted or decrypted),
|
||||
// support information, device programming or simulation file, and any other
|
||||
// associated documentation or information provided by Altera or a partner
|
||||
// under Altera's Megafunction Partnership Program may be used only to
|
||||
// program PLD devices (but not masked PLD devices) from Altera. Any other
|
||||
// use of such megafunction design, net list, support information, device
|
||||
// programming or simulation file, or any other related documentation or
|
||||
// information is prohibited for any other purpose, including, but not
|
||||
// limited to modification, reverse engineering, de-compiling, or use with
|
||||
// any other silicon devices, unless such use is explicitly licensed under
|
||||
// a separate agreement with Altera or a megafunction partner. Title to
|
||||
// the intellectual property, including patents, copyrights, trademarks,
|
||||
// trade secrets, or maskworks, embodied in any such megafunction design,
|
||||
// net list, support information, device programming or simulation file, or
|
||||
// any other related documentation or information provided by Altera or a
|
||||
// megafunction partner, remains with Altera, the megafunction partner, or
|
||||
// their respective licensors. No other licenses, including any licenses
|
||||
// needed under any third party's intellectual property, are provided herein.
|
||||
//-->
|
||||
// Retrieval info: <instance entity-name="altera_pll" version="17.0" >
|
||||
// Retrieval info: <generic name="debug_print_output" value="false" />
|
||||
// Retrieval info: <generic name="debug_use_rbc_taf_method" value="false" />
|
||||
// Retrieval info: <generic name="device_family" value="Cyclone V" />
|
||||
// Retrieval info: <generic name="device" value="5CEBA2F17A7" />
|
||||
// Retrieval info: <generic name="gui_device_speed_grade" value="2" />
|
||||
// Retrieval info: <generic name="gui_pll_mode" value="Integer-N PLL" />
|
||||
// Retrieval info: <generic name="gui_reference_clock_frequency" value="50.0" />
|
||||
// Retrieval info: <generic name="gui_channel_spacing" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_operation_mode" value="direct" />
|
||||
// Retrieval info: <generic name="gui_feedback_clock" value="Global Clock" />
|
||||
// Retrieval info: <generic name="gui_fractional_cout" value="32" />
|
||||
// Retrieval info: <generic name="gui_dsm_out_sel" value="1st_order" />
|
||||
// Retrieval info: <generic name="gui_use_locked" value="true" />
|
||||
// Retrieval info: <generic name="gui_en_adv_params" value="false" />
|
||||
// Retrieval info: <generic name="gui_number_of_clocks" value="5" />
|
||||
// Retrieval info: <generic name="gui_multiply_factor" value="1" />
|
||||
// Retrieval info: <generic name="gui_frac_multiply_factor" value="1" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_n" value="1" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter0" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency0" value="28.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c0" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency0" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units0" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift0" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg0" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift0" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle0" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter1" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency1" value="56.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c1" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency1" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units1" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift1" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg1" value="180.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift1" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle1" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter2" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency2" value="14.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c2" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency2" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units2" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift2" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg2" value="180.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift2" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle2" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter3" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency3" value="7.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c3" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency3" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units3" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift3" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg3" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift3" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle3" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter4" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency4" value="112.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c4" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency4" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units4" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift4" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg4" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift4" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle4" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter5" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency5" value="56.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c5" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency5" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units5" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift5" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg5" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift5" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle5" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter6" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency6" value="112.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c6" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency6" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units6" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift6" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg6" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift6" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle6" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter7" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency7" value="112.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c7" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency7" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units7" value="degrees" />
|
||||
// Retrieval info: <generic name="gui_phase_shift7" value="-4350" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg7" value="-90.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift7" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle7" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter8" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency8" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c8" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency8" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units8" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift8" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg8" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift8" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle8" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter9" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency9" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c9" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency9" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units9" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift9" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg9" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift9" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle9" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter10" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency10" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c10" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency10" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units10" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift10" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg10" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift10" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle10" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter11" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency11" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c11" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency11" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units11" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift11" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg11" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift11" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle11" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter12" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency12" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c12" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency12" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units12" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift12" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg12" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift12" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle12" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter13" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency13" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c13" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency13" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units13" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift13" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg13" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift13" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle13" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter14" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency14" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c14" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency14" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units14" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift14" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg14" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift14" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle14" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter15" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency15" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c15" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency15" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units15" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift15" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg15" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift15" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle15" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter16" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency16" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c16" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency16" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units16" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift16" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg16" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift16" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle16" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter17" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency17" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c17" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency17" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units17" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift17" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg17" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift17" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle17" value="50" />
|
||||
// Retrieval info: <generic name="gui_pll_auto_reset" value="On" />
|
||||
// Retrieval info: <generic name="gui_pll_bandwidth_preset" value="Auto" />
|
||||
// Retrieval info: <generic name="gui_en_reconf" value="false" />
|
||||
// Retrieval info: <generic name="gui_en_dps_ports" value="false" />
|
||||
// Retrieval info: <generic name="gui_en_phout_ports" value="false" />
|
||||
// Retrieval info: <generic name="gui_phout_division" value="1" />
|
||||
// Retrieval info: <generic name="gui_mif_generate" value="false" />
|
||||
// Retrieval info: <generic name="gui_enable_mif_dps" value="false" />
|
||||
// Retrieval info: <generic name="gui_dps_cntr" value="C0" />
|
||||
// Retrieval info: <generic name="gui_dps_num" value="1" />
|
||||
// Retrieval info: <generic name="gui_dps_dir" value="Positive" />
|
||||
// Retrieval info: <generic name="gui_refclk_switch" value="false" />
|
||||
// Retrieval info: <generic name="gui_refclk1_frequency" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_switchover_mode" value="Automatic Switchover" />
|
||||
// Retrieval info: <generic name="gui_switchover_delay" value="0" />
|
||||
// Retrieval info: <generic name="gui_active_clk" value="false" />
|
||||
// Retrieval info: <generic name="gui_clk_bad" value="false" />
|
||||
// Retrieval info: <generic name="gui_enable_cascade_out" value="false" />
|
||||
// Retrieval info: <generic name="gui_cascade_outclk_index" value="0" />
|
||||
// Retrieval info: <generic name="gui_enable_cascade_in" value="false" />
|
||||
// Retrieval info: <generic name="gui_pll_cascading_mode" value="Create an adjpllin signal to connect with an upstream PLL" />
|
||||
// Retrieval info: </instance>
|
||||
// IPFS_FILES : pll.vo
|
||||
// RELATED_FILES: pll.v, pll_0002.v
|
||||
4
rtl/pll/pll_0002.qip
Normal file
4
rtl/pll/pll_0002.qip
Normal file
@@ -0,0 +1,4 @@
|
||||
set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*"
|
||||
|
||||
set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*"
|
||||
99
rtl/pll/pll_0002.v
Normal file
99
rtl/pll/pll_0002.v
Normal file
@@ -0,0 +1,99 @@
|
||||
`timescale 1ns/10ps
|
||||
module 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 'outclk4'
|
||||
output wire outclk_4,
|
||||
|
||||
// interface 'locked'
|
||||
output wire locked
|
||||
);
|
||||
|
||||
altera_pll #(
|
||||
.fractional_vco_multiplier("false"),
|
||||
.reference_clock_frequency("50.0 MHz"),
|
||||
.operation_mode("direct"),
|
||||
.number_of_clocks(5),
|
||||
.output_clock_frequency0("28.000000 MHz"),
|
||||
.phase_shift0("0 ps"),
|
||||
.duty_cycle0(50),
|
||||
.output_clock_frequency1("56.000000 MHz"),
|
||||
.phase_shift1("0 ps"),
|
||||
.duty_cycle1(50),
|
||||
.output_clock_frequency2("14.000000 MHz"),
|
||||
.phase_shift2("0 ps"),
|
||||
.duty_cycle2(50),
|
||||
.output_clock_frequency3("7.000000 MHz"),
|
||||
.phase_shift3("0 ps"),
|
||||
.duty_cycle3(50),
|
||||
.output_clock_frequency4("112.000000 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_4, outclk_3, outclk_2, outclk_1, outclk_0}),
|
||||
.locked (locked),
|
||||
.fboutclk ( ),
|
||||
.fbclk (1'b0),
|
||||
.refclk (refclk)
|
||||
);
|
||||
endmodule
|
||||
|
||||
1055
rtl/rom/bootrom.vhd
Normal file
1055
rtl/rom/bootrom.vhd
Normal file
File diff suppressed because it is too large
Load Diff
151
rtl/serial/fifop.vhd
Normal file
151
rtl/serial/fifop.vhd
Normal file
@@ -0,0 +1,151 @@
|
||||
|
||||
-- FIFO Manager
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity fifop is
|
||||
generic (
|
||||
constant DEPTH_BITS : positive := 9
|
||||
);
|
||||
port (
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
o_empty : out std_logic; -- held
|
||||
o_full_near : out std_logic; -- held (3/4)
|
||||
o_full_almost : out std_logic; -- held (full - 2 bytes)
|
||||
o_full : out std_logic; -- held
|
||||
|
||||
i_rd : in std_logic;
|
||||
o_raddr : out std_logic_vector(DEPTH_BITS-1 downto 0);
|
||||
|
||||
i_wr : in std_logic;
|
||||
o_waddr : out std_logic_vector(DEPTH_BITS-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of fifop is
|
||||
|
||||
signal stored : std_logic_vector(DEPTH_BITS downto 0);
|
||||
signal stored_delta : std_logic_vector(DEPTH_BITS downto 0);
|
||||
|
||||
signal empty : std_logic;
|
||||
signal full : std_logic;
|
||||
|
||||
signal rd_dly : std_logic;
|
||||
signal wr_dly : std_logic;
|
||||
|
||||
signal rd_advance : std_logic;
|
||||
signal wr_advance : std_logic;
|
||||
|
||||
signal rd_addr : std_logic_vector(DEPTH_BITS-1 downto 0);
|
||||
signal wr_addr : std_logic_vector(DEPTH_BITS-1 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- read from fifo
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
rd_dly <= '0';
|
||||
else
|
||||
rd_dly <= i_rd;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
rd_advance <= rd_dly and (not i_rd) and (not empty);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
rd_addr <= (others => '0');
|
||||
elsif rd_advance = '1' then
|
||||
rd_addr <= rd_addr + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- write to fifo
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
wr_dly <= '0';
|
||||
else
|
||||
wr_dly <= i_wr;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
wr_advance <= wr_dly and (not i_wr) and (not full);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
wr_addr <= (others => '0');
|
||||
elsif wr_advance = '1' then
|
||||
wr_addr <= wr_addr + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- track number of stored bytes
|
||||
|
||||
stored_delta <= std_logic_vector(to_unsigned(1,stored_delta'length)) when (rd_advance = '0' and wr_advance = '1') else
|
||||
std_logic_vector(to_unsigned(-1,stored_delta'length)) when (rd_advance = '1' and wr_advance = '0') else
|
||||
std_logic_vector(to_unsigned(0,stored_delta'length));
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
stored <= (others => '0');
|
||||
else
|
||||
stored <= stored + stored_delta;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- flags
|
||||
|
||||
empty <= '1' when stored = std_logic_vector(to_unsigned(0,stored'length)) else '0';
|
||||
full <= stored(DEPTH_BITS);
|
||||
|
||||
-- output
|
||||
|
||||
o_empty <= empty;
|
||||
o_full_near <= stored(DEPTH_BITS) or (stored(DEPTH_BITS-1) and stored(DEPTH_BITS-2));
|
||||
o_full_almost <= '1' when stored(DEPTH_BITS) = '1' or (stored(DEPTH_BITS-1 downto 1) = std_logic_vector(to_unsigned(-1,stored'length-1))) else '0';
|
||||
o_full <= full;
|
||||
|
||||
o_raddr <= rd_addr;
|
||||
o_waddr <= wr_addr;
|
||||
|
||||
end architecture;
|
||||
146
rtl/serial/spi_master.vhd
Normal file
146
rtl/serial/spi_master.vhd
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
-- SPI Master
|
||||
--
|
||||
-- Copyright 2009-2010 Mike Stirling
|
||||
-- Copyright 2020 Alvin Albrecht and Fabio Belavenuto
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- * Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- * Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- * Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
|
||||
-- Mike Stirling's original implementation:
|
||||
-- https://github.com/mikestir/fpga-spectrum/blob/master/spi.vhd
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity spi_master is
|
||||
port (
|
||||
clock_i : in std_logic;
|
||||
reset_i : in std_logic;
|
||||
|
||||
spi_sck_o : out std_logic;
|
||||
spi_mosi_o : out std_logic;
|
||||
spi_miso_i : in std_logic;
|
||||
|
||||
spi_mosi_wr_i : in std_logic;
|
||||
spi_mosi_dat_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
spi_miso_rd_i : in std_logic;
|
||||
spi_miso_dat_o : out std_logic_vector(7 downto 0);
|
||||
|
||||
spi_wait_n_o : out std_logic -- wait signal for dma
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of spi_master is
|
||||
|
||||
signal spi_begin : std_logic;
|
||||
signal counter_is_zero : std_logic;
|
||||
signal counter : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal sck : std_logic := '0';
|
||||
signal shift : std_logic_vector(8 downto 0) := (others => '1');
|
||||
signal miso_dat : std_logic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- start condition
|
||||
|
||||
spi_begin <= '1' when (spi_miso_rd_i = '1' or spi_mosi_wr_i = '1') and counter_is_zero = '1' else '0';
|
||||
|
||||
-- spi bit counter
|
||||
|
||||
counter_is_zero <= '1' when counter = X"0" else '0';
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if falling_edge(clock_i) then
|
||||
if reset_i = '1' then
|
||||
counter <= (others => '0');
|
||||
elsif counter_is_zero = '0' or spi_begin = '1' then
|
||||
counter <= counter + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if falling_edge(clock_i) then
|
||||
if reset_i = '1' then
|
||||
sck <= '0';
|
||||
else
|
||||
sck <= counter(0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- spi shift register
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if falling_edge(clock_i) then
|
||||
if reset_i = '1' then
|
||||
shift <= (others => '1');
|
||||
elsif spi_begin = '1' then
|
||||
if spi_miso_rd_i = '1' then
|
||||
shift <= (others => '1');
|
||||
else
|
||||
shift <= spi_mosi_dat_i & '1';
|
||||
end if;
|
||||
elsif counter_is_zero = '0' then
|
||||
if sck = '0' then
|
||||
shift(0) <= spi_miso_i;
|
||||
else
|
||||
shift <= shift(7 downto 0) & '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- miso data
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if counter_is_zero = '1' then
|
||||
miso_dat <= shift(7 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- connect pins
|
||||
|
||||
spi_sck_o <= sck;
|
||||
spi_mosi_o <= shift(8);
|
||||
spi_miso_dat_o <= miso_dat;
|
||||
|
||||
spi_wait_n_o <= '1' when counter_is_zero = '1' else '0';
|
||||
|
||||
end architecture;
|
||||
818
rtl/serial/uart.vhd
Normal file
818
rtl/serial/uart.vhd
Normal file
@@ -0,0 +1,818 @@
|
||||
-- ZX NEXT UARTS
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Implements both uarts in the ZX Next. The uarts share four registers,
|
||||
-- one of which is used to select which uart to communicate with.
|
||||
--
|
||||
-- Both uarts have a 512 byte Rx buffer and a 64 byte Tx buffer
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity uart is
|
||||
generic
|
||||
(
|
||||
NOISE_REJECTION_BITS : positive := 2 -- pulse widths less than 2^NOISE_REJECTION_BITS / i_CLK will be rejected
|
||||
);
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_CLK_n : in std_logic;
|
||||
|
||||
i_reset : in std_logic;
|
||||
i_reset_hard : in std_logic;
|
||||
|
||||
i_uart_reg : in std_logic_vector(1 downto 0); -- 00 = Rx, 01 = select, 10 = frame, 11 = tx
|
||||
|
||||
-- read from uart registers to cpu
|
||||
|
||||
i_uart_rd : in std_logic;
|
||||
o_cpu_d : out std_logic_vector(7 downto 0);
|
||||
|
||||
-- write from cpu to uart registers
|
||||
|
||||
i_uart_wr : in std_logic;
|
||||
i_cpu_d : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- uart 0
|
||||
|
||||
o_uart0_hwflow : out std_logic; -- 1 = hardware flow control enabled
|
||||
|
||||
i_Rx_0 : in std_logic;
|
||||
o_Rx_0_rtr_n : out std_logic; -- 0 = ready to receive bytes
|
||||
|
||||
o_Rx_0_avail : out std_logic; -- 1 = at least one byte in the Rx buffer
|
||||
o_Rx_0_near_full : out std_logic; -- 1 = Rx buffer is at least 3/4 full
|
||||
|
||||
o_Rx_0_err : out std_logic; -- 1 = framing or parity error
|
||||
o_Rx_0_err_break : out std_logic; -- 1 = break condition detected
|
||||
|
||||
o_Tx_0 : out std_logic;
|
||||
i_Tx_0_cts_n : in std_logic; -- 0 = clear to send bytes
|
||||
|
||||
o_Tx_0_empty : out std_logic; -- 1 = Tx buffer is empty
|
||||
|
||||
-- uart 1
|
||||
|
||||
o_uart1_hwflow : out std_logic; -- 1 = hardware flow control enabled
|
||||
|
||||
i_Rx_1 : in std_logic;
|
||||
o_Rx_1_rtr_n : out std_logic; -- 0 = ready to receive bytes
|
||||
|
||||
o_Rx_1_avail : out std_logic; -- 1 = at least one byte in the Rx buffer
|
||||
o_Rx_1_near_full : out std_logic; -- 1 = Rx buffer is at least 3/4 full
|
||||
|
||||
o_Rx_1_err : out std_logic; -- 1 = framing or parity error
|
||||
o_Rx_1_err_break : out std_logic; -- 1 = break condition detected
|
||||
|
||||
o_Tx_1 : out std_logic;
|
||||
i_Tx_1_cts_n : in std_logic; -- 1 = clear to send bytes
|
||||
|
||||
o_Tx_1_empty : out std_logic -- 1 = Tx buffer is empty
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of uart is
|
||||
|
||||
component sdpram_64_9 is
|
||||
PORT (
|
||||
|
||||
DPRA : IN STD_LOGIC_VECTOR(6-1 downto 0) := (OTHERS => '0');
|
||||
CLK : IN STD_LOGIC;
|
||||
WE : IN STD_LOGIC;
|
||||
DPO : OUT STD_LOGIC_VECTOR(9-1 downto 0);
|
||||
A : IN STD_LOGIC_VECTOR(6-1-(4*0*boolean'pos(6>4)) downto 0) := (OTHERS => '0');
|
||||
D : IN STD_LOGIC_VECTOR(9-1 downto 0) := (OTHERS => '0')
|
||||
|
||||
);
|
||||
end component;
|
||||
|
||||
signal uart_select_wr : std_logic;
|
||||
signal uart_frame_wr : std_logic;
|
||||
signal uart_tx_wr : std_logic;
|
||||
signal uart_tx_rd : std_logic;
|
||||
signal uart_rx_wr : std_logic;
|
||||
signal uart_rx_rd : std_logic;
|
||||
|
||||
signal uart0_tx_rd : std_logic;
|
||||
signal uart1_tx_rd : std_logic;
|
||||
signal uart0_tx_rd_d : std_logic;
|
||||
signal uart1_tx_rd_d : std_logic;
|
||||
signal uart0_tx_rd_fe : std_logic;
|
||||
signal uart1_tx_rd_fe : std_logic;
|
||||
|
||||
signal uart_select_r : std_logic;
|
||||
|
||||
signal uart0_prescalar_msb_r : std_logic_vector(2 downto 0) := (others => '0');
|
||||
signal uart1_prescalar_msb_r : std_logic_vector(2 downto 0) := (others => '0');
|
||||
|
||||
signal uart0_framing_r : std_logic_vector(7 downto 0) := X"18";
|
||||
signal uart1_framing_r : std_logic_vector(7 downto 0) := X"18";
|
||||
|
||||
signal uart0_prescalar_lsb_r : std_logic_vector(13 downto 0) := "00000011110011";
|
||||
signal uart1_prescalar_lsb_r : std_logic_vector(13 downto 0) := "00000011110011";
|
||||
|
||||
signal uart0_fifo_reset : std_logic;
|
||||
signal uart0_rx_rd : std_logic;
|
||||
signal uart0_tx_wr : std_logic;
|
||||
|
||||
signal uart0_rx_avail : std_logic;
|
||||
signal uart0_rx_byte : std_logic_vector(7 downto 0);
|
||||
signal uart0_rx_err_framing : std_logic;
|
||||
signal uart0_rx_err_parity : std_logic;
|
||||
signal uart0_rx_err_break : std_logic;
|
||||
|
||||
signal uart0_rx_fifo_empty : std_logic;
|
||||
signal uart0_rx_fifo_full_near : std_logic;
|
||||
signal uart0_rx_fifo_full_almost : std_logic;
|
||||
signal uart0_rx_fifo_full : std_logic;
|
||||
signal uart0_rx_fifo_raddr : std_logic_vector(8 downto 0);
|
||||
signal uart0_rx_fifo_waddr : std_logic_vector(8 downto 0);
|
||||
|
||||
signal uart0_tx_busy : std_logic;
|
||||
signal uart0_tx_fifo_empty : std_logic;
|
||||
signal uart0_tx_fifo_full : std_logic;
|
||||
signal uart0_tx_fifo_raddr : std_logic_vector(5 downto 0);
|
||||
signal uart0_tx_fifo_waddr : std_logic_vector(5 downto 0);
|
||||
|
||||
signal uart0_tx_byte : std_logic_vector(8 downto 0);
|
||||
signal uart0_tx_en : std_logic;
|
||||
signal uart0_tx_wr_d : std_logic;
|
||||
signal uart0_tx_fifo_we : std_logic;
|
||||
signal Tx_0 : std_logic;
|
||||
|
||||
signal uart0_status_rx_err_overflow : std_logic;
|
||||
signal uart0_status_rx_err_framing : std_logic;
|
||||
signal uart0_status_rx_near_full : std_logic;
|
||||
signal uart0_status_rx_avail : std_logic;
|
||||
signal uart0_status_tx_full : std_logic;
|
||||
signal uart0_status_tx_empty : std_logic;
|
||||
signal uart0_status_rx_err_break : std_logic;
|
||||
signal uart0_status_rx_err : std_logic;
|
||||
|
||||
signal uart1_fifo_reset : std_logic;
|
||||
signal uart1_rx_rd : std_logic;
|
||||
signal uart1_tx_wr : std_logic;
|
||||
|
||||
signal uart1_rx_avail : std_logic;
|
||||
signal uart1_rx_byte : std_logic_vector(7 downto 0);
|
||||
signal uart1_rx_err_framing : std_logic;
|
||||
signal uart1_rx_err_parity : std_logic;
|
||||
signal uart1_rx_err_break : std_logic;
|
||||
|
||||
signal uart1_rx_fifo_empty : std_logic;
|
||||
signal uart1_rx_fifo_full_near : std_logic;
|
||||
signal uart1_rx_fifo_full_almost : std_logic;
|
||||
signal uart1_rx_fifo_full : std_logic;
|
||||
signal uart1_rx_fifo_raddr : std_logic_vector(8 downto 0);
|
||||
signal uart1_rx_fifo_waddr : std_logic_vector(8 downto 0);
|
||||
|
||||
signal uart1_tx_busy : std_logic;
|
||||
signal uart1_tx_fifo_empty : std_logic;
|
||||
signal uart1_tx_fifo_full : std_logic;
|
||||
signal uart1_tx_fifo_raddr : std_logic_vector(5 downto 0);
|
||||
signal uart1_tx_fifo_waddr : std_logic_vector(5 downto 0);
|
||||
|
||||
signal uart1_tx_byte : std_logic_vector(8 downto 0);
|
||||
signal uart1_tx_en : std_logic;
|
||||
signal uart1_tx_wr_d : std_logic;
|
||||
signal uart1_tx_fifo_we : std_logic;
|
||||
signal Tx_1 : std_logic;
|
||||
|
||||
signal uart1_status_rx_err_overflow : std_logic;
|
||||
signal uart1_status_rx_err_framing : std_logic;
|
||||
signal uart1_status_rx_near_full : std_logic;
|
||||
signal uart1_status_rx_avail : std_logic;
|
||||
signal uart1_status_tx_full : std_logic;
|
||||
signal uart1_status_tx_empty : std_logic;
|
||||
signal uart1_status_rx_err_break : std_logic;
|
||||
signal uart1_status_rx_err : std_logic;
|
||||
|
||||
signal uart0_rx_o : std_logic_vector(8 downto 0);
|
||||
signal uart1_rx_o : std_logic_vector(8 downto 0);
|
||||
|
||||
signal uart0_rx_avail_d : std_logic;
|
||||
signal uart0_rx_byte_d : std_logic_vector(8 downto 0);
|
||||
signal uart0_rx_fifo_addr : std_logic_vector(8 downto 0);
|
||||
signal uart0_rx_fifo_we : std_logic;
|
||||
|
||||
signal uart1_rx_avail_d : std_logic;
|
||||
signal uart1_rx_byte_d : std_logic_vector(8 downto 0);
|
||||
signal uart1_rx_fifo_addr : std_logic_vector(8 downto 0);
|
||||
signal uart1_rx_fifo_we : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
-----------------
|
||||
-- UART REGISTERS
|
||||
-----------------
|
||||
|
||||
process (i_uart_reg, i_uart_rd, i_uart_wr)
|
||||
begin
|
||||
|
||||
uart_select_wr <= '0';
|
||||
uart_frame_wr <= '0';
|
||||
uart_tx_wr <= '0';
|
||||
uart_tx_rd <= '0';
|
||||
uart_rx_wr <= '0';
|
||||
uart_rx_rd <= '0';
|
||||
|
||||
case i_uart_reg is
|
||||
when "00" =>
|
||||
uart_rx_wr <= i_uart_wr;
|
||||
uart_rx_rd <= i_uart_rd;
|
||||
when "01" =>
|
||||
uart_select_wr <= i_uart_wr;
|
||||
when "10" =>
|
||||
uart_frame_wr <= i_uart_wr;
|
||||
when others =>
|
||||
uart_tx_wr <= i_uart_wr;
|
||||
uart_tx_rd <= i_uart_rd;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
uart0_tx_rd <= uart_tx_rd and not uart_select_r;
|
||||
uart1_tx_rd <= uart_tx_rd and uart_select_r;
|
||||
|
||||
process(i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
uart0_tx_rd_d <= uart0_tx_rd;
|
||||
uart1_tx_rd_d <= uart1_tx_rd;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart0_tx_rd_fe <= uart0_tx_rd_d and not uart_tx_rd;
|
||||
uart1_tx_rd_fe <= uart1_tx_rd_d and not uart_tx_rd;
|
||||
|
||||
-- uart select
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' then
|
||||
uart_select_r <= '0';
|
||||
if i_reset_hard = '1' then
|
||||
uart0_prescalar_msb_r <= (others => '0');
|
||||
uart1_prescalar_msb_r <= (others => '0');
|
||||
end if;
|
||||
elsif uart_select_wr = '1' then
|
||||
uart_select_r <= i_cpu_d(6);
|
||||
if i_cpu_d(4) = '1' then
|
||||
if i_cpu_d(6) = '0' then
|
||||
uart0_prescalar_msb_r <= i_cpu_d(2 downto 0);
|
||||
else
|
||||
uart1_prescalar_msb_r <= i_cpu_d(2 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- uart frame
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset_hard = '1' then
|
||||
uart0_framing_r <= X"18";
|
||||
uart1_framing_r <= X"18";
|
||||
elsif uart_frame_wr = '1' then
|
||||
if uart_select_r = '0' then
|
||||
uart0_framing_r <= i_cpu_d; -- reset, tx break, flow control, # bits (2), parity en, parity odd, stop bits
|
||||
else
|
||||
uart1_framing_r <= i_cpu_d; -- reset, tx break, flow control, # bits (2), parity en, parity odd, stop bits
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_uart0_hwflow <= uart0_framing_r(5);
|
||||
o_uart1_hwflow <= uart1_framing_r(5);
|
||||
|
||||
-- uart prescaler lsb
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset_hard = '1' then
|
||||
uart0_prescalar_lsb_r <= "00000011110011"; -- 115200 @ 28MHz system clock
|
||||
uart1_prescalar_lsb_r <= "00000011110011"; -- 115200 @ 28MHz system clock
|
||||
elsif uart_rx_wr = '1' then
|
||||
if uart_select_r = '0' then
|
||||
if i_cpu_d(7) = '0' then
|
||||
uart0_prescalar_lsb_r(6 downto 0) <= i_cpu_d(6 downto 0);
|
||||
else
|
||||
uart0_prescalar_lsb_r(13 downto 7) <= i_cpu_d(6 downto 0);
|
||||
end if;
|
||||
else
|
||||
if i_cpu_d(7) = '0' then
|
||||
uart1_prescalar_lsb_r(6 downto 0) <= i_cpu_d(6 downto 0);
|
||||
else
|
||||
uart1_prescalar_lsb_r(13 downto 7) <= i_cpu_d(6 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- read registers
|
||||
|
||||
process (uart_select_r, i_uart_reg, uart0_rx_o, uart0_prescalar_msb_r, uart0_framing_r, uart0_status_rx_err_break, uart0_status_rx_err_framing,
|
||||
uart0_status_tx_empty, uart0_status_rx_near_full, uart0_status_rx_err_overflow, uart0_status_tx_full, uart0_status_rx_avail,
|
||||
uart1_rx_o, uart1_prescalar_msb_r, uart1_framing_r, uart1_status_rx_err_break, uart1_status_rx_err_framing, uart1_status_tx_empty,
|
||||
uart1_status_rx_near_full, uart1_status_rx_err_overflow, uart1_status_tx_full, uart1_status_rx_avail)
|
||||
begin
|
||||
if uart_select_r = '0' then
|
||||
case i_uart_reg is
|
||||
when "00" =>
|
||||
if uart0_status_rx_avail = '1' then
|
||||
o_cpu_d <= uart0_rx_o(7 downto 0);
|
||||
else
|
||||
o_cpu_d <= (others => '0');
|
||||
end if;
|
||||
when "01" =>
|
||||
o_cpu_d <= "00000" & uart0_prescalar_msb_r;
|
||||
when "10" =>
|
||||
o_cpu_d <= uart0_framing_r;
|
||||
when others =>
|
||||
o_cpu_d <= uart0_status_rx_err_break & uart0_status_rx_err_framing & (uart0_rx_o(8) and uart0_status_rx_avail) & uart0_status_tx_empty &
|
||||
uart0_status_rx_near_full & uart0_status_rx_err_overflow & uart0_status_tx_full & uart0_status_rx_avail;
|
||||
end case;
|
||||
else
|
||||
case i_uart_reg is
|
||||
when "00" =>
|
||||
if uart1_status_rx_avail = '1' then
|
||||
o_cpu_d <= uart1_rx_o(7 downto 0);
|
||||
else
|
||||
o_cpu_d <= (others => '0');
|
||||
end if;
|
||||
when "01" =>
|
||||
o_cpu_d <= "01000" & uart1_prescalar_msb_r;
|
||||
when "10" =>
|
||||
o_cpu_d <= uart1_framing_r;
|
||||
when others =>
|
||||
o_cpu_d <= uart1_status_rx_err_break & uart1_status_rx_err_framing & (uart1_rx_o(8) and uart1_status_rx_avail) & uart1_status_tx_empty &
|
||||
uart1_status_rx_near_full & uart1_status_rx_err_overflow & uart1_status_tx_full & uart1_status_rx_avail;
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
---------
|
||||
-- UART 0
|
||||
---------
|
||||
|
||||
uart0_fifo_reset <= i_reset or uart0_framing_r(7);
|
||||
|
||||
uart0_rx_rd <= uart_rx_rd and not uart_select_r;
|
||||
uart0_tx_wr <= uart_tx_wr and not uart_select_r;
|
||||
|
||||
-- uart rx
|
||||
|
||||
uart0_rx_mod: entity work.uart_rx
|
||||
generic map
|
||||
(
|
||||
PRESCALER_BITS => 17,
|
||||
NOISE_REJECTION_BITS => NOISE_REJECTION_BITS
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_CLK => i_CLK,
|
||||
i_reset => i_reset,
|
||||
|
||||
i_frame => uart0_framing_r(7) & "00" & uart0_framing_r(4 downto 0), -- reset, pause, flow control (n/a here), # bits (2), parity en, parity odd, stop bits
|
||||
i_prescaler => uart0_prescalar_msb_r & uart0_prescalar_lsb_r,
|
||||
|
||||
o_Rx_avail => uart0_rx_avail, -- 1 = Rx has byte (one cycle)
|
||||
o_Rx_byte => uart0_rx_byte,
|
||||
|
||||
o_err_framing => uart0_rx_err_framing, -- one cycle
|
||||
o_err_parity => uart0_rx_err_parity, -- one cycle
|
||||
o_err_break => uart0_rx_err_break, -- held
|
||||
|
||||
i_Rx => i_Rx_0
|
||||
);
|
||||
|
||||
uart0_rx_fifop: entity work.fifop
|
||||
generic map
|
||||
(
|
||||
DEPTH_BITS => 9
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_CLK => i_CLK,
|
||||
i_reset => uart0_fifo_reset,
|
||||
|
||||
o_empty => uart0_rx_fifo_empty, -- held
|
||||
o_full_near => uart0_rx_fifo_full_near, -- held (3/4)
|
||||
o_full_almost => uart0_rx_fifo_full_almost, -- held (full - 2 bytes)
|
||||
o_full => uart0_rx_fifo_full, -- held
|
||||
|
||||
i_rd => uart0_rx_rd, -- read address adjusted on falling edge if not empty
|
||||
o_raddr => uart0_rx_fifo_raddr,
|
||||
|
||||
i_wr => uart0_rx_fifo_we, -- write address adjusted on falling edge if not full
|
||||
o_waddr => uart0_rx_fifo_waddr
|
||||
);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if uart0_fifo_reset = '1' then
|
||||
o_Rx_0_rtr_n <= uart0_framing_r(5);
|
||||
else
|
||||
o_Rx_0_rtr_n <= uart0_framing_r(5) and uart0_rx_fifo_full_almost;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- uart0 rx fifo memory is shared with uart1 rx in a single bram block due to size (below)
|
||||
|
||||
-- uart tx
|
||||
|
||||
uart0_tx_mod: entity work.uart_tx
|
||||
generic map
|
||||
(
|
||||
PRESCALER_BITS => 17
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_CLK => i_CLK,
|
||||
i_reset => i_reset,
|
||||
|
||||
i_frame => uart0_framing_r, -- reset, break, flow control, # bits (2), parity en, parity odd, stop bits
|
||||
i_prescaler => uart0_prescalar_msb_r & uart0_prescalar_lsb_r,
|
||||
|
||||
o_busy => uart0_tx_busy, -- '0' if Tx is ready for another byte
|
||||
|
||||
i_Tx_en => uart0_tx_en,
|
||||
i_Tx_byte => uart0_tx_byte(7 downto 0),
|
||||
|
||||
i_cts_n => i_Tx_0_cts_n, -- '0' if receiver is ready (only if flow control is enabled)
|
||||
|
||||
o_Tx => Tx_0
|
||||
);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
o_Tx_0 <= Tx_0;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart0_tx_fifop: entity work.fifop
|
||||
generic map
|
||||
(
|
||||
DEPTH_BITS => 6
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_CLK => i_CLK,
|
||||
i_reset => uart0_fifo_reset,
|
||||
|
||||
o_empty => uart0_tx_fifo_empty, -- held
|
||||
o_full_near => open,
|
||||
o_full_almost => open,
|
||||
o_full => uart0_tx_fifo_full, -- held
|
||||
|
||||
i_rd => uart0_tx_en, -- read address adjusted on falling edge if not empty
|
||||
o_raddr => uart0_tx_fifo_raddr,
|
||||
|
||||
i_wr => uart0_tx_fifo_we, -- write address adjusted on falling edge if not full
|
||||
o_waddr => uart0_tx_fifo_waddr
|
||||
);
|
||||
|
||||
-- cpu write, uart read
|
||||
|
||||
uart0_tx_fifo: sdpram_64_9 -- 64x8 needed but the natural size for xilinx is 64x9
|
||||
port map
|
||||
(
|
||||
-- async read (uart)
|
||||
DPRA => uart0_tx_fifo_raddr,
|
||||
DPO => uart0_tx_byte,
|
||||
-- sync write (cpu)
|
||||
CLK => i_CLK_n,
|
||||
WE => uart0_tx_fifo_we,
|
||||
A => uart0_tx_fifo_waddr,
|
||||
D => '0' & i_cpu_d
|
||||
);
|
||||
|
||||
uart0_tx_en <= '1' when uart0_tx_busy = '0' and uart0_tx_fifo_empty = '0' else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
uart0_tx_wr_d <= uart0_tx_wr;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart0_tx_fifo_we <= uart0_tx_wr and (not uart0_tx_wr_d) and not uart0_tx_fifo_full;
|
||||
|
||||
-- uart status
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if uart0_fifo_reset = '1' or uart0_tx_rd_fe = '1' then
|
||||
uart0_status_rx_err_overflow <= '0';
|
||||
uart0_status_rx_err_framing <= '0';
|
||||
else
|
||||
uart0_status_rx_err_overflow <= uart0_status_rx_err_overflow or (uart0_rx_avail and uart0_rx_avail_d);
|
||||
uart0_status_rx_err_framing <= uart0_status_rx_err_framing or uart0_rx_err_framing or uart0_rx_err_parity;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart0_status_rx_near_full <= uart0_rx_fifo_full_near;
|
||||
uart0_status_rx_avail <= not uart0_rx_fifo_empty;
|
||||
uart0_status_tx_full <= uart0_tx_fifo_full;
|
||||
uart0_status_tx_empty <= uart0_tx_fifo_empty and not uart0_tx_busy;
|
||||
uart0_status_rx_err_break <= uart0_rx_err_break;
|
||||
uart0_status_rx_err <= uart0_status_rx_err_overflow or uart0_status_rx_err_framing;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
o_Rx_0_near_full <= uart0_status_rx_near_full;
|
||||
o_Rx_0_avail <= uart0_status_rx_avail;
|
||||
|
||||
o_Rx_0_err_break <= uart0_status_rx_err_break;
|
||||
o_Rx_0_err <= uart0_status_rx_err;
|
||||
|
||||
o_Tx_0_empty <= uart0_tx_fifo_empty;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
---------
|
||||
-- UART 1
|
||||
---------
|
||||
|
||||
uart1_fifo_reset <= i_reset or uart1_framing_r(7);
|
||||
|
||||
uart1_rx_rd <= uart_rx_rd and uart_select_r;
|
||||
uart1_tx_wr <= uart_tx_wr and uart_select_r;
|
||||
|
||||
-- uart rx
|
||||
|
||||
uart1_rx_mod: entity work.uart_rx
|
||||
generic map
|
||||
(
|
||||
PRESCALER_BITS => 17,
|
||||
NOISE_REJECTION_BITS => NOISE_REJECTION_BITS
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_CLK => i_CLK,
|
||||
i_reset => i_reset,
|
||||
|
||||
i_frame => uart1_framing_r(7) & "00" & uart1_framing_r(4 downto 0), -- reset, pause, flow control (n/a here), # bits (2), parity en, parity odd, stop bits
|
||||
i_prescaler => uart1_prescalar_msb_r & uart1_prescalar_lsb_r,
|
||||
|
||||
o_Rx_avail => uart1_rx_avail, -- 1 = Rx has byte (one cycle)
|
||||
o_Rx_byte => uart1_rx_byte,
|
||||
|
||||
o_err_framing => uart1_rx_err_framing, -- one cycle
|
||||
o_err_parity => uart1_rx_err_parity, -- one cycle
|
||||
o_err_break => uart1_rx_err_break, -- held
|
||||
|
||||
i_Rx => i_Rx_1
|
||||
);
|
||||
|
||||
uart1_rx_fifop: entity work.fifop
|
||||
generic map
|
||||
(
|
||||
DEPTH_BITS => 9
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_CLK => i_CLK,
|
||||
i_reset => uart1_fifo_reset,
|
||||
|
||||
o_empty => uart1_rx_fifo_empty, -- held
|
||||
o_full_near => uart1_rx_fifo_full_near, -- held (3/4)
|
||||
o_full_almost => uart1_rx_fifo_full_almost, -- held (full - 2 bytes)
|
||||
o_full => uart1_rx_fifo_full, -- held
|
||||
|
||||
i_rd => uart1_rx_rd, -- read address adjusted on falling edge if not empty
|
||||
o_raddr => uart1_rx_fifo_raddr,
|
||||
|
||||
i_wr => uart1_rx_fifo_we, -- write address adjusted on falling edge if not full
|
||||
o_waddr => uart1_rx_fifo_waddr
|
||||
);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if uart1_fifo_reset = '1' then
|
||||
o_Rx_1_rtr_n <= uart1_framing_r(5);
|
||||
else
|
||||
o_Rx_1_rtr_n <= uart1_framing_r(5) and uart1_rx_fifo_full_almost;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- uart1 rx fifo memory is shared with uart0 rx in a single bram block due to size (below)
|
||||
|
||||
-- uart tx
|
||||
|
||||
uart1_tx_mod: entity work.uart_tx
|
||||
generic map
|
||||
(
|
||||
PRESCALER_BITS => 17
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_CLK => i_CLK,
|
||||
i_reset => i_reset,
|
||||
|
||||
i_frame => uart1_framing_r, -- reset, break, flow control, # bits (2), parity en, parity odd, stop bits
|
||||
i_prescaler => uart1_prescalar_msb_r & uart1_prescalar_lsb_r,
|
||||
|
||||
o_busy => uart1_tx_busy, -- '0' if Tx is ready for another byte
|
||||
|
||||
i_Tx_en => uart1_tx_en,
|
||||
i_Tx_byte => uart1_tx_byte(7 downto 0),
|
||||
|
||||
i_cts_n => i_Tx_1_cts_n, -- '0' if receiver is ready (only if flow control is enabled)
|
||||
|
||||
o_Tx => Tx_1
|
||||
);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
o_Tx_1 <= Tx_1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart1_tx_fifop: entity work.fifop
|
||||
generic map
|
||||
(
|
||||
DEPTH_BITS => 6
|
||||
)
|
||||
port map
|
||||
(
|
||||
i_CLK => i_CLK,
|
||||
i_reset => uart1_fifo_reset,
|
||||
|
||||
o_empty => uart1_tx_fifo_empty, -- held
|
||||
o_full_near => open,
|
||||
o_full_almost => open,
|
||||
o_full => uart1_tx_fifo_full, -- held
|
||||
|
||||
i_rd => uart1_tx_en, -- read address adjusted on falling edge if not empty
|
||||
o_raddr => uart1_tx_fifo_raddr,
|
||||
|
||||
i_wr => uart1_tx_fifo_we, -- write address adjusted on falling edge if not full
|
||||
o_waddr => uart1_tx_fifo_waddr
|
||||
);
|
||||
|
||||
-- cpu write, uart read
|
||||
|
||||
uart1_tx_fifo: sdpram_64_9 -- 64x8 needed but the natural size for xilinx is 64x9
|
||||
port map
|
||||
(
|
||||
-- async read (uart)
|
||||
DPRA => uart1_tx_fifo_raddr,
|
||||
DPO => uart1_tx_byte,
|
||||
-- sync write (cpu)
|
||||
CLK => i_CLK_n,
|
||||
WE => uart1_tx_fifo_we,
|
||||
A => uart1_tx_fifo_waddr,
|
||||
D => '0' & i_cpu_d
|
||||
);
|
||||
|
||||
uart1_tx_en <= '1' when uart1_tx_busy = '0' and uart1_tx_fifo_empty = '0' else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
uart1_tx_wr_d <= uart1_tx_wr;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart1_tx_fifo_we <= uart1_tx_wr and (not uart1_tx_wr_d) and not uart1_tx_fifo_full;
|
||||
|
||||
-- uart status
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if uart1_fifo_reset = '1' or uart1_tx_rd_fe = '1' then
|
||||
uart1_status_rx_err_overflow <= '0';
|
||||
uart1_status_rx_err_framing <= '0';
|
||||
else
|
||||
uart1_status_rx_err_overflow <= uart1_status_rx_err_overflow or (uart1_rx_avail and uart1_rx_avail_d);
|
||||
uart1_status_rx_err_framing <= uart1_status_rx_err_framing or uart1_rx_err_framing or uart1_rx_err_parity;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart1_status_rx_near_full <= uart1_rx_fifo_full_near;
|
||||
uart1_status_rx_avail <= not uart1_rx_fifo_empty;
|
||||
uart1_status_tx_full <= uart1_tx_fifo_full;
|
||||
uart1_status_tx_empty <= uart1_tx_fifo_empty and not uart1_tx_busy;
|
||||
uart1_status_rx_err_break <= uart1_rx_err_break;
|
||||
uart1_status_rx_err <= uart1_status_rx_err_overflow or uart1_status_rx_err_framing;
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
o_Rx_1_near_full <= uart1_status_rx_near_full;
|
||||
o_Rx_1_avail <= uart1_status_rx_avail;
|
||||
|
||||
o_Rx_1_err_break <= uart1_status_rx_err_break;
|
||||
o_Rx_1_err <= uart1_status_rx_err;
|
||||
|
||||
o_Tx_1_empty <= uart1_tx_fifo_empty;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------
|
||||
-- UART 0/1 RX FIFO MEMORY
|
||||
--------------------------
|
||||
|
||||
-- cpu read, uart write
|
||||
|
||||
uart_fifo_rx: entity work.tdpram
|
||||
generic map
|
||||
(
|
||||
addr_width_g => 10,
|
||||
data_width_g => 9
|
||||
)
|
||||
port map
|
||||
(
|
||||
-- uart 0
|
||||
clk_a_i => i_CLK,
|
||||
we_a_i => uart0_rx_fifo_we,
|
||||
addr_a_i => '0' & uart0_rx_fifo_addr,
|
||||
data_a_i => uart0_rx_byte_d,
|
||||
data_a_o => uart0_rx_o,
|
||||
-- uart 1
|
||||
clk_b_i => i_CLK,
|
||||
we_b_i => uart1_rx_fifo_we,
|
||||
addr_b_i => '1' & uart1_rx_fifo_addr,
|
||||
data_b_i => uart1_rx_byte_d,
|
||||
data_b_o => uart1_rx_o
|
||||
);
|
||||
|
||||
-- share a single bram unit, the two ports are independent
|
||||
-- cpu read must have priority because response must be within two cycles for dma
|
||||
|
||||
-- uart 0
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or uart0_rx_fifo_we = '1' then
|
||||
uart0_rx_avail_d <= '0';
|
||||
uart0_rx_byte_d <= (others => '0');
|
||||
elsif uart0_rx_avail = '1' and uart0_rx_avail_d = '0' then
|
||||
uart0_rx_avail_d <= '1';
|
||||
uart0_rx_byte_d <= uart0_status_rx_err & uart0_rx_byte;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart0_rx_fifo_addr <= uart0_rx_fifo_waddr when uart0_rx_fifo_we = '1' else uart0_rx_fifo_raddr;
|
||||
uart0_rx_fifo_we <= uart0_rx_avail_d and (not uart0_rx_fifo_full) and (not uart0_rx_rd) and (not uart0_tx_rd);
|
||||
|
||||
-- uart 1
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or uart1_rx_fifo_we = '1' then
|
||||
uart1_rx_avail_d <= '0';
|
||||
uart1_rx_byte_d <= (others => '0');
|
||||
elsif uart1_rx_avail = '1' and uart1_rx_avail_d = '0' then
|
||||
uart1_rx_avail_d <= '1';
|
||||
uart1_rx_byte_d <= uart1_status_rx_err & uart1_rx_byte;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uart1_rx_fifo_addr <= uart1_rx_fifo_waddr when uart1_rx_fifo_we = '1' else uart1_rx_fifo_raddr;
|
||||
uart1_rx_fifo_we <= uart1_rx_avail_d and (not uart1_rx_fifo_full) and (not uart1_rx_rd) and (not uart1_tx_rd);
|
||||
|
||||
end architecture;
|
||||
346
rtl/serial/uart_old.vhd
Normal file
346
rtl/serial/uart_old.vhd
Normal file
@@ -0,0 +1,346 @@
|
||||
|
||||
-- UART 8/1/N
|
||||
-- Copyright 2020 Victor Trucco and Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity uart is
|
||||
port
|
||||
(
|
||||
uart_prescaler_i : in std_logic_vector(16 downto 0);
|
||||
clock_i : in std_logic;
|
||||
reset_i : in std_logic;
|
||||
TX_start_i : in std_logic;
|
||||
TX_byte_i : in std_logic_vector(7 downto 0);
|
||||
TX_active_o : out std_logic;
|
||||
TX_out_o : out std_logic;
|
||||
TX_byte_finished_o : out std_logic;
|
||||
RX_in_i : in std_logic;
|
||||
RX_byte_finished_o : out std_logic;
|
||||
RX_byte_o : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end uart;
|
||||
|
||||
|
||||
architecture rtl of uart is
|
||||
|
||||
type tx_states is (STATE_TX_IDLE, STATE_TX_START, STATE_TX_DATA, STATE_TX_STOP, STATE_TX_FINISH);
|
||||
type rx_states is (STATE_RX_IDLE, STATE_RX_START, STATE_RX_DATA, STATE_RX_STOP, STATE_RX_FINISH);
|
||||
|
||||
signal rx_current_state_s : rx_states := STATE_RX_IDLE;
|
||||
signal tx_current_state_s : tx_states := STATE_TX_IDLE;
|
||||
|
||||
signal tx_clock_counter_s : integer range 0 to 131071; -- range 0 to 3000 := 0; -- ATTENTION: MAXIMUM OF TICKS TO WAIT!!!! 2916 for 9600 bps at 28mhz change here to slow speeds
|
||||
signal tx_bit_index_s : integer range 0 to 7 := 0;
|
||||
signal tx_data_s : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal tx_clock_period_expire : std_logic;
|
||||
signal tx_done_s : std_logic := '0';
|
||||
|
||||
signal rx_clock_counter_s : integer range 0 to 131071; -- range 0 to 3000 := 0; -- ATTENTION: MAXIMUM OF TICKS TO WAIT!!!! 2916 for 9600 bps at 28mhz change here to slow speeds
|
||||
signal rx_bit_index_s : integer range 0 to 7 := 0;
|
||||
signal rx_byte_s : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal rx_byte_finished_s : std_logic := '0';
|
||||
signal rx_data_s : std_logic;
|
||||
signal rx_clock_period_expire : std_logic;
|
||||
signal rx_clock_half_period_expire : std_logic;
|
||||
|
||||
signal Rx_in_db : std_logic;
|
||||
|
||||
signal ticks_per_bit_i : integer range 0 to 131071;
|
||||
signal ticks_per_bit_rx : integer range 0 to 131071;
|
||||
signal ticks_per_bit_tx : integer range 0 to 131071;
|
||||
|
||||
begin
|
||||
|
||||
ticks_per_bit_i <= to_integer(unsigned(uart_prescaler_i)) - 1;
|
||||
|
||||
-- OUTs
|
||||
|
||||
TX_byte_finished_o <= tx_done_s;
|
||||
RX_byte_finished_o <= rx_byte_finished_s;
|
||||
RX_byte_o <= rx_byte_s;
|
||||
|
||||
-- RX process
|
||||
|
||||
db : entity work.debounce
|
||||
generic map
|
||||
(
|
||||
INITIAL_STATE => '1',
|
||||
COUNTER_SIZE => 2 -- reject noise < 142ns
|
||||
)
|
||||
port map
|
||||
(
|
||||
clk_i => clock_i,
|
||||
clk_en_i => '1',
|
||||
button_i => RX_in_i,
|
||||
button_o => Rx_in_db
|
||||
);
|
||||
|
||||
rx_data_s <= Rx_in_db;
|
||||
|
||||
rx_clock_period_expire <= '1' when rx_clock_counter_s = ticks_per_bit_rx else '0';
|
||||
rx_clock_half_period_expire <= '1' when rx_clock_counter_s = ticks_per_bit_rx / 2 else '0';
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
|
||||
if reset_i = '1' then
|
||||
|
||||
rx_current_state_s <= STATE_RX_IDLE;
|
||||
|
||||
else
|
||||
|
||||
case rx_current_state_s is
|
||||
|
||||
when STATE_RX_IDLE =>
|
||||
|
||||
ticks_per_bit_rx <= ticks_per_bit_i;
|
||||
|
||||
rx_byte_finished_s <= '0';
|
||||
rx_clock_counter_s <= 0;
|
||||
rx_bit_index_s <= 0;
|
||||
|
||||
if rx_data_s = '0' then -- Wait for start bit
|
||||
rx_current_state_s <= STATE_RX_START;
|
||||
else
|
||||
rx_current_state_s <= STATE_RX_IDLE;
|
||||
end if;
|
||||
|
||||
|
||||
when STATE_RX_START =>
|
||||
|
||||
--wait for the middle of start bit
|
||||
|
||||
if rx_data_s = '1' then
|
||||
|
||||
rx_current_state_s <= STATE_RX_IDLE;
|
||||
|
||||
elsif rx_clock_half_period_expire = '1' then
|
||||
|
||||
rx_clock_counter_s <= 0;
|
||||
rx_current_state_s <= STATE_RX_DATA;
|
||||
|
||||
else
|
||||
|
||||
rx_clock_counter_s <= rx_clock_counter_s + 1;
|
||||
rx_current_state_s <= STATE_RX_START;
|
||||
|
||||
end if;
|
||||
|
||||
|
||||
|
||||
when STATE_RX_DATA =>
|
||||
|
||||
-- Wait for the correct number of cycles
|
||||
|
||||
if rx_clock_period_expire = '1' then
|
||||
|
||||
rx_clock_counter_s <= 0;
|
||||
rx_byte_s(rx_bit_index_s) <= rx_data_s;
|
||||
|
||||
-- Check if all the byte was sent
|
||||
if rx_bit_index_s = 7 then
|
||||
|
||||
rx_current_state_s <= STATE_RX_STOP;
|
||||
|
||||
else
|
||||
|
||||
rx_bit_index_s <= rx_bit_index_s + 1;
|
||||
rx_current_state_s <= STATE_RX_DATA;
|
||||
|
||||
end if;
|
||||
|
||||
else
|
||||
|
||||
rx_clock_counter_s <= rx_clock_counter_s + 1;
|
||||
rx_current_state_s <= STATE_RX_DATA;
|
||||
|
||||
end if;
|
||||
|
||||
|
||||
-- Stop bit = 1
|
||||
when STATE_RX_STOP =>
|
||||
|
||||
-- Wait for the correct number of cycles
|
||||
if rx_clock_period_expire = '1' then
|
||||
|
||||
if rx_data_s = '0' then
|
||||
|
||||
rx_current_state_s <= STATE_RX_IDLE;
|
||||
|
||||
else
|
||||
|
||||
rx_byte_finished_s <= '1';
|
||||
rx_current_state_s <= STATE_RX_FINISH;
|
||||
|
||||
end if;
|
||||
|
||||
else
|
||||
|
||||
rx_clock_counter_s <= rx_clock_counter_s + 1;
|
||||
rx_current_state_s <= STATE_RX_STOP;
|
||||
|
||||
end if;
|
||||
|
||||
|
||||
when STATE_RX_FINISH =>
|
||||
|
||||
rx_current_state_s <= STATE_RX_IDLE;
|
||||
rx_byte_finished_s <= '0';
|
||||
|
||||
when others =>
|
||||
|
||||
rx_current_state_s <= STATE_RX_IDLE;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- end RX process
|
||||
|
||||
-- TX process
|
||||
|
||||
tx_clock_period_expire <= '1' when tx_clock_counter_s = ticks_per_bit_tx else '0';
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
|
||||
if rising_edge(clock_i) then
|
||||
|
||||
if reset_i = '1' then
|
||||
|
||||
tx_current_state_s <= STATE_TX_IDLE;
|
||||
|
||||
else
|
||||
|
||||
case tx_current_state_s is
|
||||
|
||||
when STATE_TX_IDLE =>
|
||||
|
||||
ticks_per_bit_tx <= ticks_per_bit_i;
|
||||
|
||||
TX_active_o <= '0';
|
||||
TX_out_o <= '1'; -- Idle
|
||||
tx_done_s <= '0';
|
||||
tx_clock_counter_s <= 0;
|
||||
tx_bit_index_s <= 0;
|
||||
|
||||
if TX_start_i = '1' then
|
||||
|
||||
tx_data_s <= TX_byte_i;
|
||||
tx_current_state_s <= STATE_TX_START;
|
||||
|
||||
else
|
||||
|
||||
tx_current_state_s <= STATE_TX_IDLE;
|
||||
|
||||
end if;
|
||||
|
||||
-- Start bit = 0
|
||||
when STATE_TX_START =>
|
||||
|
||||
TX_active_o <= '1';
|
||||
TX_out_o <= '0';
|
||||
|
||||
-- Wait for the correct number of cycles
|
||||
|
||||
if tx_clock_period_expire = '1' then
|
||||
|
||||
tx_clock_counter_s <= 0;
|
||||
tx_current_state_s <= STATE_TX_DATA;
|
||||
|
||||
else
|
||||
|
||||
tx_clock_counter_s <= tx_clock_counter_s + 1;
|
||||
tx_current_state_s <= STATE_TX_START;
|
||||
|
||||
end if;
|
||||
|
||||
when STATE_TX_DATA =>
|
||||
|
||||
TX_out_o <= tx_data_s(tx_bit_index_s);
|
||||
|
||||
-- Wait for the correct number of cycles
|
||||
|
||||
if tx_clock_period_expire = '1' then
|
||||
|
||||
tx_clock_counter_s <= 0;
|
||||
|
||||
-- Send all bit from the byte
|
||||
if tx_bit_index_s = 7 then
|
||||
|
||||
tx_current_state_s <= STATE_TX_STOP;
|
||||
|
||||
else
|
||||
|
||||
tx_bit_index_s <= tx_bit_index_s + 1;
|
||||
tx_current_state_s <= STATE_TX_DATA;
|
||||
|
||||
end if;
|
||||
|
||||
else
|
||||
|
||||
tx_clock_counter_s <= tx_clock_counter_s + 1;
|
||||
tx_current_state_s <= STATE_TX_DATA;
|
||||
|
||||
end if;
|
||||
|
||||
-- Stop bit = 1
|
||||
when STATE_TX_STOP =>
|
||||
|
||||
TX_out_o <= '1';
|
||||
|
||||
-- Wait for the correct number of cycles
|
||||
|
||||
if tx_clock_period_expire = '1' then
|
||||
|
||||
tx_current_state_s <= STATE_TX_FINISH;
|
||||
|
||||
else
|
||||
|
||||
tx_clock_counter_s <= tx_clock_counter_s + 1;
|
||||
tx_current_state_s <= STATE_TX_STOP;
|
||||
|
||||
end if;
|
||||
|
||||
when STATE_TX_FINISH =>
|
||||
|
||||
TX_active_o <= '0';
|
||||
tx_done_s <= '1';
|
||||
tx_current_state_s <= STATE_TX_IDLE;
|
||||
|
||||
when others =>
|
||||
|
||||
tx_current_state_s <= STATE_TX_IDLE;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
--end of TX process
|
||||
|
||||
|
||||
end rtl;
|
||||
316
rtl/serial/uart_rx.vhd
Normal file
316
rtl/serial/uart_rx.vhd
Normal file
@@ -0,0 +1,316 @@
|
||||
-- UART RX
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- UART Receiver
|
||||
--
|
||||
-- Receiving:
|
||||
--
|
||||
-- Byte is available on o_Rx_byte when o_Rx_avail = 1 for one cycle.
|
||||
--
|
||||
-- Errors:
|
||||
--
|
||||
-- 1. o_err_framing = 1 for one cycle if expected stop bits are not present
|
||||
-- 2. o_err_parity = 1 for one cycle if there is a parity mismatch
|
||||
-- 3. o_err_break = 1 while a break condition exists
|
||||
--
|
||||
-- A received byte that is accompanied by an error is thrown away.
|
||||
--
|
||||
-- Prescaler:
|
||||
--
|
||||
-- One bit period is i_CLK divided by i_prescaler
|
||||
--
|
||||
-- Framing:
|
||||
--
|
||||
-- i_frame holds framing information:
|
||||
--
|
||||
-- bit 7 = 1 to immediately reset Rx to idle
|
||||
-- bit 6 = pause when in idle state
|
||||
-- bit 5 = enable hw flow control (not applicable here)
|
||||
-- bits 4:3 = # bits in frame (11 = 8, 10 = 7, 01 = 6, 00 = 5)
|
||||
-- bit 2 = parity enable
|
||||
-- bit 1 = 1 for odd parity, 0 for even parity
|
||||
-- bit 0 = 0 for one stop bit, 1 for two stop bits
|
||||
--
|
||||
-- The prescaler and frame bits 4:0 are sampled when the start bit is seen so
|
||||
-- that the Rx parameters remain constant through the receive.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity uart_rx is
|
||||
generic (
|
||||
PRESCALER_BITS : positive := 17; -- number of bits in bit period divisor
|
||||
NOISE_REJECTION_BITS : positive := 2 -- pulse widths less than 2^NOISE_REJECTION_BITS / i_CLK will be rejected
|
||||
);
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
-- configuration
|
||||
|
||||
i_frame : in std_logic_vector(7 downto 0); -- reset, pause, flow control (n/a here), # bits (2), parity en, parity odd, stop bits
|
||||
i_prescaler : in std_logic_vector(PRESCALER_BITS-1 downto 0); -- baud rate divisor
|
||||
|
||||
-- receive byte
|
||||
|
||||
o_Rx_avail : out std_logic; -- 1 = Rx has byte (one cycle)
|
||||
o_Rx_byte : out std_logic_vector(7 downto 0);
|
||||
|
||||
o_err_framing : out std_logic; -- one cycle
|
||||
o_err_parity : out std_logic; -- one cycle
|
||||
o_err_break : out std_logic; -- held as long as condition exists
|
||||
|
||||
-- serial in
|
||||
|
||||
i_Rx : in std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of uart_rx is
|
||||
|
||||
signal Rx : std_logic;
|
||||
signal Rx_d : std_logic;
|
||||
signal Rx_e : std_logic;
|
||||
|
||||
signal rx_frame_bits : std_logic_vector(1 downto 0);
|
||||
signal rx_frame_parity_en : std_logic;
|
||||
signal rx_frame_stop_bits : std_logic;
|
||||
signal rx_prescaler : std_logic_vector(PRESCALER_BITS-1 downto 0);
|
||||
|
||||
signal rx_shift : std_logic_vector(7 downto 0);
|
||||
|
||||
signal rx_timer_expired : std_logic;
|
||||
signal rx_timer : std_logic_vector(PRESCALER_BITS-1 downto 0);
|
||||
signal rx_timer_updated : std_logic;
|
||||
|
||||
signal rx_bit_count_expired : std_logic;
|
||||
signal rx_bit_count : std_logic_vector(2 downto 0);
|
||||
signal rx_parity : std_logic;
|
||||
|
||||
type state_t is (S_IDLE, S_START, S_BITS, S_PARITY, S_STOP_1, S_STOP_2, S_ERROR, S_PAUSE);
|
||||
signal state : state_t;
|
||||
signal state_next : state_t;
|
||||
|
||||
begin
|
||||
|
||||
-- NOISE REJECTION
|
||||
|
||||
db : entity work.debounce
|
||||
generic map
|
||||
(
|
||||
INITIAL_STATE => '1',
|
||||
COUNTER_SIZE => NOISE_REJECTION_BITS
|
||||
)
|
||||
port map
|
||||
(
|
||||
clk_i => i_CLK,
|
||||
clk_en_i => '1',
|
||||
button_i => i_Rx,
|
||||
button_o => Rx
|
||||
);
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
Rx_d <= Rx;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
Rx_e <= Rx xor Rx_d;
|
||||
|
||||
-- RECEIVE VARIABLES
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if falling_edge(i_CLK) then
|
||||
if state = S_IDLE then
|
||||
rx_frame_bits <= i_frame(4 downto 3);
|
||||
rx_frame_parity_en <= i_frame(2);
|
||||
rx_frame_stop_bits <= i_frame(0);
|
||||
rx_prescaler <= i_prescaler;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- shift register
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if state = S_START or state_next = S_ERROR then
|
||||
rx_shift <= (others => '1');
|
||||
elsif (state = S_BITS or state = S_ERROR) and rx_timer_expired = '1' then
|
||||
rx_shift <= Rx & rx_shift(7 downto 1);
|
||||
elsif state = S_STOP_1 and rx_timer_expired = '1' then
|
||||
case rx_frame_bits is
|
||||
when "10" => rx_shift <= '0' & rx_shift(7 downto 1);
|
||||
when "01" => rx_shift <= "00" & rx_shift(7 downto 2);
|
||||
when "00" => rx_shift <= "000" & rx_shift(7 downto 3);
|
||||
when others => rx_shift <= rx_shift;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- baud rate timer
|
||||
|
||||
rx_timer_expired <= '1' when rx_timer(PRESCALER_BITS-1 downto 1) = std_logic_vector(to_unsigned(0,PRESCALER_BITS-1)) else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if state = S_IDLE then
|
||||
rx_timer <= '0' & rx_prescaler(PRESCALER_BITS-1 downto 1);
|
||||
elsif rx_timer_expired = '1' then
|
||||
rx_timer <= rx_prescaler;
|
||||
rx_timer_updated <= '0';
|
||||
elsif state /= S_START and Rx_e = '1' and rx_timer_updated = '0' then
|
||||
rx_timer <= '0' & rx_prescaler(PRESCALER_BITS-1 downto 1);
|
||||
rx_timer_updated <= '1';
|
||||
else
|
||||
rx_timer <= rx_timer - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- bit counter & parity calculation
|
||||
|
||||
rx_bit_count_expired <= '1' when rx_bit_count = "000" else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if state = S_IDLE then
|
||||
rx_bit_count <= '1' & rx_frame_bits;
|
||||
rx_parity <= i_frame(1);
|
||||
elsif state = S_BITS and rx_timer_expired = '1' then
|
||||
rx_bit_count <= rx_bit_count - 1;
|
||||
rx_parity <= rx_parity xor Rx;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- STATE MACHINE
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or i_frame(7) = '1' then
|
||||
state <= S_PAUSE;
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (state, Rx, rx_timer_expired, rx_bit_count_expired, rx_frame_parity_en, rx_parity, rx_frame_stop_bits, i_frame)
|
||||
begin
|
||||
case state is
|
||||
when S_IDLE =>
|
||||
if i_frame(6) = '1' then
|
||||
state_next <= S_PAUSE;
|
||||
elsif Rx = '0' then
|
||||
state_next <= S_START;
|
||||
else
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when S_START =>
|
||||
if Rx = '1' then
|
||||
state_next <= S_IDLE;
|
||||
elsif rx_timer_expired = '1' then
|
||||
state_next <= S_BITS;
|
||||
else
|
||||
state_next <= S_START;
|
||||
end if;
|
||||
when S_BITS =>
|
||||
if rx_bit_count_expired = '0' or rx_timer_expired = '0' then
|
||||
state_next <= S_BITS;
|
||||
elsif rx_frame_parity_en = '1' then
|
||||
state_next <= S_PARITY;
|
||||
else
|
||||
state_next <= S_STOP_1;
|
||||
end if;
|
||||
when S_PARITY =>
|
||||
if rx_timer_expired = '0' then
|
||||
state_next <= S_PARITY;
|
||||
elsif Rx = rx_parity then
|
||||
state_next <= S_STOP_1;
|
||||
else
|
||||
state_next <= S_ERROR;
|
||||
end if;
|
||||
when S_STOP_1 =>
|
||||
if rx_timer_expired = '0' then
|
||||
state_next <= S_STOP_1;
|
||||
elsif Rx = '0' then
|
||||
state_next <= S_ERROR;
|
||||
elsif rx_frame_stop_bits = '1' then
|
||||
state_next <= S_STOP_2;
|
||||
else
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when S_STOP_2 =>
|
||||
if rx_timer_expired = '0' then
|
||||
state_next <= S_STOP_2;
|
||||
elsif Rx = '0' then
|
||||
state_next <= S_ERROR;
|
||||
else
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when S_ERROR =>
|
||||
if Rx = '0' then
|
||||
state_next <= S_ERROR;
|
||||
else
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when S_PAUSE =>
|
||||
if i_frame(6) = '1' or Rx = '0' then
|
||||
state_next <= S_PAUSE;
|
||||
else
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when others =>
|
||||
state_next <= S_IDLE;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- OUTPUT
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if (state = S_STOP_1 or state = S_STOP_2) and state_next = S_IDLE then
|
||||
o_Rx_avail <= '1';
|
||||
else
|
||||
o_Rx_avail <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_Rx_byte <= rx_shift;
|
||||
|
||||
o_err_parity <= '1' when state = S_PARITY and state_next = S_ERROR else '0';
|
||||
o_err_framing <= '1' when (state = S_STOP_1 or state = S_STOP_2) and state_next = S_ERROR else '0';
|
||||
o_err_break <= '1' when state = S_ERROR and rx_shift = "00000000" else '0';
|
||||
|
||||
end architecture;
|
||||
247
rtl/serial/uart_tx.vhd
Normal file
247
rtl/serial/uart_tx.vhd
Normal file
@@ -0,0 +1,247 @@
|
||||
-- UART TX
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- UART Transmitter
|
||||
--
|
||||
-- Sending:
|
||||
--
|
||||
-- 1. Wait for o_busy = 0 (break state will hold o_busy = 1)
|
||||
-- 2. Set i_Tx_byte = byte to send, i_Tx_en = 1 for one cycle
|
||||
--
|
||||
-- Prescaler:
|
||||
--
|
||||
-- One bit period is i_CLK divided by i_prescaler
|
||||
--
|
||||
-- Framing:
|
||||
--
|
||||
-- i_frame holds framing information:
|
||||
--
|
||||
-- bit 7 = 1 to immediately reset Tx to idle; any in flight byte is ended prematurely
|
||||
-- bit 6 = 1 to hold break (o_Tx = 0) while Tx is idle (cannot send in break state)
|
||||
-- bit 5 = 1 to enable flow control signal i_rdr (1 = receiver ready)
|
||||
-- bits 4:3 = # bits in frame (11 = 8, 10 = 7, 01 = 6, 00 = 5)
|
||||
-- bit 2 = parity enable
|
||||
-- bit 1 = 1 for odd parity, 0 for even parity
|
||||
-- bit 0 = 0 for one stop bit, 1 for two stop bits
|
||||
--
|
||||
-- The prescaler and frame bits 4:0 are sampled at the time a byte is sent to hold
|
||||
-- Tx parameters constant through a transmission.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity uart_tx is
|
||||
generic (
|
||||
PRESCALER_BITS : positive := 17 -- number of bits in bit period divisor
|
||||
);
|
||||
port
|
||||
(
|
||||
i_CLK : in std_logic;
|
||||
i_reset : in std_logic;
|
||||
|
||||
-- configuration
|
||||
|
||||
i_frame : in std_logic_vector(7 downto 0); -- reset, break, flow control, # bits (2), parity en, parity odd, stop bits
|
||||
i_prescaler : in std_logic_vector(PRESCALER_BITS-1 downto 0); -- baud rate divisor
|
||||
|
||||
-- send byte
|
||||
|
||||
o_busy : out std_logic; -- 0 = Tx ready for next byte
|
||||
|
||||
i_Tx_en : in std_logic; -- 1 = byte is being written (one cycle)
|
||||
i_Tx_byte : in std_logic_vector(7 downto 0);
|
||||
|
||||
i_cts_n : in std_logic; -- 0 = receiver is ready for Tx (if flow control is enabled)
|
||||
|
||||
-- serial out
|
||||
|
||||
o_Tx : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of uart_tx is
|
||||
|
||||
signal tx_frame_parity_en : std_logic;
|
||||
signal tx_frame_stop_bits : std_logic;
|
||||
signal tx_prescaler : std_logic_vector(PRESCALER_BITS-1 downto 0);
|
||||
|
||||
signal tx_shift : std_logic_vector(7 downto 0);
|
||||
|
||||
signal tx_timer_expired : std_logic;
|
||||
signal tx_timer : std_logic_vector(PRESCALER_BITS-1 downto 0);
|
||||
|
||||
signal tx_bit_count_expired : std_logic;
|
||||
signal tx_bit_count : std_logic_vector(2 downto 0);
|
||||
signal tx_parity : std_logic;
|
||||
|
||||
type state_t is (S_IDLE, S_RTR, S_START, S_BITS, S_PARITY, S_STOP_1, S_STOP_2);
|
||||
signal state : state_t;
|
||||
signal state_next : state_t;
|
||||
|
||||
begin
|
||||
|
||||
-- TRANSMISSION VARIABLES
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if falling_edge(i_CLK) then
|
||||
if state = S_IDLE then
|
||||
tx_frame_parity_en <= i_frame(2);
|
||||
tx_frame_stop_bits <= i_frame(0);
|
||||
tx_prescaler <= i_prescaler;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- shift register
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if state = S_IDLE then
|
||||
tx_shift <= i_Tx_byte;
|
||||
elsif state = S_BITS and tx_timer_expired = '1' then
|
||||
tx_shift <= '0' & tx_shift(7 downto 1);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- baud rate timer
|
||||
|
||||
tx_timer_expired <= '1' when tx_timer(PRESCALER_BITS-1 downto 1) = std_logic_vector(to_unsigned(0,PRESCALER_BITS-1)) else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if (state /= state_next) or tx_timer_expired = '1' then
|
||||
tx_timer <= tx_prescaler;
|
||||
else
|
||||
tx_timer <= tx_timer - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- bit counter & parity calculation
|
||||
|
||||
tx_bit_count_expired <= '1' when tx_bit_count = "000" else '0';
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if state = S_IDLE then
|
||||
tx_bit_count <= '1' & i_frame(4 downto 3);
|
||||
tx_parity <= i_frame(1);
|
||||
elsif state = S_BITS and tx_timer_expired = '1' then
|
||||
tx_bit_count <= tx_bit_count - 1;
|
||||
tx_parity <= tx_parity xor tx_shift(0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- STATE MACHINE
|
||||
|
||||
process (i_CLK)
|
||||
begin
|
||||
if rising_edge(i_CLK) then
|
||||
if i_reset = '1' or i_frame(7) = '1' then
|
||||
state <= S_IDLE;
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (state, i_frame, i_Tx_en, i_cts_n, tx_timer_expired, tx_bit_count_expired, tx_frame_parity_en, tx_frame_stop_bits)
|
||||
begin
|
||||
case state is
|
||||
when S_IDLE =>
|
||||
if i_frame(6) = '1' or i_Tx_en = '0' then
|
||||
state_next <= S_IDLE;
|
||||
elsif i_Tx_en = '1' and (i_cts_n = '0' or i_frame(5) = '0') then
|
||||
state_next <= S_START;
|
||||
elsif i_Tx_en = '1' and (i_cts_n = '1' and i_frame(5) = '1') then
|
||||
state_next <= S_RTR;
|
||||
else
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when S_RTR =>
|
||||
if i_cts_n = '1' and i_frame(5) = '1' then
|
||||
state_next <= S_RTR;
|
||||
else
|
||||
state_next <= S_START;
|
||||
end if;
|
||||
when S_START =>
|
||||
if tx_timer_expired = '1' then
|
||||
state_next <= S_BITS;
|
||||
else
|
||||
state_next <= S_START;
|
||||
end if;
|
||||
when S_BITS =>
|
||||
if tx_bit_count_expired = '0' or tx_timer_expired = '0' then
|
||||
state_next <= S_BITS;
|
||||
elsif tx_frame_parity_en = '1' then
|
||||
state_next <= S_PARITY;
|
||||
else
|
||||
state_next <= S_STOP_1;
|
||||
end if;
|
||||
when S_PARITY =>
|
||||
if tx_timer_expired = '1' then
|
||||
state_next <= S_STOP_1;
|
||||
else
|
||||
state_next <= S_PARITY;
|
||||
end if;
|
||||
when S_STOP_1 =>
|
||||
if tx_timer_expired = '0' then
|
||||
state_next <= S_STOP_1;
|
||||
elsif tx_frame_stop_bits = '1' then
|
||||
state_next <= S_STOP_2;
|
||||
else
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when S_STOP_2 =>
|
||||
if tx_timer_expired = '0' then
|
||||
state_next <= S_STOP_2;
|
||||
else
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when others =>
|
||||
state_next <= S_IDLE;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- OUTPUT
|
||||
|
||||
o_busy <= '1' when state /= S_IDLE or i_frame(7) = '1' or i_frame(6) = '1' else '0';
|
||||
|
||||
process (state, i_frame, tx_shift, tx_parity)
|
||||
begin
|
||||
case state is
|
||||
when S_IDLE => o_Tx <= not i_frame(6);
|
||||
when S_START => o_Tx <= '0';
|
||||
when S_BITS => o_Tx <= tx_shift(0);
|
||||
when S_PARITY => o_Tx <= tx_parity;
|
||||
when others => o_Tx <= '1';
|
||||
end case;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
216
rtl/video/layer2.vhd
Normal file
216
rtl/video/layer2.vhd
Normal file
@@ -0,0 +1,216 @@
|
||||
|
||||
-- ZX Spectrum Next Layer 2 Bitmap Display
|
||||
-- Copyright 2020 Alvin Albrecht and Victor Trucco
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity layer2 is
|
||||
port (
|
||||
i_CLK_7 : in std_logic; -- pixel clock
|
||||
i_CLK_28 : in std_logic;
|
||||
|
||||
i_sc : in std_logic_vector(1 downto 0); -- 28MHz subcount
|
||||
|
||||
i_phc : in std_logic_vector(8 downto 0); -- current x coordinate
|
||||
i_pvc : in std_logic_vector(8 downto 0); -- current y coordinate
|
||||
|
||||
i_whc : in std_logic_vector(8 downto 0); -- current wide x coordinate
|
||||
i_wvc : in std_logic_vector(8 downto 0); -- current wide y coordinate
|
||||
|
||||
i_layer2_en : in std_logic;
|
||||
i_resolution : in std_logic_vector(1 downto 0); -- 00 = 256x192, 01 = 320x256, 1X = 640x256x4
|
||||
i_palette_offset : in std_logic_vector(3 downto 0);
|
||||
|
||||
i_scroll_x : in std_logic_vector(8 downto 0);
|
||||
i_scroll_y : in std_logic_vector(7 downto 0);
|
||||
|
||||
i_clip_x1 : in std_logic_vector(7 downto 0);
|
||||
i_clip_x2 : in std_logic_vector(7 downto 0);
|
||||
i_clip_y1 : in std_logic_vector(7 downto 0);
|
||||
i_clip_y2 : in std_logic_vector(7 downto 0);
|
||||
|
||||
i_layer2_active_bank : in std_logic_vector(6 downto 0); -- starting 16K bank
|
||||
|
||||
o_layer2_sram_addr : out std_logic_vector(20 downto 0);
|
||||
o_layer2_req_t : out std_logic;
|
||||
i_layer2_sram_di : in std_logic_vector(7 downto 0);
|
||||
|
||||
o_layer2_en : out std_logic;
|
||||
o_layer2_pixel : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of layer2 is
|
||||
|
||||
signal layer2_en_q : std_logic;
|
||||
signal layer2_resolution_q : std_logic_vector(1 downto 0);
|
||||
signal layer2_scroll_x_q : std_logic_vector(8 downto 0);
|
||||
signal layer2_scroll_y_q : std_logic_vector(7 downto 0);
|
||||
signal layer2_palette_offset_q : std_logic_vector(3 downto 0);
|
||||
signal layer2_active_bank_q : std_logic_vector(6 downto 0);
|
||||
|
||||
signal clip_x1_q : std_logic_vector(8 downto 0);
|
||||
signal clip_x2_q : std_logic_vector(8 downto 0);
|
||||
signal clip_y1_q : std_logic_vector(7 downto 0);
|
||||
signal clip_y2_q : std_logic_vector(7 downto 0);
|
||||
|
||||
signal layer2_wide_res : std_logic;
|
||||
signal hc : std_logic_vector(8 downto 0);
|
||||
signal hc_eff : std_logic_vector(8 downto 0);
|
||||
signal vc_eff : std_logic_vector(8 downto 0);
|
||||
signal x_pre : std_logic_vector(9 downto 0);
|
||||
signal x : std_logic_vector(8 downto 0);
|
||||
signal y_pre : std_logic_vector(8 downto 0);
|
||||
signal y : std_logic_vector(7 downto 0);
|
||||
signal layer2_addr : std_logic_vector(16 downto 0);
|
||||
|
||||
signal hc_valid : std_logic;
|
||||
signal vc_valid : std_logic;
|
||||
signal layer2_clip_en : std_logic;
|
||||
|
||||
signal layer2_bank_eff : std_logic_vector(7 downto 0);
|
||||
signal layer2_addr_eff : std_logic_vector(21 downto 0);
|
||||
signal layer2_en : std_logic;
|
||||
signal layer2_req_t : std_logic;
|
||||
signal layer2_sram_addr : std_logic_vector(20 downto 0);
|
||||
signal layer2_pixel_qq : std_logic_vector(7 downto 0);
|
||||
|
||||
signal layer2_en_qq : std_logic;
|
||||
signal layer2_hires_qq : std_logic;
|
||||
signal layer2_pixel_pre : std_logic_vector(7 downto 0);
|
||||
signal layer2_pixel : std_logic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- capture settings for pixel period
|
||||
|
||||
process (i_CLK_7)
|
||||
begin
|
||||
if rising_edge(i_CLK_7) then
|
||||
|
||||
layer2_en_q <= i_layer2_en;
|
||||
|
||||
layer2_resolution_q <= i_resolution;
|
||||
|
||||
layer2_scroll_x_q <= i_scroll_x;
|
||||
layer2_scroll_y_q <= i_scroll_y;
|
||||
|
||||
layer2_palette_offset_q <= i_palette_offset;
|
||||
|
||||
layer2_active_bank_q <= i_layer2_active_bank;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK_7)
|
||||
begin
|
||||
if rising_edge(i_CLK_7) then
|
||||
|
||||
if i_resolution = "00" then
|
||||
clip_x1_q <= '0' & i_clip_x1;
|
||||
clip_x2_q <= '0' & i_clip_x2;
|
||||
else
|
||||
clip_x1_q <= i_clip_x1 & '0';
|
||||
clip_x2_q <= i_clip_x2 & '1';
|
||||
end if;
|
||||
|
||||
clip_y1_q <= i_clip_y1;
|
||||
clip_y2_q <= i_clip_y2;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- generate layer 2 address one x pixel ahead
|
||||
|
||||
layer2_wide_res <= '0' when layer2_resolution_q = "00" else '1';
|
||||
|
||||
hc <= i_phc when layer2_wide_res = '0' else i_whc;
|
||||
hc_eff <= hc + 1;
|
||||
|
||||
vc_eff <= i_pvc when layer2_wide_res = '0' else i_wvc;
|
||||
|
||||
x_pre <= ('0' & hc_eff) + ('0' & layer2_scroll_x_q);
|
||||
x(8 downto 6) <= x_pre(8 downto 6) when (layer2_wide_res = '0' or (x_pre(9) = '0' and (x_pre(8) = '0' or x_pre(7 downto 6) = "00"))) else (x_pre(8 downto 6) + "011");
|
||||
x(5 downto 0) <= x_pre(5 downto 0);
|
||||
|
||||
y_pre <= vc_eff + ('0' & layer2_scroll_y_q);
|
||||
y(7 downto 6) <= y_pre(7 downto 6) when (layer2_wide_res = '1' or (y_pre(8) = '0' and y_pre(7 downto 6) /= "11")) else (y_pre(7 downto 6) + 1);
|
||||
y(5 downto 0) <= y_pre(5 downto 0);
|
||||
|
||||
layer2_addr <= ('0' & y & x(7 downto 0)) when layer2_wide_res = '0' else (x & y);
|
||||
|
||||
-- clip
|
||||
|
||||
hc_valid <= '1' when (layer2_wide_res = '0' and hc_eff(8) = '0') or (layer2_wide_res = '1' and (hc_eff(8) = '0' or hc_eff(7 downto 6) = "00")) else '0';
|
||||
vc_valid <= '1' when (layer2_wide_res = '1' and vc_eff(8) = '0') or (layer2_wide_res = '0' and (vc_eff(8) = '0' and vc_eff(7 downto 6) /= "11")) else '0';
|
||||
|
||||
layer2_clip_en <= '1' when (hc_eff >= clip_x1_q) and (hc_eff <= clip_x2_q) and (vc_eff >= ('0' & clip_y1_q)) and (vc_eff <= ('0' & clip_y2_q)) and (hc_valid = '1') and (vc_valid = '1') else '0';
|
||||
|
||||
-- generate sram cycle
|
||||
-- 0x040000 - 0x05FFFF (128K) => ZX Spectrum RAM A20:A16 = 00100,BB max 11011,11
|
||||
|
||||
layer2_bank_eff <= (('0' & layer2_active_bank_q(6 downto 4)) + 1) & layer2_active_bank_q(3 downto 0);
|
||||
layer2_addr_eff <= (layer2_bank_eff + ("00000" & layer2_addr(16 downto 14))) & layer2_addr(13 downto 0);
|
||||
|
||||
layer2_en <= '1' when layer2_en_q = '1' and layer2_clip_en = '1' and layer2_addr_eff(21) = '0' and layer2_addr_eff(20 downto 18) /= "111" else '0';
|
||||
|
||||
process (i_CLK_28)
|
||||
begin
|
||||
if rising_edge(i_CLK_28) then
|
||||
if i_sc = "00" then
|
||||
if layer2_en = '1' then
|
||||
layer2_req_t <= not layer2_req_t;
|
||||
end if;
|
||||
layer2_sram_addr <= layer2_addr_eff(20 downto 0);
|
||||
layer2_pixel_qq <= i_layer2_sram_di;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_layer2_sram_addr <= layer2_sram_addr;
|
||||
o_layer2_req_t <= layer2_req_t;
|
||||
|
||||
-- generate pixels
|
||||
|
||||
process (i_CLK_7) begin
|
||||
if rising_edge(i_CLK_7) then
|
||||
layer2_en_qq <= layer2_en;
|
||||
layer2_hires_qq <= layer2_resolution_q(1);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
layer2_pixel_pre <= layer2_pixel_qq when layer2_hires_qq = '0' else ("0000" & layer2_pixel_qq(7 downto 4)) when i_sc(1) = '0' else ("0000" & layer2_pixel_qq(3 downto 0));
|
||||
layer2_pixel <= (layer2_pixel_pre(7 downto 4) + layer2_palette_offset_q) & layer2_pixel_pre(3 downto 0);
|
||||
|
||||
process (i_CLK_28)
|
||||
begin
|
||||
if rising_edge(i_CLK_28) then
|
||||
if i_sc(0) = '1' then
|
||||
o_layer2_pixel <= layer2_pixel;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_layer2_en <= layer2_en_qq;
|
||||
|
||||
end architecture;
|
||||
117
rtl/video/lores.vhd
Normal file
117
rtl/video/lores.vhd
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
-- ZX Spectrum Next LoRes Display
|
||||
-- Copyright 2020 Victor Trucco and Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- LoRes video mode
|
||||
-- 128 x 96, 8-bit colour
|
||||
-- $4000-$57FF for top half
|
||||
-- $6000-$77FF for bottom half
|
||||
--
|
||||
-- LoRes radastan (original mode from zx uno <http://zxuno.speccy.org/>)
|
||||
-- 128 x 96, 4-bit colour
|
||||
-- $4000 - $57ff if timex dfile 0 active
|
||||
-- $6000 - $77ff if timex dfile 1 active
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity lores is
|
||||
port (
|
||||
mode_i : in std_logic; -- 0 = lores, 1 = radastan
|
||||
dfile_i : in std_logic; -- timex display file to use for radastan
|
||||
ulap_en_i : in std_logic; -- 1 = ula plus enabled
|
||||
|
||||
lores_palette_offset_i : in std_logic_vector(3 downto 0);
|
||||
|
||||
hc_i : in std_logic_vector(8 downto 0); -- current x coordinate
|
||||
vc_i : in std_logic_vector(8 downto 0); -- current y coordinate
|
||||
|
||||
clip_x1_i : in std_logic_vector(7 downto 0);
|
||||
clip_x2_i : in std_logic_vector(7 downto 0);
|
||||
clip_y1_i : in std_logic_vector(7 downto 0);
|
||||
clip_y2_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
scroll_x_i : in std_logic_vector(7 downto 0);
|
||||
scroll_y_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
lores_addr_o : out std_logic_vector(13 downto 0); -- bank 5 offset
|
||||
lores_data_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
lores_pixel_o : out std_logic_vector(7 downto 0);
|
||||
lores_pixel_en_o : out std_logic -- 1 = valid pixel
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of lores is
|
||||
|
||||
signal x : std_logic_vector(7 downto 0);
|
||||
signal y : std_logic_vector(7 downto 0);
|
||||
signal y_pre : std_logic_vector(8 downto 0);
|
||||
|
||||
signal lores_addr : std_logic_vector(13 downto 0);
|
||||
signal lores_addr_pre : std_logic_vector(13 downto 0);
|
||||
signal lores_addr_rad : std_logic_vector(13 downto 0);
|
||||
|
||||
signal pixel_lores_nib_H : std_logic_vector(3 downto 0);
|
||||
signal pixel_rad_nib_L : std_logic_vector(3 downto 0);
|
||||
signal pixel_rad_nib_H : std_logic_vector(3 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- generate pixel coordinate
|
||||
|
||||
x <= hc_i(7 downto 0) + scroll_x_i;
|
||||
|
||||
y_pre <= vc_i + ('0' & scroll_y_i);
|
||||
|
||||
y(7 downto 6) <= (y_pre(7 downto 6) + 1) when y_pre >= 192 else y_pre(7 downto 6);
|
||||
y(5 downto 0) <= y_pre(5 downto 0);
|
||||
|
||||
-- generate pixel address
|
||||
|
||||
lores_addr_pre <= y(7 downto 1) & x(7 downto 1);
|
||||
|
||||
lores_addr(13 downto 11) <= (lores_addr_pre(13 downto 11) + 1) when y >= 96 else lores_addr_pre(13 downto 11);
|
||||
lores_addr(10 downto 0) <= lores_addr_pre(10 downto 0);
|
||||
|
||||
lores_addr_rad <= dfile_i & y(7 downto 1) & x(7 downto 2);
|
||||
|
||||
lores_addr_o <= lores_addr when mode_i = '0' else lores_addr_rad;
|
||||
|
||||
-- generate pixel out lores
|
||||
|
||||
pixel_lores_nib_H <= lores_data_i(7 downto 4) + lores_palette_offset_i;
|
||||
|
||||
-- generate pixel out lores radastan
|
||||
|
||||
pixel_rad_nib_L <= lores_data_i(7 downto 4) when x(1) = '0' else lores_data_i(3 downto 0);
|
||||
pixel_rad_nib_H <= lores_palette_offset_i when ulap_en_i = '0' else ("11" & lores_palette_offset_i(1 downto 0));
|
||||
|
||||
-- pixel out
|
||||
|
||||
lores_pixel_o <= (pixel_rad_nib_H & pixel_rad_nib_L) when mode_i = '1' else (pixel_lores_nib_H & lores_data_i(3 downto 0));
|
||||
|
||||
-- clip
|
||||
|
||||
lores_pixel_en_o <= '1' when (hc_i >= '0' & clip_x1_i) and (hc_i <= '0' & clip_x2_i) and (vc_i >= '0' & clip_y1_i) and (vc_i <= '0' & clip_y2_i) else '0';
|
||||
|
||||
end architecture;
|
||||
1088
rtl/video/sprites.vhd
Normal file
1088
rtl/video/sprites.vhd
Normal file
File diff suppressed because it is too large
Load Diff
448
rtl/video/tilemap.vhd
Normal file
448
rtl/video/tilemap.vhd
Normal file
@@ -0,0 +1,448 @@
|
||||
|
||||
-- ZX Spectrum Next Tilemap Display
|
||||
-- Copyright 2020 Alvin Albrecht
|
||||
--
|
||||
-- Ideas - Spectrum Next Team
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- Currently the hi-res pixel fetch requires 26/32 cycles at 28MHz to accommodate
|
||||
-- a scrolling screen but this can be improved to 23 cycles. -- AA
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity tilemap is
|
||||
port (
|
||||
reset_i : in std_logic;
|
||||
|
||||
clock_master_i : in std_logic; -- 28MHz synchronized with 7MHz pixel clock
|
||||
clock_master_180o_i : in std_logic; -- 28MHz inverted
|
||||
|
||||
hcounter_i : in unsigned(8 downto 0); -- sprite counter 0-319 visible area
|
||||
vcounter_i : in unsigned(8 downto 0); -- sprite counter 0-255 visible area
|
||||
subpixel_i : in std_logic_vector(1 downto 0); -- 28MHz subpixel count
|
||||
|
||||
control_i : in std_logic_vector(6 downto 0);
|
||||
default_flags_i : in std_logic_vector(7 downto 0); -- default flags if tilemap flags are eliminated
|
||||
transp_colour_i : in std_logic_vector(3 downto 0);
|
||||
|
||||
-- ULA Memory Interface
|
||||
|
||||
tm_mem_bank7_o : out std_logic;
|
||||
tm_mem_addr_o : out std_logic_vector(13 downto 0);
|
||||
tm_mem_rd_o : out std_logic;
|
||||
tm_mem_ack_i : in std_logic;
|
||||
tm_mem_data_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- Memory Map
|
||||
|
||||
tm_map_base_i : in std_logic_vector(6 downto 0); -- bit 6 is bank selector, 5:0 are offsets into 16K
|
||||
tm_tile_base_i : in std_logic_vector(6 downto 0); -- bit 6 is bank selector, 5:0 are offsets into 16K
|
||||
|
||||
-- Out
|
||||
|
||||
pixel_o : out std_logic_vector(7 downto 0); -- tilemap pixel
|
||||
pixel_en_o : out std_logic; -- tilemap pixel is valid
|
||||
pixel_below_o : out std_logic; -- tilemap pixel should cover ula pixel
|
||||
pixel_textmode_o : out std_logic; -- tilemap pixel is a textmode pixel
|
||||
|
||||
-- Scroll
|
||||
|
||||
tm_scroll_x_i : in std_logic_vector(9 downto 0);
|
||||
tm_scroll_y_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- Clip Window
|
||||
|
||||
clip_x1_i : in unsigned(7 downto 0);
|
||||
clip_x2_i : in unsigned(7 downto 0);
|
||||
clip_y1_i : in unsigned(7 downto 0);
|
||||
clip_y2_i : in unsigned(7 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of tilemap is
|
||||
|
||||
-- coregen
|
||||
|
||||
component sdpram_16_9 is
|
||||
port (
|
||||
DPRA : IN STD_LOGIC_VECTOR(4-1 downto 0) := (OTHERS => '0');
|
||||
CLK : IN STD_LOGIC;
|
||||
WE : IN STD_LOGIC;
|
||||
DPO : OUT STD_LOGIC_VECTOR(9-1 downto 0);
|
||||
A : IN STD_LOGIC_VECTOR(4-1-(4*0*boolean'pos(4>4)) downto 0) := (OTHERS => '0');
|
||||
D : IN STD_LOGIC_VECTOR(9-1 downto 0) := (OTHERS => '0')
|
||||
);
|
||||
end component;
|
||||
|
||||
--
|
||||
|
||||
signal mode_i : std_logic; -- 1 = 80x32, 0 = 40x32
|
||||
signal strip_flags_i : std_logic; -- 1 = eliminate flags from tilemap
|
||||
signal textmode_i : std_logic; -- 1 = extend palette offset to 7 bits at expense of rotations and mirrors
|
||||
-- signal reduced_tm_i : std_logic; -- 1 = tilemap area reduced to 64x24 / 32x24
|
||||
-- signal split_addr_i : std_logic; -- 1 = tilemap flags and tiles split between two 8k halves
|
||||
signal mode_512_i : std_logic; -- 1 = 512 tile mode
|
||||
signal tm_on_top_i : std_logic; -- 1 = tilemap is always on top
|
||||
|
||||
signal tm_mem_fetch : std_logic;
|
||||
signal tm_pixel_half_wr : std_logic;
|
||||
signal tm_pixel_half_rd : std_logic;
|
||||
signal tm_mode : std_logic;
|
||||
signal hcount : std_logic_vector(10 downto 0);
|
||||
signal hcount_eff : std_logic_vector(9 downto 0);
|
||||
signal hcount_effsub : std_logic_vector(9 downto 0);
|
||||
signal tm_mem_ack_d : std_logic;
|
||||
|
||||
-- tilemap pixel loader
|
||||
|
||||
type state_t is (S_IDLE, S_READ_TILE_0, S_READ_TILE_1, S_READ_PIXELS);
|
||||
signal state_s : state_t;
|
||||
signal next_state_s : state_t;
|
||||
|
||||
signal tm_abs_x : std_logic_vector(9 downto 0);
|
||||
signal tm_abs_y : std_logic_vector(11 downto 0);
|
||||
signal tm_pixel : std_logic_vector(2 downto 0);
|
||||
signal tm_tilemap_0 : std_logic_vector(7 downto 0);
|
||||
signal tm_tilemap_1 : std_logic_vector(7 downto 0);
|
||||
signal tm_tile_base_q : std_logic_vector(6 downto 0);
|
||||
signal tm_map_base_q : std_logic_vector(6 downto 0);
|
||||
signal tm_strip_flags_q : std_logic;
|
||||
signal textmode_q : std_logic;
|
||||
signal mode_512_q : std_logic;
|
||||
signal tm_on_top_q : std_logic;
|
||||
signal textmode_0 : std_logic;
|
||||
signal textmode_1 : std_logic;
|
||||
|
||||
signal tm_next_pixel : std_logic_vector(2 downto 0);
|
||||
|
||||
signal tm_x_addend_0 : std_logic_vector(9 downto 0);
|
||||
signal tm_x_addend_1 : std_logic_vector(9 downto 0);
|
||||
signal tm_x_sum : std_logic_vector(10 downto 0);
|
||||
signal tm_x_correction : std_logic_vector(3 downto 0);
|
||||
signal tm_next_abs_x : std_logic_vector(9 downto 0);
|
||||
|
||||
signal tm_abs_y_s : std_logic_vector(7 downto 0);
|
||||
signal tm_abs_y_mult_sub : std_logic_vector(7 downto 0);
|
||||
signal tm_abs_y_mult : std_logic_vector(8 downto 0);
|
||||
|
||||
signal tm_effective_x_mirror : std_logic;
|
||||
signal tm_effective_x : std_logic_vector(2 downto 0);
|
||||
signal tm_effective_y : std_logic_vector(2 downto 0);
|
||||
signal tm_transformed_x : std_logic_vector(2 downto 0);
|
||||
signal tm_transformed_y : std_logic_vector(2 downto 0);
|
||||
|
||||
signal tm_tilemap_pixel_waddr : std_logic_vector(3 downto 0);
|
||||
signal tm_tilemap_pixel_we : std_logic;
|
||||
signal tm_tilemap_pixel_data_standard : std_logic_vector(7 downto 0);
|
||||
signal tm_tilemap_pixel_data_textmode_shift : std_logic_vector(7 downto 0);
|
||||
signal tm_tilemap_pixel_data_textmode : std_logic_vector(7 downto 0);
|
||||
signal tm_tilemap_pixel_wdata : std_logic_vector(8 downto 0);
|
||||
|
||||
signal tm_mem_addr_pix_sub_sub : std_logic_vector(8 downto 0);
|
||||
signal tm_mem_addr_pix_sub : std_logic_vector(13 downto 0);
|
||||
signal tm_mem_addr_tile_sub : std_logic_vector(13 downto 0);
|
||||
signal tm_mem_addr_tile_sub_sub : std_logic_vector(11 downto 0);
|
||||
signal tm_mem_addr_sub : std_logic_vector(13 downto 0);
|
||||
signal tm_mem_addr_offset : std_logic_vector(6 downto 0);
|
||||
|
||||
-- VIDEO OUT
|
||||
|
||||
signal video_addr : std_logic_vector(3 downto 0);
|
||||
signal video_data : std_logic_vector(8 downto 0);
|
||||
|
||||
signal xsv : unsigned(8 downto 0);
|
||||
signal xev : unsigned(8 downto 0);
|
||||
signal ysv : unsigned(7 downto 0);
|
||||
signal yev : unsigned(7 downto 0);
|
||||
|
||||
signal pixel_en_s : std_logic;
|
||||
signal pixel_en_f : std_logic;
|
||||
signal pixel_textmode_s : std_logic;
|
||||
signal pixel_en_standard_s : std_logic;
|
||||
signal video_data_q : std_logic_vector(10 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
--------------------------
|
||||
-- TILEMAP CONTROL ALIASES
|
||||
--------------------------
|
||||
|
||||
mode_i <= control_i(6); -- 0 = 40x32, 1 = 80x32
|
||||
strip_flags_i <= control_i(5); -- 1 = eliminate tilemap flags
|
||||
textmode_i <= control_i(3); -- 1 = extend palette offset to 7 bits at expense of rotations and mirrors
|
||||
-- reduced_tm_i <= control_i(3); -- 1 = select reduced tilemap area (32x24 or 64x24) NOT IMPLEMENTED
|
||||
-- split_addr_i <= control_i(2); -- 1 = select split addressing NOT IMPLEMENTED
|
||||
mode_512_i <= control_i(1); -- 1 = select 512 tile mode
|
||||
tm_on_top_i <= control_i(0); -- 1 = tilemap always on top of ula
|
||||
|
||||
-----------------------
|
||||
-- TILEMAP PIXEL MEMORY
|
||||
-----------------------
|
||||
|
||||
tilemem : sdpram_16_9
|
||||
port map (
|
||||
DPRA => video_addr,
|
||||
CLK => clock_master_i,
|
||||
WE => tm_tilemap_pixel_we,
|
||||
DPO => video_data,
|
||||
A => tm_tilemap_pixel_waddr,
|
||||
D => tm_tilemap_pixel_wdata
|
||||
);
|
||||
|
||||
-------------
|
||||
-- SCHEDULING
|
||||
-------------
|
||||
|
||||
hcount <= std_logic_vector(hcounter_i(8 downto 0)) & subpixel_i;
|
||||
|
||||
process (clock_master_i)
|
||||
begin
|
||||
if rising_edge(clock_master_i) then
|
||||
if reset_i = '1' then
|
||||
tm_mode <= '0';
|
||||
elsif hcount(4 downto 0) = "11111" then
|
||||
tm_mode <= mode_i;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
hcount_effsub <= hcount(10 downto 1) when tm_mode = '1' else ((hcount(10) and hcount(9)) & hcount(10 downto 2)); -- sign extend
|
||||
hcount_eff <= (hcount_effsub(9 downto 3) + 1) & hcount_effsub(2 downto 0); -- one character ahead
|
||||
|
||||
tm_mem_fetch <= '1' when hcount_eff(2 downto 0) = "000" else '0';
|
||||
|
||||
process (clock_master_i)
|
||||
begin
|
||||
if rising_edge(clock_master_i) then
|
||||
if reset_i = '1' then
|
||||
tm_pixel_half_wr <= '0';
|
||||
elsif hcount_eff(2 downto 0) = "111" and hcount(1 downto 0) = "11" then
|
||||
tm_pixel_half_wr <= not tm_pixel_half_wr;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
tm_pixel_half_rd <= not tm_pixel_half_wr;
|
||||
|
||||
process (clock_master_180o_i)
|
||||
begin
|
||||
if rising_edge(clock_master_180o_i) then
|
||||
tm_mem_ack_d <= tm_mem_ack_i;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-----------------------
|
||||
-- TILEMAP PIXEL LOADER
|
||||
-----------------------
|
||||
|
||||
-- state
|
||||
|
||||
process (clock_master_i)
|
||||
begin
|
||||
if rising_edge(clock_master_i) then
|
||||
if reset_i = '1' then
|
||||
state_s <= S_IDLE;
|
||||
elsif hcount_eff(2 downto 0) = "111" and hcount(1 downto 0) = "11" then
|
||||
state_s <= S_IDLE;
|
||||
else
|
||||
state_s <= next_state_s;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- next state combinatorial
|
||||
|
||||
process (state_s, tm_mem_fetch, tm_mem_ack_d, tm_next_pixel, tm_abs_x, tm_next_abs_x)
|
||||
begin
|
||||
case state_s is
|
||||
when S_IDLE => if tm_mem_fetch = '1' then
|
||||
next_state_s <= S_READ_TILE_0;
|
||||
else
|
||||
next_state_s <= S_IDLE;
|
||||
end if;
|
||||
when S_READ_TILE_0 => if tm_mem_ack_d = '1' then
|
||||
next_state_s <= S_READ_TILE_1;
|
||||
else
|
||||
next_state_s <= S_READ_TILE_0;
|
||||
end if;
|
||||
when S_READ_TILE_1 => if tm_mem_ack_d = '1' then
|
||||
next_state_s <= S_READ_PIXELS;
|
||||
else
|
||||
next_state_s <= S_READ_TILE_1;
|
||||
end if;
|
||||
when S_READ_PIXELS => if tm_mem_ack_d = '0' then
|
||||
next_state_s <= S_READ_PIXELS;
|
||||
elsif tm_next_pixel = "000" then
|
||||
next_state_s <= S_IDLE;
|
||||
elsif tm_next_abs_x(3) /= tm_abs_x(3) then
|
||||
next_state_s <= S_READ_TILE_0;
|
||||
else
|
||||
next_state_s <= S_READ_PIXELS;
|
||||
end if;
|
||||
when others => next_state_s <= S_IDLE;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- state machine variables
|
||||
|
||||
tm_next_pixel <= tm_pixel + 1;
|
||||
|
||||
tm_x_addend_0 <= tm_scroll_x_i when state_s = S_IDLE else tm_abs_x;
|
||||
tm_x_addend_1 <= hcount_eff when state_s = S_IDLE else "0000000001";
|
||||
tm_x_sum <= ('0' & tm_x_addend_0) + ('0' & tm_x_addend_1);
|
||||
tm_x_correction <= "1100" when tm_x_sum >= 1280 else
|
||||
"0001" when tm_x_sum >= 960 and tm_mode = '0' else
|
||||
"0110" when tm_x_sum >= 640 else
|
||||
"1011" when tm_x_sum >= 320 and tm_mode = '0' else
|
||||
"0000";
|
||||
tm_next_abs_x(9 downto 6) <= tm_x_sum(9 downto 6) + tm_x_correction;
|
||||
tm_next_abs_x(5 downto 0) <= tm_x_sum(5 downto 0);
|
||||
|
||||
tm_effective_x_mirror <= tm_tilemap_1(3) xor tm_tilemap_1(1); -- rotation inverts x mirror
|
||||
tm_effective_x <= tm_abs_x(2 downto 0) when tm_effective_x_mirror = '0' else not (tm_abs_x(2 downto 0)); -- x mirror inverts x coord
|
||||
tm_effective_y <= tm_abs_y(2 downto 0) when tm_tilemap_1(2) = '0' else not (tm_abs_y(2 downto 0)); -- y mirror inverts y coord
|
||||
tm_transformed_x <= tm_effective_x when tm_tilemap_1(1) = '0' else tm_effective_y; -- rotation exchanges x and y
|
||||
tm_transformed_y <= tm_effective_y when tm_tilemap_1(1) = '0' else tm_effective_x;
|
||||
|
||||
tm_abs_y_s <= tm_scroll_y_i + std_logic_vector(vcounter_i(7 downto 0));
|
||||
tm_abs_y_mult_sub <= ('0' & tm_abs_y_s(7 downto 3) & "00") + ("000" & tm_abs_y_s(7 downto 3)); -- * 5
|
||||
tm_abs_y_mult <= '0' & tm_abs_y_mult_sub when tm_mode = '0' else tm_abs_y_mult_sub & '0';
|
||||
|
||||
process (clock_master_i)
|
||||
begin
|
||||
if rising_edge(clock_master_i) then
|
||||
if reset_i = '1' then
|
||||
tm_abs_x <= (others => '0');
|
||||
tm_abs_y <= (others => '0');
|
||||
tm_pixel <= (others => '0');
|
||||
tm_tilemap_0 <= (others => '0');
|
||||
tm_tilemap_1 <= (others => '0');
|
||||
tm_map_base_q <= (others => '0');
|
||||
tm_tile_base_q <= (others => '0');
|
||||
tm_strip_flags_q <= '0';
|
||||
textmode_q <= '0';
|
||||
mode_512_q <= '0';
|
||||
tm_on_top_q <= '0';
|
||||
elsif state_s = S_IDLE then
|
||||
tm_abs_x <= tm_next_abs_x;
|
||||
tm_abs_y <= tm_abs_y_mult & tm_abs_y_s(2 downto 0);
|
||||
tm_pixel <= (others => '0');
|
||||
tm_map_base_q <= tm_map_base_i;
|
||||
tm_tile_base_q <= tm_tile_base_i;
|
||||
tm_strip_flags_q <= strip_flags_i;
|
||||
textmode_q <= textmode_i;
|
||||
mode_512_q <= mode_512_i;
|
||||
tm_on_top_q <= tm_on_top_i;
|
||||
elsif state_s = S_READ_TILE_0 then
|
||||
tm_tilemap_0 <= tm_mem_data_i;
|
||||
if tm_pixel_half_wr = '0' then
|
||||
textmode_0 <= textmode_q;
|
||||
else
|
||||
textmode_1 <= textmode_q;
|
||||
end if;
|
||||
elsif state_s = S_READ_TILE_1 then
|
||||
if tm_strip_flags_q = '0' then
|
||||
tm_tilemap_1 <= tm_mem_data_i;
|
||||
else
|
||||
tm_tilemap_1 <= default_flags_i;
|
||||
end if;
|
||||
elsif state_s = S_READ_PIXELS then
|
||||
if tm_mem_ack_d = '1' then
|
||||
tm_pixel <= tm_next_pixel;
|
||||
tm_abs_x <= tm_next_abs_x;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- write pixel data to local memory
|
||||
|
||||
tm_tilemap_pixel_waddr <= tm_pixel_half_wr & tm_pixel;
|
||||
tm_tilemap_pixel_we <= '1' when state_s = S_READ_PIXELS else '0';
|
||||
|
||||
tm_tilemap_pixel_data_standard(7 downto 4) <= tm_tilemap_1(7 downto 4);
|
||||
tm_tilemap_pixel_data_standard(3 downto 0) <= tm_mem_data_i(7 downto 4) when tm_transformed_x(0) = '0' else tm_mem_data_i(3 downto 0);
|
||||
|
||||
tm_tilemap_pixel_data_textmode_shift <= std_logic_vector(shift_left(unsigned(tm_mem_data_i), to_integer(unsigned(tm_abs_x(2 downto 0)))));
|
||||
tm_tilemap_pixel_data_textmode <= tm_tilemap_1(7 downto 1) & tm_tilemap_pixel_data_textmode_shift(7);
|
||||
|
||||
tm_tilemap_pixel_wdata(8) <= (tm_tilemap_1(0) or mode_512_q) and not tm_on_top_q;
|
||||
tm_tilemap_pixel_wdata(7 downto 0) <= tm_tilemap_pixel_data_standard when textmode_q = '0' else tm_tilemap_pixel_data_textmode;
|
||||
|
||||
-- read from external memory
|
||||
|
||||
tm_mem_addr_pix_sub_sub <= (mode_512_q and tm_tilemap_1(0)) & tm_tilemap_0;
|
||||
tm_mem_addr_pix_sub <= (tm_mem_addr_pix_sub_sub & tm_transformed_y & tm_transformed_x(2 downto 1)) when textmode_q = '0' else ("00" & tm_mem_addr_pix_sub_sub & tm_abs_y(2 downto 0));
|
||||
tm_mem_addr_tile_sub_sub <= (tm_abs_y(11 downto 3) + ("00000" & tm_abs_x(9 downto 6))) & tm_abs_x(5 downto 3);
|
||||
tm_mem_addr_tile_sub <= '0' & tm_mem_addr_tile_sub_sub & '0' when state_s = S_READ_TILE_0 and tm_strip_flags_q = '0' else
|
||||
'0' & tm_mem_addr_tile_sub_sub & '1' when tm_strip_flags_q = '0' else
|
||||
"00" & tm_mem_addr_tile_sub_sub;
|
||||
tm_mem_addr_sub <= tm_mem_addr_pix_sub when state_s = S_READ_PIXELS else tm_mem_addr_tile_sub;
|
||||
tm_mem_addr_offset <= tm_tile_base_q when state_s = S_READ_PIXELS else tm_map_base_q;
|
||||
|
||||
tm_mem_bank7_o <= tm_mem_addr_offset(6);
|
||||
tm_mem_addr_o <= (tm_mem_addr_sub(13 downto 8) + tm_mem_addr_offset(5 downto 0)) & tm_mem_addr_sub(7 downto 0);
|
||||
tm_mem_rd_o <= '0' when state_s = S_IDLE else '1';
|
||||
|
||||
------------------------
|
||||
-- GENERATE VIDEO OUTPUT
|
||||
------------------------
|
||||
|
||||
video_addr <= tm_pixel_half_rd & hcount_eff(2 downto 0);
|
||||
|
||||
process (clock_master_i)
|
||||
begin
|
||||
if rising_edge(clock_master_i) then
|
||||
if hcount(1 downto 0) = "11" then -- rising edge of 7MHz
|
||||
xsv <= clip_x1_i & '0';
|
||||
xev <= clip_x2_i & '1';
|
||||
ysv <= clip_y1_i;
|
||||
yev <= clip_y2_i;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
pixel_en_s <= '1' when (hcounter_i < 320) and (vcounter_i(8) = '0') and (hcounter_i >= xsv) and (hcounter_i <= xev) and (vcounter_i >= ysv) and (vcounter_i <= yev) else '0';
|
||||
|
||||
pixel_textmode_s <= (textmode_0 and not tm_pixel_half_rd) or (textmode_1 and tm_pixel_half_rd);
|
||||
pixel_en_standard_s <= '1' when pixel_en_s = '1' and (video_data(3 downto 0) /= transp_colour_i) else '0';
|
||||
|
||||
pixel_en_f <= (pixel_en_standard_s and not pixel_textmode_s) or (pixel_en_s and pixel_textmode_s);
|
||||
|
||||
process (clock_master_i)
|
||||
begin
|
||||
if rising_edge(clock_master_i) then
|
||||
if reset_i = '1' then
|
||||
video_data_q <= (others => '0');
|
||||
elsif hcount(0) = '1' then -- rising edge of 14MHz
|
||||
video_data_q(10) <= pixel_textmode_s;
|
||||
video_data_q(9 downto 0) <= pixel_en_f & video_data;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
pixel_textmode_o <= video_data_q(10);
|
||||
pixel_en_o <= video_data_q(9);
|
||||
pixel_below_o <= video_data_q(8);
|
||||
pixel_o <= video_data_q(7 downto 0);
|
||||
|
||||
end architecture;
|
||||
603
rtl/video/zxula.vhd
Normal file
603
rtl/video/zxula.vhd
Normal file
@@ -0,0 +1,603 @@
|
||||
|
||||
-- ZX Spectrum Next ULA
|
||||
-- Copyright 2020 Alvin Albrecht, Fabio Belavenuto and Victor Trucco
|
||||
-- Thanks to Kev Brady for creating tests comparing original hardware
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
--
|
||||
|
||||
-- Features of this implementation:
|
||||
--
|
||||
-- * compatible with 48k, 128k, +3, pentagon ula including contention and floating bus
|
||||
-- * hardware pixel scrolling in X and Y
|
||||
-- * implements timex hi-res, hi-colour and dual screen
|
||||
-- * dynamic choice of ULAnext, ULA+ and standard ula palette
|
||||
--
|
||||
-- References:
|
||||
--
|
||||
-- "The ZX Spectrum ULA: How to Design a Microcomputer", (c) 2010 Chris Smith
|
||||
-- https://faqwiki.zxnet.co.uk/wiki/Contended_memory Emulator Reference
|
||||
-- https://zxnet.co.uk/spectrum/schematics/Z70830.pdf +3 Schematic
|
||||
-- http://sky.relative-path.com/zx/floating_bus.html by Ast A Moore
|
||||
-- http://sblive.narod.ru/ZX-Spectrum/Pentagon128k/Pentagon128k.htm by Z.A.N.
|
||||
--
|
||||
-- The implementation was simplified somewhat from Chris Smith's description and then
|
||||
-- was complicated by the addition of pixel scrolling and re-interpretation of the
|
||||
-- attribute byte. It's likely possible to reduce the number of registers used
|
||||
-- but only at the expense of clarity.
|
||||
--
|
||||
-- The display position as seen by the ULA and as described in Chris' book is held
|
||||
-- in i_vc and i_hc. There is a second horizontal counter i_phc which is a practical
|
||||
-- counter in that 0 corresponds to when the system is actually generating pixel 0.
|
||||
-- This position corresponds to ULA count i_hc = 0xC.
|
||||
--
|
||||
-- Because display memory is held in dual port bram, there is no real contention in
|
||||
-- the zx next. Instead contention is simulated at the exact moments it would occur
|
||||
-- on the original machine. And because there is no shortage of memory bandwidth to
|
||||
-- bram, this implementation may continually access bram even outside the display area
|
||||
-- with no detrimental impact on the system.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity zxula is
|
||||
port (
|
||||
|
||||
i_CLK_7 : in std_logic;
|
||||
i_CLK_14 : in std_logic;
|
||||
i_CLK_CPU : in std_logic;
|
||||
|
||||
i_cpu_mreq_n : in std_logic;
|
||||
i_cpu_iorq_n : in std_logic;
|
||||
|
||||
i_hc : in std_logic_vector(8 downto 0);
|
||||
i_vc : in std_logic_vector(8 downto 0);
|
||||
i_phc : in std_logic_vector(8 downto 0);
|
||||
|
||||
i_timing_pentagon : in std_logic;
|
||||
i_timing_p3 : in std_logic;
|
||||
|
||||
i_port_ff_reg : in std_logic_vector(5 downto 0);
|
||||
i_port_fe_border : in std_logic_vector(2 downto 0);
|
||||
i_ula_shadow_en : in std_logic;
|
||||
|
||||
i_ulanext_en : in std_logic;
|
||||
i_ulanext_format : in std_logic_vector(7 downto 0);
|
||||
i_ulap_en : in std_logic;
|
||||
|
||||
o_ula_vram_a : out std_logic_vector(13 downto 0);
|
||||
o_ula_shadow : out std_logic;
|
||||
o_ula_vram_rd : out std_logic;
|
||||
i_ula_vram_d : in std_logic_vector(7 downto 0);
|
||||
|
||||
o_ula_border : out std_logic;
|
||||
o_ula_pixel : out std_logic_vector(7 downto 0);
|
||||
o_ula_select_bgnd : out std_logic;
|
||||
o_ula_clipped : out std_logic;
|
||||
|
||||
i_ula_clip_x1 : in std_logic_vector(7 downto 0);
|
||||
i_ula_clip_x2 : in std_logic_vector(7 downto 0);
|
||||
i_ula_clip_y1 : in std_logic_vector(7 downto 0);
|
||||
i_ula_clip_y2 : in std_logic_vector(7 downto 0);
|
||||
|
||||
i_ula_scroll_x : in std_logic_vector(7 downto 0);
|
||||
i_ula_scroll_y : in std_logic_vector(7 downto 0);
|
||||
i_ula_fine_scroll_x : in std_logic;
|
||||
|
||||
i_p3_floating_bus : in std_logic_vector(7 downto 0);
|
||||
o_ula_floating_bus : out std_logic_vector(7 downto 0);
|
||||
|
||||
i_contention_en : in std_logic;
|
||||
i_contention_port : in std_logic;
|
||||
i_contention_memory : in std_logic;
|
||||
|
||||
o_cpu_wait_n : out std_logic;
|
||||
o_cpu_contend : out std_logic
|
||||
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of zxula is
|
||||
|
||||
signal screen_mode_s : std_logic_vector(2 downto 0);
|
||||
signal screen_mode : std_logic_vector(2 downto 0);
|
||||
signal py_s : std_logic_vector(8 downto 0);
|
||||
signal py : std_logic_vector(7 downto 0);
|
||||
signal px : std_logic_vector(8 downto 0);
|
||||
signal px_1 : std_logic_vector(8 downto 0);
|
||||
signal ula_shadow : std_logic;
|
||||
|
||||
signal addr_p_spc_12_5 : std_logic_vector(7 downto 0);
|
||||
signal addr_a_spc_12_5 : std_logic_vector(7 downto 0);
|
||||
signal vram_rd : std_logic;
|
||||
signal vram_a : std_logic_vector(13 downto 0);
|
||||
|
||||
signal pbyte00 : std_logic_vector(7 downto 0);
|
||||
signal pbyte01 : std_logic_vector(7 downto 0);
|
||||
signal abyte00 : std_logic_vector(7 downto 0);
|
||||
signal abyte01 : std_logic_vector(7 downto 0);
|
||||
signal pbyte10 : std_logic_vector(7 downto 0);
|
||||
signal pbyte11 : std_logic_vector(7 downto 0);
|
||||
signal abyte10 : std_logic_vector(7 downto 0);
|
||||
signal abyte11 : std_logic_vector(7 downto 0);
|
||||
signal floating_bus_r : std_logic_vector(7 downto 0);
|
||||
signal floating_bus_en : std_logic;
|
||||
|
||||
signal screen_mode_0 : std_logic_vector(2 downto 0);
|
||||
signal screen_mode_1 : std_logic_vector(2 downto 0);
|
||||
signal scroll_0 : std_logic_vector(3 downto 0);
|
||||
signal scroll_1 : std_logic_vector(3 downto 0);
|
||||
|
||||
signal sload_0 : std_logic;
|
||||
signal sload_1 : std_logic;
|
||||
signal sload_x : std_logic;
|
||||
signal sload_d : std_logic;
|
||||
signal sload : std_logic;
|
||||
|
||||
signal shift_pbyte : std_logic_vector(15 downto 0);
|
||||
signal shift_abyte : std_logic_vector(15 downto 0);
|
||||
signal shift_screen_mode : std_logic_vector(2 downto 0);
|
||||
signal shift_scroll : std_logic_vector(3 downto 0);
|
||||
signal shift_reg_32 : std_logic_vector(31 downto 0);
|
||||
signal shift_reg_ld : std_logic_vector(31 downto 0);
|
||||
signal shift_reg : std_logic_vector(15 downto 0);
|
||||
|
||||
signal border_active_v : std_logic;
|
||||
signal border_active : std_logic;
|
||||
signal border_active_d : std_logic;
|
||||
signal border_active_ula : std_logic;
|
||||
signal border_clr : std_logic_vector(7 downto 0);
|
||||
signal border_clr_tmx : std_logic_vector(7 downto 0);
|
||||
signal attr_reg : std_logic_vector(15 downto 0);
|
||||
signal attr_scroll_r : std_logic_vector(4 downto 0);
|
||||
signal screen_mode_r : std_logic_vector(2 downto 0);
|
||||
signal attr_active : std_logic_vector(7 downto 0);
|
||||
|
||||
signal pixel_en : std_logic;
|
||||
signal flash_cnt : std_logic_vector(4 downto 0);
|
||||
|
||||
signal ula_select_bgnd : std_logic;
|
||||
signal ula_pixel : std_logic_vector(7 downto 0);
|
||||
|
||||
signal hc_adj : std_logic_vector(3 downto 0);
|
||||
signal wait_s : std_logic;
|
||||
signal mreq23_n : std_logic;
|
||||
signal ioreqtw3_n : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
--
|
||||
-- MEMORY FETCH
|
||||
--
|
||||
|
||||
-- Sample Display Mode and Scroll Amount Prior to Address Generation
|
||||
|
||||
screen_mode_s <= i_port_ff_reg(2 downto 0) when i_ula_shadow_en = '0' else "000"; -- limit timex modes to bank 5 as bank 7 only has 8k bram
|
||||
py_s <= i_vc + ('0' & i_ula_scroll_y);
|
||||
|
||||
process (i_CLK_7)
|
||||
begin
|
||||
if falling_edge(i_CLK_7) then
|
||||
if i_hc(3 downto 0) = X"3" or i_hc(3 downto 0) = X"B" then
|
||||
|
||||
px <= i_ula_fine_scroll_x & (i_hc(7 downto 3) + i_ula_scroll_x(7 downto 3)) & i_ula_scroll_x(2 downto 0);
|
||||
|
||||
if py_s(8 downto 7) = "11" then
|
||||
py <= (not py_s(7)) & py_s(6 downto 0);
|
||||
elsif py_s(8) = '1' or py_s(7 downto 6) = "11" then
|
||||
py <= (py_s(7 downto 6) + 1) & py_s(5 downto 0);
|
||||
else
|
||||
py <= py_s(7 downto 0);
|
||||
end if;
|
||||
|
||||
screen_mode <= screen_mode_s;
|
||||
ula_shadow <= i_ula_shadow_en;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
px_1 <= px(8) & (px(7 downto 3) + 1) & px(2 downto 0);
|
||||
|
||||
-- Generate memory read cycles
|
||||
|
||||
-- Cycles 0x8,0x9 and 0xC,0xD read pixel bytes
|
||||
-- Cycles 0xA,0xB and 0xE,0xF read attribute bytes
|
||||
|
||||
addr_p_spc_12_5 <= py(7 downto 6) & py(2 downto 0) & py(5 downto 3);
|
||||
addr_a_spc_12_5 <= "110" & py(7 downto 3);
|
||||
|
||||
process (i_CLK_7)
|
||||
begin
|
||||
if rising_edge(i_CLK_7) then
|
||||
|
||||
vram_rd <= '0';
|
||||
|
||||
case i_hc(3 downto 0) is
|
||||
|
||||
when X"F" | X"3" =>
|
||||
vram_a <= screen_mode(0) & addr_p_spc_12_5 & px_1(7 downto 3);
|
||||
|
||||
when X"1" | X"5" =>
|
||||
if screen_mode(1) = '1' then
|
||||
vram_a <= '1' & addr_p_spc_12_5 & px_1(7 downto 3);
|
||||
else
|
||||
vram_a <= screen_mode(0) & addr_a_spc_12_5 & px_1(7 downto 3);
|
||||
end if;
|
||||
|
||||
when X"7" | X"B" =>
|
||||
vram_a <= screen_mode(0) & addr_p_spc_12_5 & px(7 downto 3);
|
||||
|
||||
when X"9" | X"D" =>
|
||||
if screen_mode(1) = '1' then
|
||||
vram_a <= '1' & addr_p_spc_12_5 & px(7 downto 3);
|
||||
else
|
||||
vram_a <= screen_mode(0) & addr_a_spc_12_5 & px(7 downto 3);
|
||||
end if;
|
||||
|
||||
when X"0" | X"2" | X"4" | X"6" | X"8" | X"A" | X"C" | X"E" =>
|
||||
vram_rd <= '1';
|
||||
|
||||
when others =>
|
||||
null;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_ula_vram_a <= vram_a;
|
||||
o_ula_vram_rd <= vram_rd;
|
||||
o_ula_shadow <= ula_shadow;
|
||||
|
||||
-- Record bytes read from memory and associated mode information
|
||||
|
||||
process (i_CLK_7)
|
||||
begin
|
||||
if falling_edge(i_CLK_7) then
|
||||
|
||||
case i_hc(3 downto 0) is
|
||||
|
||||
when X"1" =>
|
||||
pbyte11 <= i_ula_vram_d;
|
||||
|
||||
when X"3" =>
|
||||
abyte11 <= i_ula_vram_d;
|
||||
|
||||
when X"5" =>
|
||||
pbyte01 <= i_ula_vram_d;
|
||||
|
||||
when X"7" =>
|
||||
abyte01 <= i_ula_vram_d;
|
||||
|
||||
when X"9" =>
|
||||
pbyte00 <= i_ula_vram_d;
|
||||
|
||||
when X"B" =>
|
||||
abyte00 <= i_ula_vram_d;
|
||||
|
||||
when X"D" =>
|
||||
pbyte10 <= i_ula_vram_d;
|
||||
|
||||
when X"F" =>
|
||||
abyte10 <= i_ula_vram_d;
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK_7)
|
||||
begin
|
||||
if falling_edge(i_CLK_7) then
|
||||
|
||||
if border_active_ula = '1' then
|
||||
|
||||
floating_bus_r <= X"FF";
|
||||
floating_bus_en <= '0';
|
||||
|
||||
else
|
||||
|
||||
case i_hc(3 downto 0) is
|
||||
|
||||
when X"1" =>
|
||||
floating_bus_r <= X"FF";
|
||||
floating_bus_en <= '0';
|
||||
|
||||
when X"9" =>
|
||||
floating_bus_r <= i_ula_vram_d;
|
||||
floating_bus_en <= '1';
|
||||
|
||||
when X"B" =>
|
||||
floating_bus_r <= i_ula_vram_d;
|
||||
|
||||
when X"D" =>
|
||||
floating_bus_r <= i_ula_vram_d;
|
||||
|
||||
when X"F" =>
|
||||
floating_bus_r <= i_ula_vram_d;
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (i_CLK_7)
|
||||
begin
|
||||
if rising_edge(i_CLK_7) then
|
||||
|
||||
if i_hc(3 downto 0) = X"7" then
|
||||
screen_mode_0 <= screen_mode;
|
||||
scroll_0 <= px(2 downto 0) & px(8);
|
||||
end if;
|
||||
|
||||
if i_hc(3 downto 0) = X"B" then
|
||||
screen_mode_1 <= screen_mode;
|
||||
scroll_1 <= px(2 downto 0) & px(8);
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--
|
||||
-- PIXEL SHIFT REGISTER
|
||||
--
|
||||
|
||||
sload_0 <= '1' when i_hc(3 downto 0) = X"C" else '0';
|
||||
sload_1 <= '1' when i_hc(3 downto 0) = X"4" else '0';
|
||||
|
||||
sload_x <= sload_0 or sload_1;
|
||||
|
||||
process (i_CLK_14)
|
||||
begin
|
||||
if rising_edge(i_CLK_14) then
|
||||
sload_d <= sload_x;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sload <= sload_x and not sload_d;
|
||||
|
||||
-- Shifted pixel load
|
||||
|
||||
shift_pbyte <= (pbyte00 & pbyte01) when sload_0 = '1' else (pbyte10 & pbyte11);
|
||||
shift_abyte <= (abyte00 & abyte01) when sload_0 = '1' else (abyte10 & abyte11);
|
||||
shift_screen_mode <= screen_mode_0 when sload_0 = '1' else screen_mode_1;
|
||||
shift_scroll <= scroll_0 when sload_0 = '1' else scroll_1;
|
||||
|
||||
shift_reg_32 <= (shift_pbyte(15 downto 8) & shift_abyte(15 downto 8) & shift_pbyte(7 downto 0) & shift_abyte(7 downto 0)) when shift_screen_mode(2) = '1' else
|
||||
(shift_pbyte(15) & shift_pbyte(15) & shift_pbyte(14) & shift_pbyte(14) & shift_pbyte(13) & shift_pbyte(13) & shift_pbyte(12) & shift_pbyte(12) &
|
||||
shift_pbyte(11) & shift_pbyte(11) & shift_pbyte(10) & shift_pbyte(10) & shift_pbyte(9) & shift_pbyte(9) & shift_pbyte(8) & shift_pbyte(8) &
|
||||
shift_pbyte(7) & shift_pbyte(7) & shift_pbyte(6) & shift_pbyte(6) & shift_pbyte(5) & shift_pbyte(5) & shift_pbyte(4) & shift_pbyte(4) &
|
||||
shift_pbyte(3) & shift_pbyte(3) & shift_pbyte(2) & shift_pbyte(2) & shift_pbyte(1) & shift_pbyte(1) & shift_pbyte(0) & shift_pbyte(0));
|
||||
|
||||
shift_reg_ld <= std_logic_vector(shift_left(unsigned(shift_reg_32), to_integer(unsigned(shift_scroll))));
|
||||
|
||||
process (i_CLK_14)
|
||||
begin
|
||||
if rising_edge(i_CLK_14) then
|
||||
if sload = '1' then
|
||||
shift_reg <= shift_reg_ld(31 downto 16);
|
||||
else
|
||||
shift_reg <= shift_reg(14 downto 0) & '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--
|
||||
-- ATTRIBUTE REGISTER
|
||||
--
|
||||
|
||||
-- Indicate when second attribute byte should be used
|
||||
|
||||
border_active_v <= i_vc(8) or (i_vc(7) and i_vc(6));
|
||||
border_active <= i_phc(8) or border_active_v;
|
||||
border_active_ula <= i_hc(8) or border_active_v;
|
||||
|
||||
border_clr <= "00" & i_port_fe_border & i_port_fe_border;
|
||||
border_clr_tmx <= "01" & (not i_port_ff_reg(5 downto 3)) & i_port_ff_reg(5 downto 3);
|
||||
|
||||
process (i_CLK_14)
|
||||
begin
|
||||
if rising_edge(i_CLK_14) then
|
||||
if sload = '1' then
|
||||
|
||||
if shift_screen_mode(2) = '1' then
|
||||
attr_reg <= border_clr_tmx & border_clr_tmx;
|
||||
elsif border_active = '1' then
|
||||
attr_reg <= border_clr & border_clr;
|
||||
else
|
||||
attr_reg <= shift_abyte;
|
||||
end if;
|
||||
|
||||
attr_scroll_r <= '0' & shift_scroll;
|
||||
screen_mode_r <= shift_screen_mode;
|
||||
|
||||
else
|
||||
|
||||
if attr_scroll_r(4) = '0' then
|
||||
attr_scroll_r <= attr_scroll_r + 1;
|
||||
end if;
|
||||
|
||||
if i_timing_pentagon = '1' and border_active = '1' then
|
||||
if screen_mode_r(2) = '1' then
|
||||
attr_reg <= border_clr_tmx & border_clr_tmx;
|
||||
else
|
||||
attr_reg <= border_clr & border_clr;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
attr_active <= attr_reg(15 downto 8) when attr_scroll_r(4) = '0' else attr_reg(7 downto 0);
|
||||
|
||||
--
|
||||
-- GENERATE RGB PIXEL OUT
|
||||
--
|
||||
|
||||
-- Delay border turn off signal by half a pixel
|
||||
|
||||
process (i_CLK_14)
|
||||
begin
|
||||
if rising_edge(i_CLK_14) then
|
||||
border_active_d <= border_active;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
pixel_en <= (shift_reg(15) xor (attr_active(7) and flash_cnt(4) and (not i_ulanext_en) and not i_ulap_en)) and not border_active_d;
|
||||
|
||||
-- Flash Counter
|
||||
|
||||
process (i_CLK_7)
|
||||
begin
|
||||
if rising_edge(i_CLK_7) then
|
||||
if i_hc = ('0' & X"00") and i_vc = ('0' & X"00") then
|
||||
flash_cnt <= flash_cnt + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Standard ULA, ULAnext, ULA+
|
||||
|
||||
process (i_CLK_14)
|
||||
constant paper_base_index : std_logic_vector(7 downto 0) := "10000000";
|
||||
begin
|
||||
if falling_edge(i_CLK_14) then
|
||||
|
||||
ula_select_bgnd <= '0';
|
||||
|
||||
if i_ulanext_en = '1' then
|
||||
|
||||
-- ULAnext
|
||||
|
||||
if border_active_d = '1' then
|
||||
|
||||
-- border
|
||||
|
||||
if i_ulanext_format = X"FF" then
|
||||
ula_select_bgnd <= '1';
|
||||
end if;
|
||||
|
||||
ula_pixel <= paper_base_index(7 downto 3) & attr_active(5 downto 3);
|
||||
|
||||
elsif pixel_en = '1' then
|
||||
|
||||
-- ink
|
||||
|
||||
ula_pixel <= attr_active and i_ulanext_format;
|
||||
|
||||
else
|
||||
|
||||
-- paper
|
||||
|
||||
case i_ulanext_format is
|
||||
|
||||
when X"01" => ula_pixel <= paper_base_index(7) & attr_active(7 downto 1);
|
||||
when X"03" => ula_pixel <= paper_base_index(7 downto 6) & attr_active(7 downto 2);
|
||||
when X"07" => ula_pixel <= paper_base_index(7 downto 5) & attr_active(7 downto 3);
|
||||
when X"0F" => ula_pixel <= paper_base_index(7 downto 4) & attr_active(7 downto 4);
|
||||
when X"1F" => ula_pixel <= paper_base_index(7 downto 3) & attr_active(7 downto 5);
|
||||
when X"3F" => ula_pixel <= paper_base_index(7 downto 2) & attr_active(7 downto 6);
|
||||
when X"7F" => ula_pixel <= paper_base_index(7 downto 1) & attr_active(7);
|
||||
when others => ula_select_bgnd <= '1';
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
|
||||
elsif i_ulap_en = '1' then
|
||||
|
||||
-- ULA+
|
||||
|
||||
ula_pixel(7 downto 3) <= "11" & attr_active(7 downto 6) & (screen_mode_r(2) or not pixel_en);
|
||||
|
||||
if pixel_en = '1' then
|
||||
ula_pixel(2 downto 0) <= attr_active(2 downto 0);
|
||||
else
|
||||
ula_pixel(2 downto 0) <= attr_active(5 downto 3);
|
||||
end if;
|
||||
|
||||
else
|
||||
|
||||
-- Standard ULA
|
||||
|
||||
ula_pixel(7 downto 3) <= "000" & not pixel_en & attr_active(6);
|
||||
|
||||
if pixel_en = '1' then
|
||||
ula_pixel(2 downto 0) <= attr_active(2 downto 0);
|
||||
else
|
||||
ula_pixel(2 downto 0) <= attr_active(5 downto 3);
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Pixel Out
|
||||
|
||||
o_ula_clipped <= '0' when (i_phc >= i_ula_clip_x1 and i_phc <= i_ula_clip_x2 and i_vc >= i_ula_clip_y1 and i_vc <= i_ula_clip_y2) or border_active = '1' else '1';
|
||||
|
||||
o_ula_pixel <= ula_pixel;
|
||||
o_ula_select_bgnd <= ula_select_bgnd;
|
||||
|
||||
o_ula_border <= border_active; -- border_active_d ??
|
||||
|
||||
--
|
||||
-- FLOATING BUS
|
||||
--
|
||||
|
||||
o_ula_floating_bus <= (floating_bus_r(7 downto 1) & (floating_bus_r(0) or i_timing_p3)) when (border_active_ula = '0' and floating_bus_en = '1') else i_p3_floating_bus when i_timing_p3 = '1' else X"FF";
|
||||
|
||||
--
|
||||
-- CPU CONTENTION
|
||||
--
|
||||
|
||||
-- the zx next is a synchronous machine and decides whether the z80 clock will be allowed to go low in the previous i_hc cycle (contend 3-14)
|
||||
-- the original spectrums are combinatorial, they will OR a one into the clock in the current cycle (contend 4-15)
|
||||
|
||||
hc_adj <= i_hc(3 downto 0) + 1;
|
||||
wait_s <= '1' when ((hc_adj(3 downto 2) /= "00") or (hc_adj(3 downto 1) = "000" and i_timing_p3 = '1')) and i_hc(8) = '0' and border_active_v = '0' and i_contention_en = '1' else '0';
|
||||
|
||||
-- 48k / 128k
|
||||
|
||||
process (i_CLK_CPU)
|
||||
begin
|
||||
if rising_edge(i_CLK_CPU) then
|
||||
mreq23_n <= i_cpu_mreq_n;
|
||||
ioreqtw3_n <= i_cpu_iorq_n;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
o_cpu_contend <= '1' when ((i_contention_memory = '1' and mreq23_n = '1') or (i_contention_port = '1' and i_cpu_iorq_n = '0' and ioreqtw3_n = '1')) and i_timing_p3 = '0' and wait_s = '1' else '0';
|
||||
|
||||
-- +3
|
||||
|
||||
-- o_cpu_wait_n <= '0' when ((i_cpu_mreq_n = '0' and i_contention_memory = '1') or (i_cpu_iorq_n = '0' and i_contention_port = '1')) and i_timing_p3 = '1' and wait_s = '1' else '1';
|
||||
o_cpu_wait_n <= '0' when (i_cpu_mreq_n = '0' and i_contention_memory = '1') and i_timing_p3 = '1' and wait_s = '1' else '1';
|
||||
|
||||
end architecture;
|
||||
471
rtl/video/zxula_timing.vhd
Normal file
471
rtl/video/zxula_timing.vhd
Normal file
@@ -0,0 +1,471 @@
|
||||
|
||||
-- ZX Spectrum Next Video Timing Module
|
||||
--
|
||||
-- Copyright 2017 superfo, mcleod, avillena (ZX UNO Project)
|
||||
-- Copyright 2020 Fabio Belavenuto, Alvin Albrecht
|
||||
--
|
||||
-- This file is part of the ZX Spectrum Next Project
|
||||
-- <https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/tree/master/cores>
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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.
|
||||
--
|
||||
-- The ZX Spectrum Next FPGA source code 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 the ZX Spectrum Next FPGA source code. If not, see
|
||||
-- <https://www.gnu.org/licenses/>.
|
||||
--
|
||||
|
||||
-- Original pal_sync_generator.v from the ZX UNO project:
|
||||
-- <https://github.com/yomboprime/zxuno-addons/blob/master/test24_uart/common/pal_sync_generator.v>
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity zxula_timing is
|
||||
port (
|
||||
clock_i : in std_logic;
|
||||
clock_x4_i : in std_logic;
|
||||
reset_conter_i : in std_logic;
|
||||
mode_i : in std_logic_vector(2 downto 0);
|
||||
video_timing_i : in std_logic_vector(2 downto 0);
|
||||
vf50_60_i : in std_logic;
|
||||
cu_offset_i : in std_logic_vector(7 downto 0);
|
||||
hcount_o : out unsigned(8 downto 0);
|
||||
vcount_o : out unsigned(8 downto 0);
|
||||
phcount_o : out unsigned(8 downto 0);
|
||||
whcount_o : out unsigned(8 downto 0);
|
||||
wvcount_o : out unsigned(8 downto 0);
|
||||
cvcount_o : out unsigned(8 downto 0);
|
||||
sc_o : out std_logic_vector(1 downto 0);
|
||||
hsync_n_o : out std_logic;
|
||||
vsync_n_o : out std_logic;
|
||||
hblank_n_o : out std_logic;
|
||||
vblank_n_o : out std_logic;
|
||||
lint_ctrl_i : in std_logic_vector(1 downto 0);
|
||||
lint_line_i : in std_logic_vector(8 downto 0);
|
||||
ula_int_o : out std_logic;
|
||||
line_int_o : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture Behavior of zxula_timing is
|
||||
|
||||
signal hc_s : unsigned(8 downto 0);
|
||||
signal vc_s : unsigned(8 downto 0);
|
||||
signal phc_s : unsigned(8 downto 0);
|
||||
signal whc_s : unsigned(8 downto 0);
|
||||
signal wvc_s : unsigned(8 downto 0);
|
||||
signal cvc_s : unsigned(8 downto 0);
|
||||
signal whc_lsb_d : std_logic;
|
||||
signal sc_s : std_logic_vector(1 downto 0);
|
||||
|
||||
signal max_hc_s : std_logic;
|
||||
signal max_vc_s : std_logic;
|
||||
signal max_cvc_s : std_logic;
|
||||
signal max_whc_s : std_logic;
|
||||
|
||||
signal int_ula_s : std_logic;
|
||||
signal int_lint_s : std_logic;
|
||||
|
||||
signal c_max_hc_s : unsigned(8 downto 0);
|
||||
signal c_max_vc_s : unsigned(8 downto 0);
|
||||
signal c_vblank_min_s : unsigned(8 downto 0);
|
||||
signal c_vblank_max_s : unsigned(8 downto 0);
|
||||
signal c_hblank_min_s : unsigned(8 downto 0);
|
||||
signal c_hblank_max_s : unsigned(8 downto 0);
|
||||
signal c_vsync_min_s : unsigned(8 downto 0);
|
||||
signal c_vsync_max_s : unsigned(8 downto 0);
|
||||
signal c_hsync_min_s : unsigned(8 downto 0);
|
||||
signal c_hsync_max_s : unsigned(8 downto 0);
|
||||
signal c_int_h_s : unsigned(8 downto 0);
|
||||
signal c_int_v_s : unsigned(8 downto 0);
|
||||
|
||||
signal vblank_top_cancel : std_logic;
|
||||
signal vblank_bottom_cancel : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
--
|
||||
process (mode_i, vf50_60_i, video_timing_i)
|
||||
begin
|
||||
-- Modeline "720x576x50hz" 27 720 732 796 864 576 581 586 625
|
||||
-- 360 366 398 432 288 290 293 312
|
||||
-- ModeLine "720x480@60" 27 720 736 798 858 480 489 495 525
|
||||
-- 360 368 399 429 240 244 247 262
|
||||
if video_timing_i = "111" then
|
||||
|
||||
-- HDMI
|
||||
|
||||
-- Investigate later.. these numbers were chosen to agree with most hdmi tvs.
|
||||
|
||||
if vf50_60_i = '0' then
|
||||
|
||||
-- 50 Hz
|
||||
|
||||
c_hblank_min_s <= to_unsigned(360-37, 9); -- -37 ok
|
||||
c_hsync_min_s <= to_unsigned(366-37, 9);
|
||||
c_hsync_max_s <= to_unsigned(398-37, 9);
|
||||
c_hblank_max_s <= to_unsigned(431-37, 9);
|
||||
c_int_h_s <= to_unsigned(4, 9);
|
||||
c_max_hc_s <= to_unsigned(431, 9);
|
||||
|
||||
c_vblank_min_s <= to_unsigned(248+8-1, 9);-- +8 ok
|
||||
c_vsync_min_s <= to_unsigned(248+8, 9);
|
||||
c_vsync_max_s <= to_unsigned(251+8, 9);
|
||||
c_vblank_max_s <= to_unsigned(255+8, 9);
|
||||
c_int_v_s <= to_unsigned(248+8, 9);
|
||||
c_max_vc_s <= to_unsigned(311, 9);
|
||||
|
||||
else
|
||||
|
||||
-- 60 Hz
|
||||
|
||||
c_hblank_min_s <= to_unsigned(360-37, 9); -- -37 ok
|
||||
|
||||
c_hsync_min_s <= to_unsigned(368-37, 9);
|
||||
c_hsync_max_s <= to_unsigned(399-37, 9);
|
||||
c_hblank_max_s <= to_unsigned(428-37, 9);
|
||||
c_int_h_s <= to_unsigned(4, 9);
|
||||
c_max_hc_s <= to_unsigned(428, 9);
|
||||
|
||||
c_vblank_min_s <= to_unsigned(240-9-1, 9); -- -9 ok
|
||||
c_vsync_min_s <= to_unsigned(244-9, 9);
|
||||
c_vsync_max_s <= to_unsigned(247-9, 9);
|
||||
c_vblank_max_s <= to_unsigned(247-9, 9);
|
||||
c_int_v_s <= to_unsigned(244-9, 9);
|
||||
c_max_vc_s <= to_unsigned(261, 9);
|
||||
|
||||
end if;
|
||||
|
||||
elsif mode_i = "000" or mode_i = "001" then
|
||||
|
||||
-- 48k
|
||||
|
||||
c_hblank_min_s <= to_unsigned(320, 9);
|
||||
c_hsync_min_s <= to_unsigned(344, 9);
|
||||
c_hsync_max_s <= to_unsigned(375, 9);
|
||||
c_hblank_max_s <= to_unsigned(415, 9);
|
||||
c_int_h_s <= to_unsigned(0, 9);
|
||||
c_max_hc_s <= to_unsigned(447, 9);
|
||||
|
||||
if vf50_60_i = '0' then
|
||||
|
||||
-- 50 Hz
|
||||
|
||||
c_vblank_min_s <= to_unsigned(248-1, 9);
|
||||
c_vblank_max_s <= to_unsigned(255, 9);
|
||||
c_vsync_min_s <= to_unsigned(248, 9);
|
||||
c_vsync_max_s <= to_unsigned(251, 9);
|
||||
c_int_v_s <= to_unsigned(248, 9);
|
||||
c_max_vc_s <= to_unsigned(311, 9);
|
||||
|
||||
else
|
||||
|
||||
-- 60 Hz
|
||||
|
||||
c_vblank_min_s <= to_unsigned(224-1, 9);
|
||||
c_vsync_min_s <= to_unsigned(224, 9);
|
||||
c_vsync_max_s <= to_unsigned(227, 9);
|
||||
c_vblank_max_s <= to_unsigned(231, 9);
|
||||
c_int_v_s <= to_unsigned(224, 9);
|
||||
c_max_vc_s <= to_unsigned(263, 9);
|
||||
|
||||
end if;
|
||||
|
||||
elsif mode_i = "010" or mode_i = "011" then
|
||||
|
||||
-- 128k, +3
|
||||
|
||||
c_hblank_min_s <= to_unsigned(320, 9);
|
||||
c_hsync_min_s <= to_unsigned(344, 9);
|
||||
c_hsync_max_s <= to_unsigned(375, 9);
|
||||
c_hblank_max_s <= to_unsigned(415, 9);
|
||||
|
||||
if mode_i = "010" then
|
||||
|
||||
-- 128k
|
||||
|
||||
c_int_h_s <= to_unsigned(4, 9); -- 8
|
||||
|
||||
else
|
||||
|
||||
-- +3
|
||||
|
||||
c_int_h_s <= to_unsigned(2, 9);
|
||||
|
||||
end if;
|
||||
|
||||
c_max_hc_s <= to_unsigned(455, 9);
|
||||
|
||||
if vf50_60_i = '0' then
|
||||
|
||||
-- 50 Hz
|
||||
|
||||
c_vblank_min_s <= to_unsigned(248-1, 9);
|
||||
c_vsync_min_s <= to_unsigned(248, 9);
|
||||
c_vsync_max_s <= to_unsigned(251, 9);
|
||||
c_vblank_max_s <= to_unsigned(255, 9);
|
||||
c_int_v_s <= to_unsigned(248, 9);
|
||||
c_max_vc_s <= to_unsigned(310, 9);
|
||||
|
||||
else
|
||||
|
||||
-- 60 Hz
|
||||
|
||||
c_vblank_min_s <= to_unsigned(224-1, 9);
|
||||
c_vsync_min_s <= to_unsigned(224, 9);
|
||||
c_vsync_max_s <= to_unsigned(227, 9);
|
||||
c_vblank_max_s <= to_unsigned(231, 9);
|
||||
c_int_v_s <= to_unsigned(224, 9);
|
||||
c_max_vc_s <= to_unsigned(263, 9);
|
||||
|
||||
end if;
|
||||
|
||||
else
|
||||
|
||||
-- Pentagon
|
||||
|
||||
c_hblank_min_s <= to_unsigned(336, 9); -- 336, 320
|
||||
c_hsync_min_s <= to_unsigned(336, 9); -- 336, 320
|
||||
c_hsync_max_s <= to_unsigned(367, 9); -- 367, 351
|
||||
c_hblank_max_s <= to_unsigned(399, 9); -- 399, 383
|
||||
c_int_h_s <= to_unsigned(323, 9); -- 323, 320
|
||||
c_max_hc_s <= to_unsigned(447, 9); -- 447, 447
|
||||
|
||||
-- There is no 60Hz Pentagon
|
||||
|
||||
c_vblank_min_s <= to_unsigned(240-1, 9);
|
||||
c_vsync_min_s <= to_unsigned(240, 9);
|
||||
c_vsync_max_s <= to_unsigned(255, 9);
|
||||
c_vblank_max_s <= to_unsigned(256, 9); -- 271
|
||||
c_int_v_s <= to_unsigned(239, 9); -- 240, 239
|
||||
c_max_vc_s <= to_unsigned(319, 9);
|
||||
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
-- Signals generation
|
||||
|
||||
vblank_top_cancel <= '1' when vc_s = c_vblank_max_s and hc_s >= c_hblank_min_s else '0';
|
||||
vblank_bottom_cancel <= '1' when vc_s = c_vblank_min_s and hc_s < c_hblank_min_s else '0';
|
||||
|
||||
process (hc_s, vc_s, c_hblank_min_s, c_hblank_max_s, c_vblank_min_s, c_vblank_max_s,
|
||||
c_hsync_min_s, c_hsync_max_s, c_vsync_min_s, c_vsync_max_s, vblank_top_cancel, vblank_bottom_cancel)
|
||||
begin
|
||||
hblank_n_o <= '1';
|
||||
vblank_n_o <= '1';
|
||||
hsync_n_o <= '1';
|
||||
vsync_n_o <= '1';
|
||||
|
||||
-- HBlank
|
||||
if hc_s >= c_hblank_min_s and hc_s <= c_hblank_max_s then
|
||||
hblank_n_o <= '0';
|
||||
end if;
|
||||
-- VBlank
|
||||
if vc_s >= c_vblank_min_s and vc_s <= c_vblank_max_s then
|
||||
vblank_n_o <= vblank_top_cancel or vblank_bottom_cancel;
|
||||
end if;
|
||||
-- HSync
|
||||
if hc_s >= c_hsync_min_s and hc_s <= c_hsync_max_s then
|
||||
hsync_n_o <= '0';
|
||||
end if;
|
||||
-- VSync
|
||||
if vc_s >= c_vsync_min_s and vc_s <= c_vsync_max_s then
|
||||
vsync_n_o <= '0';
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
-- INT pulse generation, lasts one 7MHz period
|
||||
|
||||
process (hc_s, vc_s, cvc_s, c_int_v_s, c_int_h_s, max_cvc_s, lint_line_i, lint_ctrl_i)
|
||||
|
||||
variable lint_minus_one_v : unsigned(8 downto 0);
|
||||
begin
|
||||
|
||||
int_ula_s <= '0';
|
||||
int_lint_s <= '0';
|
||||
lint_minus_one_v := unsigned(lint_line_i) - 1;
|
||||
|
||||
if lint_ctrl_i(0) = '1' then
|
||||
if vc_s = c_int_v_s and hc_s = c_int_h_s then
|
||||
int_ula_s <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if lint_ctrl_i(1) = '1' and hc_s = 256 then
|
||||
if lint_line_i = 0 then
|
||||
if max_cvc_s = '1' then
|
||||
int_lint_s <= '1';
|
||||
end if;
|
||||
elsif cvc_s = lint_minus_one_v then
|
||||
int_lint_s <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
ula_int_o <= int_ula_s;
|
||||
line_int_o <= int_lint_s;
|
||||
|
||||
-- Pixel position counters
|
||||
|
||||
-- All timing refers to the ULA counter as implemented in the original hardware.
|
||||
-- The ULA produces its first pixel in the 256 pixel wide area during count 12.
|
||||
|
||||
-- Practical counters are generated for other modules that count the actual pixel
|
||||
-- position being generated in the current cycle as well as delivering negative values
|
||||
-- leading up to pixel zero.
|
||||
|
||||
-- ULA counter, pixel 0 is generated in cycle 12
|
||||
|
||||
max_hc_s <= '1' when hc_s = c_max_hc_s else '0';
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_conter_i = '1' then
|
||||
hc_s <= (others => '0');
|
||||
elsif max_hc_s = '1' then
|
||||
hc_s <= (others => '0');
|
||||
else
|
||||
hc_s <= hc_s + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
max_vc_s <= '1' when vc_s = c_max_vc_s else '0';
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_conter_i = '1' then
|
||||
vc_s <= c_vsync_min_s;
|
||||
elsif max_hc_s = '1' then
|
||||
if max_vc_s = '1' then
|
||||
vc_s <= (others => '0');
|
||||
else
|
||||
vc_s <= vc_s + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Copper offset vertical counter
|
||||
|
||||
max_cvc_s <= '1' when cvc_s = c_max_vc_s else '0';
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_conter_i = '1' then
|
||||
cvc_s <= c_vsync_min_s;
|
||||
elsif max_hc_s = '1' then
|
||||
if max_vc_s = '1' then
|
||||
cvc_s <= unsigned('0' & cu_offset_i);
|
||||
elsif max_cvc_s = '1' then
|
||||
cvc_s <= (others => '0');
|
||||
else
|
||||
cvc_s <= cvc_s + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Practical wide counters. (0,0) corresponds to (-32,-32) for the 320 x 256 surface
|
||||
|
||||
max_whc_s <= '1' when hc_s = (c_max_hc_s - 32+12-16) else '0';
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_conter_i = '1' then
|
||||
whc_s <= (others => '0');
|
||||
elsif max_whc_s = '1' then
|
||||
whc_s <= "111110000"; -- starting at -16
|
||||
else
|
||||
whc_s <= whc_s + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_conter_i = '1' then
|
||||
wvc_s <= to_unsigned(256, 9);
|
||||
elsif max_whc_s = '1' then
|
||||
if vc_s = (c_max_vc_s - 32-2) then
|
||||
wvc_s <= "111111110"; -- starting at -2
|
||||
else
|
||||
wvc_s <= wvc_s + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Practical 256 horizontal counter. 0 corresponds to pixel x=0 on the 256 x 192 surface
|
||||
|
||||
process (clock_i)
|
||||
begin
|
||||
if rising_edge(clock_i) then
|
||||
if reset_conter_i = '1' then
|
||||
phc_s <= (others => '0');
|
||||
elsif max_whc_s = '1' then
|
||||
phc_s <= "111010000"; -- starting at -48
|
||||
else
|
||||
phc_s <= phc_s + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 28MHZ sub-pixel counter
|
||||
|
||||
process (clock_x4_i)
|
||||
begin
|
||||
if rising_edge(clock_x4_i) then
|
||||
if reset_conter_i = '1' then
|
||||
whc_lsb_d <= '0';
|
||||
else
|
||||
whc_lsb_d <= whc_s(0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clock_x4_i)
|
||||
begin
|
||||
if rising_edge(clock_x4_i) then
|
||||
if reset_conter_i = '1' then
|
||||
sc_s <= (others => '0');
|
||||
elsif whc_s(0) /= whc_lsb_d then
|
||||
sc_s <= "01";
|
||||
else
|
||||
sc_s <= sc_s + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--
|
||||
|
||||
hcount_o <= hc_s;
|
||||
vcount_o <= vc_s;
|
||||
|
||||
phcount_o <= phc_s;
|
||||
|
||||
whcount_o <= whc_s;
|
||||
wvcount_o <= wvc_s;
|
||||
cvcount_o <= cvc_s;
|
||||
|
||||
sc_o <= sc_s;
|
||||
|
||||
end architecture;
|
||||
6939
rtl/zxnext.vhd
Normal file
6939
rtl/zxnext.vhd
Normal file
File diff suppressed because it is too large
Load Diff
157
sys/alsa.sv
Normal file
157
sys/alsa.sv
Normal file
@@ -0,0 +1,157 @@
|
||||
//============================================================================
|
||||
//
|
||||
// ALSA sound support for MiSTer
|
||||
// (c)2019,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; 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 alsa
|
||||
#(
|
||||
parameter CLK_RATE = 24576000
|
||||
)
|
||||
(
|
||||
input reset,
|
||||
input clk,
|
||||
|
||||
output reg [31:3] ram_address,
|
||||
input [63:0] ram_data,
|
||||
output reg ram_req = 0,
|
||||
input ram_ready,
|
||||
|
||||
input spi_ss,
|
||||
input spi_sck,
|
||||
input spi_mosi,
|
||||
output spi_miso,
|
||||
|
||||
output reg [15:0] pcm_l,
|
||||
output reg [15:0] pcm_r
|
||||
);
|
||||
|
||||
reg [60:0] buf_info;
|
||||
reg [6:0] spicnt = 0;
|
||||
always @(posedge spi_sck, posedge spi_ss) begin
|
||||
reg [95:0] spi_data;
|
||||
|
||||
if(spi_ss) spicnt <= 0;
|
||||
else begin
|
||||
spi_data[{spicnt[6:3],~spicnt[2:0]}] <= spi_mosi;
|
||||
if(&spicnt) buf_info <= {spi_data[82:67],spi_data[50:35],spi_data[31:3]};
|
||||
spicnt <= spicnt + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
assign spi_miso = spi_out[{spicnt[4:3],~spicnt[2:0]}];
|
||||
|
||||
reg [31:0] spi_out = 0;
|
||||
always @(posedge clk) if(spi_ss) spi_out <= {buf_rptr, hurryup, 8'h00};
|
||||
|
||||
|
||||
reg [31:3] buf_addr;
|
||||
reg [18:3] buf_len;
|
||||
reg [18:3] buf_wptr = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [60:0] data1,data2;
|
||||
|
||||
data1 <= buf_info;
|
||||
data2 <= data1;
|
||||
if(data2 == data1) {buf_wptr,buf_len,buf_addr} <= data2;
|
||||
end
|
||||
|
||||
reg [2:0] hurryup = 0;
|
||||
reg [18:3] buf_rptr = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [18:3] len = 0;
|
||||
reg [1:0] ready = 0;
|
||||
reg [63:0] readdata;
|
||||
reg got_first = 0;
|
||||
reg [7:0] ce_cnt = 0;
|
||||
reg [1:0] state = 0;
|
||||
|
||||
if(reset) begin
|
||||
ready <= 0;
|
||||
ce_cnt <= 0;
|
||||
state <= 0;
|
||||
got_first <= 0;
|
||||
len <= 0;
|
||||
end
|
||||
else begin
|
||||
|
||||
//ramp up
|
||||
if(len[18:14] && (hurryup < 1)) hurryup <= 1;
|
||||
if(len[18:16] && (hurryup < 2)) hurryup <= 2;
|
||||
if(len[18:17] && (hurryup < 4)) hurryup <= 4;
|
||||
|
||||
//ramp down
|
||||
if(!len[18:15] && (hurryup > 2)) hurryup <= 2;
|
||||
if(!len[18:13] && (hurryup > 1)) hurryup <= 1;
|
||||
if(!len[18:10]) hurryup <= 0;
|
||||
|
||||
if(ce_sample && ~&ce_cnt) ce_cnt <= ce_cnt + 1'd1;
|
||||
|
||||
case(state)
|
||||
0: if(!ce_sample) begin
|
||||
if(ready) begin
|
||||
if(ce_cnt) begin
|
||||
{readdata[31:0],pcm_r,pcm_l} <= readdata;
|
||||
ready <= ready - 1'd1;
|
||||
ce_cnt <= ce_cnt - 1'd1;
|
||||
end
|
||||
end
|
||||
else if(buf_rptr != buf_wptr) begin
|
||||
if(~got_first) begin
|
||||
buf_rptr <= buf_wptr;
|
||||
got_first <= 1;
|
||||
end
|
||||
else begin
|
||||
ram_address <= buf_addr + buf_rptr;
|
||||
ram_req <= ~ram_req;
|
||||
buf_rptr <= buf_rptr + 1'd1;
|
||||
len <= (buf_wptr < buf_rptr) ? (buf_len + buf_wptr - buf_rptr) : (buf_wptr - buf_rptr);
|
||||
state <= 1;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
len <= 0;
|
||||
ce_cnt <= 0;
|
||||
hurryup <= 0;
|
||||
end
|
||||
end
|
||||
1: if(ram_ready) begin
|
||||
ready <= 2;
|
||||
readdata <= ram_data;
|
||||
if(buf_rptr >= buf_len) buf_rptr <= buf_rptr - buf_len;
|
||||
state <= 0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
reg ce_sample;
|
||||
always @(posedge clk) begin
|
||||
reg [31:0] acc = 0;
|
||||
|
||||
ce_sample <= 0;
|
||||
acc <= acc + 48000 + {hurryup,6'd0};
|
||||
if(acc >= CLK_RATE) begin
|
||||
acc <= acc - CLK_RATE;
|
||||
ce_sample <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
302
sys/arcade_video.v
Normal file
302
sys/arcade_video.v
Normal file
@@ -0,0 +1,302 @@
|
||||
//============================================================================
|
||||
//
|
||||
// Copyright (C) 2017-2020 Sorgelig
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// DW:
|
||||
// 6 : 2R 2G 2B
|
||||
// 8 : 3R 3G 2B
|
||||
// 9 : 3R 3G 3B
|
||||
// 12 : 4R 4G 4B
|
||||
// 24 : 8R 8G 8B
|
||||
|
||||
module arcade_video #(parameter WIDTH=320, DW=8, GAMMA=1)
|
||||
(
|
||||
input clk_video,
|
||||
input ce_pix,
|
||||
|
||||
input[DW-1:0] RGB_in,
|
||||
input HBlank,
|
||||
input VBlank,
|
||||
input HSync,
|
||||
input VSync,
|
||||
|
||||
output CLK_VIDEO,
|
||||
output CE_PIXEL,
|
||||
output [7:0] VGA_R,
|
||||
output [7:0] VGA_G,
|
||||
output [7:0] VGA_B,
|
||||
output VGA_HS,
|
||||
output VGA_VS,
|
||||
output VGA_DE,
|
||||
output [1:0] VGA_SL,
|
||||
|
||||
input [2:0] fx,
|
||||
input forced_scandoubler,
|
||||
inout [21:0] gamma_bus
|
||||
);
|
||||
|
||||
assign CLK_VIDEO = clk_video;
|
||||
|
||||
wire hs_fix,vs_fix;
|
||||
sync_fix sync_v(CLK_VIDEO, HSync, hs_fix);
|
||||
sync_fix sync_h(CLK_VIDEO, VSync, vs_fix);
|
||||
|
||||
reg [DW-1:0] RGB_fix;
|
||||
|
||||
reg CE,HS,VS,HBL,VBL;
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg old_ce;
|
||||
old_ce <= ce_pix;
|
||||
CE <= 0;
|
||||
if(~old_ce & ce_pix) begin
|
||||
CE <= 1;
|
||||
HS <= hs_fix;
|
||||
if(~HS & hs_fix) VS <= vs_fix;
|
||||
|
||||
RGB_fix <= RGB_in;
|
||||
HBL <= HBlank;
|
||||
if(HBL & ~HBlank) VBL <= VBlank;
|
||||
end
|
||||
end
|
||||
|
||||
wire [7:0] R,G,B;
|
||||
|
||||
generate
|
||||
if(DW == 6) begin
|
||||
assign R = {RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4]};
|
||||
assign G = {RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2]};
|
||||
assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]};
|
||||
end
|
||||
else if(DW == 8) begin
|
||||
assign R = {RGB_fix[7:5],RGB_fix[7:5],RGB_fix[7:6]};
|
||||
assign G = {RGB_fix[4:2],RGB_fix[4:2],RGB_fix[4:3]};
|
||||
assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]};
|
||||
end
|
||||
else if(DW == 9) begin
|
||||
assign R = {RGB_fix[8:6],RGB_fix[8:6],RGB_fix[8:7]};
|
||||
assign G = {RGB_fix[5:3],RGB_fix[5:3],RGB_fix[5:4]};
|
||||
assign B = {RGB_fix[2:0],RGB_fix[2:0],RGB_fix[2:1]};
|
||||
end
|
||||
else if(DW == 12) begin
|
||||
assign R = {RGB_fix[11:8],RGB_fix[11:8]};
|
||||
assign G = {RGB_fix[7:4],RGB_fix[7:4]};
|
||||
assign B = {RGB_fix[3:0],RGB_fix[3:0]};
|
||||
end
|
||||
else begin // 24
|
||||
assign R = RGB_fix[23:16];
|
||||
assign G = RGB_fix[15:8];
|
||||
assign B = RGB_fix[7:0];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign VGA_SL = sl[1:0];
|
||||
wire [2:0] sl = fx ? fx - 1'd1 : 3'd0;
|
||||
wire scandoubler = fx || forced_scandoubler;
|
||||
|
||||
video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer
|
||||
(
|
||||
.CLK_VIDEO(CLK_VIDEO),
|
||||
.ce_pix(CE),
|
||||
.CE_PIXEL(CE_PIXEL),
|
||||
|
||||
.scandoubler(scandoubler),
|
||||
.hq2x(fx==1),
|
||||
.gamma_bus(gamma_bus),
|
||||
|
||||
.R((DW!=24) ? R[7:4] : R),
|
||||
.G((DW!=24) ? G[7:4] : G),
|
||||
.B((DW!=24) ? B[7:4] : B),
|
||||
|
||||
.HSync (HS),
|
||||
.VSync (VS),
|
||||
.HBlank(HBL),
|
||||
.VBlank(VBL),
|
||||
|
||||
.VGA_R(VGA_R),
|
||||
.VGA_G(VGA_G),
|
||||
.VGA_B(VGA_B),
|
||||
.VGA_VS(VGA_VS),
|
||||
.VGA_HS(VGA_HS),
|
||||
.VGA_DE(VGA_DE)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Screen +90/-90 deg. rotation
|
||||
// Copyright (C) 2020 Sorgelig
|
||||
//
|
||||
// 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 screen_rotate
|
||||
(
|
||||
input CLK_VIDEO,
|
||||
input CE_PIXEL,
|
||||
|
||||
input [7:0] VGA_R,
|
||||
input [7:0] VGA_G,
|
||||
input [7:0] VGA_B,
|
||||
input VGA_HS,
|
||||
input VGA_VS,
|
||||
input VGA_DE,
|
||||
|
||||
input rotate_ccw,
|
||||
input no_rotate,
|
||||
|
||||
output FB_EN,
|
||||
output [4:0] FB_FORMAT,
|
||||
output [11:0] FB_WIDTH,
|
||||
output [11:0] FB_HEIGHT,
|
||||
output [31:0] FB_BASE,
|
||||
output [13:0] FB_STRIDE,
|
||||
input FB_VBL,
|
||||
input FB_LL,
|
||||
|
||||
output DDRAM_CLK,
|
||||
input DDRAM_BUSY,
|
||||
output [7:0] DDRAM_BURSTCNT,
|
||||
output [28:0] DDRAM_ADDR,
|
||||
output [63:0] DDRAM_DIN,
|
||||
output [7:0] DDRAM_BE,
|
||||
output DDRAM_WE,
|
||||
output DDRAM_RD
|
||||
);
|
||||
|
||||
parameter MEM_BASE = 7'b0010010; // buffer at 0x24000000, 3x8MB
|
||||
|
||||
assign DDRAM_CLK = CLK_VIDEO;
|
||||
assign DDRAM_BURSTCNT = 1;
|
||||
assign DDRAM_ADDR = {MEM_BASE, i_fb, ram_addr[22:3]};
|
||||
assign DDRAM_BE = ram_addr[2] ? 8'hF0 : 8'h0F;
|
||||
assign DDRAM_DIN = {ram_data,ram_data};
|
||||
assign DDRAM_WE = ram_wr;
|
||||
assign DDRAM_RD = 0;
|
||||
|
||||
assign FB_EN = fb_en[2];
|
||||
assign FB_FORMAT = 5'b00110;
|
||||
assign FB_BASE = {MEM_BASE,o_fb,23'd0};
|
||||
assign FB_WIDTH = vsz;
|
||||
assign FB_HEIGHT = hsz;
|
||||
assign FB_STRIDE = stride;
|
||||
|
||||
function [1:0] buf_next;
|
||||
input [1:0] a,b;
|
||||
begin
|
||||
buf_next = 1;
|
||||
if ((a==0 && b==1) || (a==1 && b==0)) buf_next = 2;
|
||||
if ((a==1 && b==2) || (a==2 && b==1)) buf_next = 0;
|
||||
end
|
||||
endfunction
|
||||
|
||||
reg [1:0] i_fb,o_fb;
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg old_vbl,old_vs;
|
||||
old_vbl <= FB_VBL;
|
||||
old_vs <= VGA_VS;
|
||||
|
||||
if(FB_LL) begin
|
||||
if(~old_vbl & FB_VBL) o_fb<={1'b0,~i_fb[0]};
|
||||
if(~old_vs & VGA_VS) i_fb<={1'b0,~i_fb[0]};
|
||||
end
|
||||
else begin
|
||||
if(~old_vbl & FB_VBL) o_fb<=buf_next(o_fb,i_fb);
|
||||
if(~old_vs & VGA_VS) i_fb<=buf_next(i_fb,o_fb);
|
||||
end
|
||||
end
|
||||
|
||||
initial begin
|
||||
fb_en = 0;
|
||||
end
|
||||
|
||||
reg [2:0] fb_en = 0;
|
||||
reg [11:0] hsz = 320, vsz = 240;
|
||||
reg [11:0] bwidth;
|
||||
reg [22:0] bufsize;
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg [11:0] hcnt = 0, vcnt = 0;
|
||||
reg old_vs, old_de;
|
||||
|
||||
if(CE_PIXEL) begin
|
||||
old_vs <= VGA_VS;
|
||||
old_de <= VGA_DE;
|
||||
|
||||
hcnt <= hcnt + 1'd1;
|
||||
if(~old_de & VGA_DE) begin
|
||||
hcnt <= 1;
|
||||
vcnt <= vcnt + 1'd1;
|
||||
end
|
||||
if(old_de & ~VGA_DE) hsz <= hcnt;
|
||||
if(~old_vs & VGA_VS) begin
|
||||
vsz <= vcnt;
|
||||
bwidth <= vcnt + 2'd3;
|
||||
vcnt <= 0;
|
||||
fb_en <= {fb_en[1:0], ~no_rotate};
|
||||
end
|
||||
if(old_vs & ~VGA_VS) bufsize <= hsz * stride;
|
||||
end
|
||||
end
|
||||
|
||||
wire [13:0] stride = {bwidth[11:2], 4'd0};
|
||||
|
||||
reg [22:0] ram_addr, next_addr;
|
||||
reg [31:0] ram_data;
|
||||
reg ram_wr;
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg [13:0] hcnt = 0;
|
||||
reg old_vs, old_de;
|
||||
|
||||
ram_wr <= 0;
|
||||
if(CE_PIXEL) begin
|
||||
old_vs <= VGA_VS;
|
||||
old_de <= VGA_DE;
|
||||
|
||||
if(~old_vs & VGA_VS) begin
|
||||
next_addr <= rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
|
||||
hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00};
|
||||
end
|
||||
if(VGA_DE) begin
|
||||
ram_wr <= 1;
|
||||
ram_data <= {VGA_B,VGA_G,VGA_R};
|
||||
ram_addr <= next_addr;
|
||||
next_addr <= rotate_ccw ? (next_addr - stride) : (next_addr + stride);
|
||||
end
|
||||
if(old_de & ~VGA_DE) begin
|
||||
next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt;
|
||||
hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
2561
sys/ascal.vhd
Normal file
2561
sys/ascal.vhd
Normal file
File diff suppressed because it is too large
Load Diff
296
sys/audio_out.v
Normal file
296
sys/audio_out.v
Normal file
@@ -0,0 +1,296 @@
|
||||
|
||||
module audio_out
|
||||
#(
|
||||
parameter CLK_RATE = 24576000
|
||||
)
|
||||
(
|
||||
input reset,
|
||||
input clk,
|
||||
|
||||
//0 - 48KHz, 1 - 96KHz
|
||||
input sample_rate,
|
||||
|
||||
input [31:0] flt_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 [4:0] att,
|
||||
input [1:0] mix,
|
||||
|
||||
input is_signed,
|
||||
input [15:0] core_l,
|
||||
input [15:0] core_r,
|
||||
|
||||
input [15:0] alsa_l,
|
||||
input [15:0] alsa_r,
|
||||
|
||||
// I2S
|
||||
output i2s_bclk,
|
||||
output i2s_lrclk,
|
||||
output i2s_data,
|
||||
|
||||
// SPDIF
|
||||
output spdif,
|
||||
|
||||
// Sigma-Delta DAC
|
||||
output dac_l,
|
||||
output dac_r
|
||||
);
|
||||
|
||||
localparam AUDIO_RATE = 48000;
|
||||
localparam AUDIO_DW = 16;
|
||||
|
||||
localparam CE_RATE = AUDIO_RATE*AUDIO_DW*8;
|
||||
localparam FILTER_DIV = (CE_RATE/(AUDIO_RATE*32))-1;
|
||||
|
||||
wire [31:0] real_ce = sample_rate ? {CE_RATE[30:0],1'b0} : CE_RATE[31:0];
|
||||
|
||||
reg mclk_ce;
|
||||
always @(posedge clk) begin
|
||||
reg [31:0] cnt;
|
||||
|
||||
mclk_ce = 0;
|
||||
cnt = cnt + real_ce;
|
||||
if(cnt >= CLK_RATE) begin
|
||||
cnt = cnt - CLK_RATE;
|
||||
mclk_ce = 1;
|
||||
end
|
||||
end
|
||||
|
||||
reg i2s_ce;
|
||||
always @(posedge clk) begin
|
||||
reg div;
|
||||
i2s_ce <= 0;
|
||||
if(mclk_ce) begin
|
||||
div <= ~div;
|
||||
i2s_ce <= div;
|
||||
end
|
||||
end
|
||||
|
||||
i2s i2s
|
||||
(
|
||||
.reset(reset),
|
||||
|
||||
.clk(clk),
|
||||
.ce(i2s_ce),
|
||||
|
||||
.sclk(i2s_bclk),
|
||||
.lrclk(i2s_lrclk),
|
||||
.sdata(i2s_data),
|
||||
|
||||
.left_chan(al),
|
||||
.right_chan(ar)
|
||||
);
|
||||
|
||||
spdif toslink
|
||||
(
|
||||
.rst_i(reset),
|
||||
|
||||
.clk_i(clk),
|
||||
.bit_out_en_i(mclk_ce),
|
||||
|
||||
.sample_i({ar,al}),
|
||||
.spdif_o(spdif)
|
||||
);
|
||||
|
||||
sigma_delta_dac #(15) sd_l
|
||||
(
|
||||
.CLK(clk),
|
||||
.RESET(reset),
|
||||
.DACin({~al[15], al[14:0]}),
|
||||
.DACout(dac_l)
|
||||
);
|
||||
|
||||
sigma_delta_dac #(15) sd_r
|
||||
(
|
||||
.CLK(clk),
|
||||
.RESET(reset),
|
||||
.DACin({~ar[15], ar[14:0]}),
|
||||
.DACout(dac_r)
|
||||
);
|
||||
|
||||
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 = 0;
|
||||
reg [14:0] dly2 = 0;
|
||||
|
||||
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] al, audio_l_pre;
|
||||
aud_mix_top audmix_l
|
||||
(
|
||||
.clk(clk),
|
||||
.ce(sample_ce),
|
||||
.att(att),
|
||||
.mix(mix),
|
||||
|
||||
.core_audio(adl),
|
||||
.pre_in(audio_r_pre),
|
||||
.linux_audio(alsa_l),
|
||||
|
||||
.pre_out(audio_l_pre),
|
||||
.out(al)
|
||||
);
|
||||
|
||||
wire [15:0] ar, audio_r_pre;
|
||||
aud_mix_top audmix_r
|
||||
(
|
||||
.clk(clk),
|
||||
.ce(sample_ce),
|
||||
.att(att),
|
||||
.mix(mix),
|
||||
|
||||
.core_audio(adr),
|
||||
.pre_in(audio_l_pre),
|
||||
.linux_audio(alsa_r),
|
||||
|
||||
.pre_out(audio_r_pre),
|
||||
.out(ar)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module aud_mix_top
|
||||
(
|
||||
input clk,
|
||||
input ce,
|
||||
|
||||
input [4:0] att,
|
||||
input [1:0] mix,
|
||||
|
||||
input [15:0] core_audio,
|
||||
input [15:0] linux_audio,
|
||||
input [15:0] pre_in,
|
||||
|
||||
output reg [15:0] pre_out = 0,
|
||||
output reg [15:0] out = 0
|
||||
);
|
||||
|
||||
reg signed [16:0] a1, a2, a3, a4;
|
||||
always @(posedge clk) if (ce) begin
|
||||
|
||||
a1 <= {core_audio[15],core_audio};
|
||||
a2 <= a1 + {linux_audio[15],linux_audio};
|
||||
|
||||
pre_out <= a2[16:1];
|
||||
|
||||
case(mix)
|
||||
0: a3 <= a2;
|
||||
1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]);
|
||||
2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]);
|
||||
3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in};
|
||||
endcase
|
||||
|
||||
if(att[4]) a4 <= 0;
|
||||
else a4 <= a3 >>> att[3:0];
|
||||
|
||||
//clamping
|
||||
out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0];
|
||||
end
|
||||
|
||||
endmodule
|
||||
73
sys/build_id.tcl
Normal file
73
sys/build_id.tcl
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
# Build TimeStamp Verilog Module
|
||||
# Jeff Wiencrot - 8/1/2011
|
||||
# Sorgelig - 02/11/2019
|
||||
proc generateBuildID_Verilog {} {
|
||||
|
||||
# Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html)
|
||||
set buildDate "`define BUILD_DATE \"[clock format [ clock seconds ] -format %y%m%d]\""
|
||||
|
||||
# Create a Verilog file for output
|
||||
set outputFileName "build_id.v"
|
||||
|
||||
set fileData ""
|
||||
if { [file exists $outputFileName]} {
|
||||
set outputFile [open $outputFileName "r"]
|
||||
set fileData [read $outputFile]
|
||||
close $outputFile
|
||||
}
|
||||
|
||||
if {$buildDate ne $fileData} {
|
||||
set outputFile [open $outputFileName "w"]
|
||||
puts -nonewline $outputFile $buildDate
|
||||
close $outputFile
|
||||
# Send confirmation message to the Messages window
|
||||
post_message "Generated: [pwd]/$outputFileName: $buildDate"
|
||||
}
|
||||
}
|
||||
|
||||
# Build CDF file
|
||||
# Sorgelig - 17/2/2018
|
||||
proc generateCDF {revision device outpath} {
|
||||
|
||||
set outputFileName "jtag.cdf"
|
||||
set outputFile [open $outputFileName "w"]
|
||||
|
||||
puts $outputFile "JedecChain;"
|
||||
puts $outputFile " FileRevision(JESD32A);"
|
||||
puts $outputFile " DefaultMfr(6E);"
|
||||
puts $outputFile ""
|
||||
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;"
|
||||
}
|
||||
|
||||
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]
|
||||
|
||||
if [is_project_open] {
|
||||
project_close
|
||||
}
|
||||
|
||||
generateBuildID_Verilog
|
||||
generateCDF $revision $device $outpath
|
||||
108
sys/ddr_svc.sv
Normal file
108
sys/ddr_svc.sv
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// 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 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ------------------------------------------
|
||||
//
|
||||
|
||||
// 16-bit version
|
||||
|
||||
module ddr_svc
|
||||
(
|
||||
input clk,
|
||||
|
||||
input ram_waitrequest,
|
||||
output [7:0] ram_burstcnt,
|
||||
output [28:0] ram_addr,
|
||||
input [63:0] ram_readdata,
|
||||
input ram_read_ready,
|
||||
output reg ram_read,
|
||||
output [63:0] ram_writedata,
|
||||
output [7:0] ram_byteenable,
|
||||
output reg ram_write,
|
||||
|
||||
output [7:0] ram_bcnt,
|
||||
|
||||
input [31:3] ch0_addr,
|
||||
input [7:0] ch0_burst,
|
||||
output [63:0] ch0_data,
|
||||
input ch0_req,
|
||||
output ch0_ready,
|
||||
|
||||
input [31:3] ch1_addr,
|
||||
input [7:0] ch1_burst,
|
||||
output [63:0] ch1_data,
|
||||
input ch1_req,
|
||||
output ch1_ready
|
||||
);
|
||||
|
||||
assign ram_burstcnt = ram_burst;
|
||||
assign ram_byteenable = 8'hFF;
|
||||
assign ram_addr = ram_address;
|
||||
assign ram_writedata = 0;
|
||||
|
||||
assign ch0_data = ram_q[0];
|
||||
assign ch1_data = ram_q[1];
|
||||
assign ch0_ready = ready[0];
|
||||
assign ch1_ready = ready[1];
|
||||
|
||||
reg [7:0] ram_burst;
|
||||
reg [63:0] ram_q[2];
|
||||
reg [31:3] ram_address;
|
||||
reg [1:0] ack = 0;
|
||||
reg [1:0] ready;
|
||||
reg state = 0;
|
||||
reg ch = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
ready <= 0;
|
||||
|
||||
if(!ram_waitrequest) begin
|
||||
ram_read <= 0;
|
||||
ram_write <= 0;
|
||||
|
||||
case(state)
|
||||
0: if(ch0_req != ack[0]) begin
|
||||
ack[0] <= ch0_req;
|
||||
ram_address <= ch0_addr;
|
||||
ram_burst <= ch0_burst;
|
||||
ram_read <= 1;
|
||||
ch <= 0;
|
||||
ram_bcnt <= 8'hFF;
|
||||
state <= 1;
|
||||
end
|
||||
else if(ch1_req != ack[1]) begin
|
||||
ack[1] <= ch1_req;
|
||||
ram_address <= ch1_addr;
|
||||
ram_burst <= ch1_burst;
|
||||
ram_read <= 1;
|
||||
ch <= 1;
|
||||
ram_bcnt <= 8'hFF;
|
||||
state <= 1;
|
||||
end
|
||||
1: begin
|
||||
if(ram_read_ready) begin
|
||||
ram_bcnt <= ram_bcnt + 1'd1;
|
||||
ram_q[ch] <= ram_readdata;
|
||||
ready[ch] <= 1;
|
||||
if ((ram_bcnt+2'd2) == ram_burst) state <= 0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
250
sys/f2sdram_safe_terminator.sv
Normal file
250
sys/f2sdram_safe_terminator.sv
Normal file
@@ -0,0 +1,250 @@
|
||||
// ============================================================================
|
||||
//
|
||||
// f2sdram_safe_terminator for MiSTer platform
|
||||
//
|
||||
// ============================================================================
|
||||
// Copyright (c) 2021 bellwood420
|
||||
//
|
||||
// Background:
|
||||
//
|
||||
// Terminating a transaction of burst writing(/reading) in its midstream
|
||||
// seems to cause an illegal state to f2sdram interface.
|
||||
//
|
||||
// Forced reset request that occurs when loading other core is inevitable.
|
||||
//
|
||||
// So if it happens exactly within the transaction period,
|
||||
// unexpected issues with accessing to f2sdram interface will be caused
|
||||
// in next loaded core.
|
||||
//
|
||||
// It seems that only way to reset broken f2sdram interface is to reset
|
||||
// whole SDRAM Controller Subsystem from HPS via permodrst register
|
||||
// in Reset Manager.
|
||||
// But it cannot be done safely while Linux is running.
|
||||
// It is usually done when cold or warm reset is issued in HPS.
|
||||
//
|
||||
// Main_MiSTer is issuing reset for FPGA <> HPS bridges
|
||||
// via brgmodrst register in Reset Manager when loading rbf.
|
||||
// But it has no effect on f2sdram interface.
|
||||
// f2sdram interface seems to belong to SDRAM Controller Subsystem
|
||||
// rather than FPGA-to-HPS bridge.
|
||||
//
|
||||
// Main_MiSTer is also trying to issuing reset for f2sdram ports
|
||||
// via fpgaportrst register in SDRAM Controller Subsystem when loading rbf.
|
||||
// But according to the Intel's document, fpgaportrst register can be
|
||||
// used to stretch the port reset.
|
||||
// It seems that it cannot be used to assert the port reset.
|
||||
//
|
||||
// According to the Intel's document, there seems to be a reset port on
|
||||
// Avalon-MM slave interface, but it cannot be found in Qsys generated HDL.
|
||||
//
|
||||
// To conclude, the only thing FPGA can do is not to break the transaction.
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//
|
||||
// Purpose:
|
||||
// To prevent the issue, this module completes ongoing transaction
|
||||
// on behalf of user logic, when reset is asserted.
|
||||
//
|
||||
// Usage:
|
||||
// Insert this module into the bus line between
|
||||
// f2sdram (Avalon-MM slave) and user logic (Avalon-MM master).
|
||||
//
|
||||
// Notice:
|
||||
// Asynchronous reset request is not supported.
|
||||
// Please feed reset request synchronized to clock.
|
||||
//
|
||||
module f2sdram_safe_terminator #(
|
||||
parameter DATA_WIDTH = 64,
|
||||
parameter BURSTCOUNT_WIDTH = 8
|
||||
) (
|
||||
// clk should be the same as one provided to f2sdram port
|
||||
// clk should not be stop when reset is asserted
|
||||
input clk,
|
||||
// rst_req_sync should be synchronized to clk
|
||||
// Asynchronous reset request is not supported
|
||||
input rst_req_sync,
|
||||
|
||||
// Master port: connecting to Alavon-MM slave(f2sdram)
|
||||
input waitrequest_master,
|
||||
output [BURSTCOUNT_WIDTH-1:0] burstcount_master,
|
||||
output [ADDRESS_WITDH-1:0] address_master,
|
||||
input [DATA_WIDTH-1:0] readdata_master,
|
||||
input readdatavalid_master,
|
||||
output read_master,
|
||||
output [DATA_WIDTH-1:0] writedata_master,
|
||||
output [BYTEENABLE_WIDTH-1:0] byteenable_master,
|
||||
output write_master,
|
||||
|
||||
// Slave port: connecting to Alavon-MM master(user logic)
|
||||
output waitrequest_slave,
|
||||
input [BURSTCOUNT_WIDTH-1:0] burstcount_slave,
|
||||
input [ADDRESS_WITDH-1:0] address_slave,
|
||||
output [DATA_WIDTH-1:0] readdata_slave,
|
||||
output readdatavalid_slave,
|
||||
input read_slave,
|
||||
input [DATA_WIDTH-1:0] writedata_slave,
|
||||
input [BYTEENABLE_WIDTH-1:0] byteenable_slave,
|
||||
input write_slave
|
||||
);
|
||||
|
||||
localparam BYTEENABLE_WIDTH = DATA_WIDTH/8;
|
||||
localparam ADDRESS_WITDH = 32-$clog2(BYTEENABLE_WIDTH);
|
||||
|
||||
/*
|
||||
* Capture init reset deaseert
|
||||
*/
|
||||
reg init_reset_deasserted = 1'b0;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (!rst_req_sync) begin
|
||||
init_reset_deasserted <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
/*
|
||||
* Lock stage
|
||||
*/
|
||||
reg lock_stage = 1'b0;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst_req_sync) begin
|
||||
// Reset assert
|
||||
if (init_reset_deasserted) begin
|
||||
lock_stage <= 1'b1;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
// Reset deassert
|
||||
lock_stage <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
/*
|
||||
* Write burst transaction observer
|
||||
*/
|
||||
reg state_write = 1'b0;
|
||||
wire next_state_write;
|
||||
|
||||
wire burst_write_start = !state_write && next_state_write;
|
||||
wire valid_write_data = state_write && !waitrequest_master;
|
||||
wire burst_write_end = state_write && (write_burstcounter == write_burstcount_latch - 1'd1);
|
||||
wire valid_non_burst_write = !state_write && write_slave && (burstcount_slave == 1) && !waitrequest_master;
|
||||
|
||||
reg [BURSTCOUNT_WIDTH-1:0] write_burstcounter = 0;
|
||||
reg [BURSTCOUNT_WIDTH-1:0] write_burstcount_latch = 0;
|
||||
reg [ADDRESS_WITDH-1:0] write_address_latch = 0;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
state_write <= next_state_write;
|
||||
|
||||
if (burst_write_start) begin
|
||||
write_burstcounter <= waitrequest_master ? 1'd0 : 1'd1;
|
||||
write_burstcount_latch <= burstcount_slave;
|
||||
write_address_latch <= address_slave;
|
||||
end
|
||||
else if (valid_write_data) begin
|
||||
write_burstcounter <= write_burstcounter + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
if (!state_write) begin
|
||||
if (valid_non_burst_write)
|
||||
next_state_write = 1'b0;
|
||||
else if (write_slave)
|
||||
next_state_write = 1'b1;
|
||||
else
|
||||
next_state_write = 1'b0;
|
||||
end
|
||||
else begin
|
||||
if (burst_write_end)
|
||||
next_state_write = 1'b0;
|
||||
else
|
||||
next_state_write = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
reg [BURSTCOUNT_WIDTH-1:0] write_terminate_counter = 0;
|
||||
reg [BURSTCOUNT_WIDTH-1:0] burstcount_latch = 0;
|
||||
reg [ADDRESS_WITDH-1:0] address_latch = 0;
|
||||
|
||||
reg terminating = 0;
|
||||
reg read_terminating = 0;
|
||||
reg write_terminating = 0;
|
||||
|
||||
wire on_write_transaction = state_write && next_state_write;
|
||||
wire on_start_write_transaction = !state_write && next_state_write;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst_req_sync) begin
|
||||
// Reset assert
|
||||
if (init_reset_deasserted) begin
|
||||
if (!lock_stage) begin
|
||||
// Even not knowing reading is in progress or not,
|
||||
// if it is in progress, it will finish at some point, and no need to do anything.
|
||||
// Assume that reading is in progress when we are not on write transaction.
|
||||
burstcount_latch <= burstcount_slave;
|
||||
address_latch <= address_slave;
|
||||
terminating <= 1;
|
||||
|
||||
if (on_write_transaction) begin
|
||||
write_terminating <= 1;
|
||||
burstcount_latch <= write_burstcount_latch;
|
||||
address_latch <= write_address_latch;
|
||||
write_terminate_counter <= waitrequest_master ? write_burstcounter : write_burstcounter + 1'd1;
|
||||
end
|
||||
else if (on_start_write_transaction) begin
|
||||
if (!valid_non_burst_write) begin
|
||||
write_terminating <= 1;
|
||||
write_terminate_counter <= waitrequest_master ? 1'd0 : 1'd1;
|
||||
end
|
||||
end
|
||||
else if (read_slave && waitrequest_master) begin
|
||||
// Need to keep read signal, burstcount and address until waitrequest_master deasserted
|
||||
read_terminating <= 1;
|
||||
end
|
||||
end
|
||||
else if (!waitrequest_master) begin
|
||||
read_terminating <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
else begin
|
||||
// Reset deassert
|
||||
if (!write_terminating) terminating <= 0;
|
||||
read_terminating <= 0;
|
||||
end
|
||||
|
||||
if (write_terminating) begin
|
||||
// Continue write transaction until the end
|
||||
if (!waitrequest_master) write_terminate_counter <= write_terminate_counter + 1'd1;
|
||||
if (write_terminate_counter == burstcount_latch - 1'd1) write_terminating <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
/*
|
||||
* Bus mux depending on the stage.
|
||||
*/
|
||||
always_comb begin
|
||||
if (terminating) begin
|
||||
burstcount_master = burstcount_latch;
|
||||
address_master = address_latch;
|
||||
read_master = read_terminating;
|
||||
write_master = write_terminating;
|
||||
byteenable_master = 0;
|
||||
end
|
||||
else begin
|
||||
burstcount_master = burstcount_slave;
|
||||
address_master = address_slave;
|
||||
read_master = read_slave;
|
||||
byteenable_master = byteenable_slave;
|
||||
write_master = write_slave;
|
||||
end
|
||||
end
|
||||
|
||||
// Just passing master <-> slave
|
||||
assign writedata_master = writedata_slave;
|
||||
assign readdata_slave = readdata_master;
|
||||
assign readdatavalid_slave = readdatavalid_master;
|
||||
assign waitrequest_slave = waitrequest_master;
|
||||
|
||||
endmodule
|
||||
124
sys/gamma_corr.sv
Normal file
124
sys/gamma_corr.sv
Normal file
@@ -0,0 +1,124 @@
|
||||
module gamma_corr
|
||||
(
|
||||
input clk_sys,
|
||||
input clk_vid,
|
||||
input ce_pix,
|
||||
input gamma_en,
|
||||
input gamma_wr,
|
||||
input [9:0] gamma_wr_addr,
|
||||
input [7:0] gamma_value,
|
||||
input HSync,
|
||||
input VSync,
|
||||
input HBlank,
|
||||
input VBlank,
|
||||
input [23:0] RGB_in,
|
||||
output reg HSync_out,
|
||||
output reg VSync_out,
|
||||
output reg HBlank_out,
|
||||
output reg VBlank_out,
|
||||
output reg [23:0] RGB_out
|
||||
);
|
||||
|
||||
(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve[768];
|
||||
|
||||
always @(posedge clk_sys) if (gamma_wr) gamma_curve[gamma_wr_addr] <= gamma_value;
|
||||
always @(posedge clk_vid) gamma <= gamma_curve[gamma_index];
|
||||
|
||||
reg [9:0] gamma_index;
|
||||
reg [7:0] gamma;
|
||||
|
||||
always @(posedge clk_vid) begin
|
||||
reg [7:0] R_in, G_in, B_in;
|
||||
reg [7:0] R_gamma, G_gamma;
|
||||
reg hs,vs,hb,vb;
|
||||
reg [1:0] ctr = 0;
|
||||
reg old_ce;
|
||||
|
||||
old_ce <= ce_pix;
|
||||
if(~old_ce & ce_pix) begin
|
||||
{R_in,G_in,B_in} <= RGB_in;
|
||||
hs <= HSync; vs <= VSync;
|
||||
hb <= HBlank; vb <= VBlank;
|
||||
|
||||
RGB_out <= gamma_en ? {R_gamma,G_gamma,gamma} : {R_in,G_in,B_in};
|
||||
HSync_out <= hs; VSync_out <= vs;
|
||||
HBlank_out <= hb; VBlank_out <= vb;
|
||||
|
||||
ctr <= 1;
|
||||
gamma_index <= {2'b00,RGB_in[23:16]};
|
||||
end
|
||||
|
||||
if (|ctr) ctr <= ctr + 1'd1;
|
||||
|
||||
case(ctr)
|
||||
1: begin gamma_index <= {2'b01,G_in}; end
|
||||
2: begin R_gamma <= gamma; gamma_index <= {2'b10,B_in}; end
|
||||
3: begin G_gamma <= gamma; end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module gamma_fast
|
||||
(
|
||||
input clk_vid,
|
||||
input ce_pix,
|
||||
|
||||
inout [21:0] gamma_bus,
|
||||
|
||||
input HSync,
|
||||
input VSync,
|
||||
input HBlank,
|
||||
input VBlank,
|
||||
input DE,
|
||||
input [23:0] RGB_in,
|
||||
|
||||
output reg HSync_out,
|
||||
output reg VSync_out,
|
||||
output reg HBlank_out,
|
||||
output reg VBlank_out,
|
||||
output reg DE_out,
|
||||
output reg [23:0] RGB_out
|
||||
);
|
||||
|
||||
(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_r[256];
|
||||
(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_g[256];
|
||||
(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_b[256];
|
||||
|
||||
assign gamma_bus[21] = 1;
|
||||
wire clk_sys = gamma_bus[20];
|
||||
wire gamma_en = gamma_bus[19];
|
||||
wire gamma_wr = gamma_bus[18];
|
||||
wire [9:0] gamma_wr_addr = gamma_bus[17:8];
|
||||
wire [7:0] gamma_value = gamma_bus[7:0];
|
||||
|
||||
always @(posedge clk_sys) if (gamma_wr) begin
|
||||
case(gamma_wr_addr[9:8])
|
||||
0: gamma_curve_r[gamma_wr_addr[7:0]] <= gamma_value;
|
||||
1: gamma_curve_g[gamma_wr_addr[7:0]] <= gamma_value;
|
||||
2: gamma_curve_b[gamma_wr_addr[7:0]] <= gamma_value;
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [7:0] gamma_index_r,gamma_index_g,gamma_index_b;
|
||||
|
||||
always @(posedge clk_vid) begin
|
||||
reg [7:0] R_in, G_in, B_in;
|
||||
reg [7:0] R_gamma, G_gamma;
|
||||
reg hs,vs,hb,vb,de;
|
||||
|
||||
if(ce_pix) begin
|
||||
{gamma_index_r,gamma_index_g,gamma_index_b} <= RGB_in;
|
||||
hs <= HSync; vs <= VSync;
|
||||
hb <= HBlank; vb <= VBlank;
|
||||
de <= DE;
|
||||
|
||||
RGB_out <= gamma_en ? {gamma_curve_r[gamma_index_r],gamma_curve_g[gamma_index_g],gamma_curve_b[gamma_index_b]}
|
||||
: {gamma_index_r,gamma_index_g,gamma_index_b};
|
||||
HSync_out <= hs; VSync_out <= vs;
|
||||
HBlank_out <= hb; VBlank_out <= vb;
|
||||
DE_out <= de;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
239
sys/hdmi_config.sv
Normal file
239
sys/hdmi_config.sv
Normal file
@@ -0,0 +1,239 @@
|
||||
|
||||
module hdmi_config
|
||||
(
|
||||
// Host Side
|
||||
input iCLK,
|
||||
input iRST_N,
|
||||
|
||||
input dvi_mode,
|
||||
input audio_96k,
|
||||
input [1:0] limited,
|
||||
input ypbpr,
|
||||
|
||||
output reg done,
|
||||
|
||||
// I2C Side
|
||||
output I2C_SCL,
|
||||
inout I2C_SDA
|
||||
);
|
||||
|
||||
// Internal Registers/Wires
|
||||
reg mI2C_GO = 0;
|
||||
wire mI2C_END;
|
||||
wire mI2C_ACK;
|
||||
reg [15:0] LUT_DATA;
|
||||
reg [7:0] LUT_INDEX = 0;
|
||||
|
||||
i2c #(50_000_000, 20_000) i2c_av
|
||||
(
|
||||
.CLK(iCLK),
|
||||
|
||||
.I2C_SCL(I2C_SCL), // I2C CLOCK
|
||||
.I2C_SDA(I2C_SDA), // I2C DATA
|
||||
|
||||
.I2C_ADDR('h39), // 0x39 is the Slave Address of the ADV7513 chip!
|
||||
.I2C_WLEN(1),
|
||||
.I2C_WDATA1(init_data[LUT_INDEX][15:8]), // SUB_ADDR
|
||||
.I2C_WDATA2(init_data[LUT_INDEX][7:0]), // DATA
|
||||
.START(mI2C_GO), // START transfer
|
||||
.READ(0),
|
||||
.END(mI2C_END), // END transfer
|
||||
.ACK(mI2C_ACK) // ACK
|
||||
);
|
||||
|
||||
////////////////////// Config Control ////////////////////////////
|
||||
always@(posedge iCLK or negedge iRST_N) begin
|
||||
reg [1:0] mSetup_ST = 0;
|
||||
|
||||
if(!iRST_N) begin
|
||||
LUT_INDEX <= 0;
|
||||
mSetup_ST <= 0;
|
||||
mI2C_GO <= 0;
|
||||
done <= 0;
|
||||
end else begin
|
||||
if(init_data[LUT_INDEX] != 16'hFFFF) begin
|
||||
case(mSetup_ST)
|
||||
0: begin
|
||||
mI2C_GO <= 1;
|
||||
mSetup_ST <= 1;
|
||||
end
|
||||
1: if(~mI2C_END) mSetup_ST <= 2;
|
||||
2: begin
|
||||
mI2C_GO <= 0;
|
||||
if(mI2C_END) begin
|
||||
mSetup_ST <= 0;
|
||||
if(!mI2C_ACK) LUT_INDEX <= LUT_INDEX + 8'd1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
else done <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
///////////////////// Config Data LUT //////////////////////////
|
||||
|
||||
wire [15:0] init_data[82] =
|
||||
'{
|
||||
16'h9803, // ADI required Write.
|
||||
|
||||
{8'hD6, 8'b1100_0000}, // [7:6] HPD Control...
|
||||
// 00 = HPD is from both HPD pin or CDC HPD
|
||||
// 01 = HPD is from CDC HPD
|
||||
// 10 = HPD is from HPD pin
|
||||
// 11 = HPD is always high
|
||||
|
||||
16'h4110, // Power Down control
|
||||
16'h9A70, // ADI required Write.
|
||||
16'h9C30, // ADI required Write.
|
||||
{8'h9D, 8'b0110_0001}, // [7:4] must be b0110!.
|
||||
// [3:2] b00 = Input clock not divided. b01 = Clk divided by 2. b10 = Clk divided by 4. b11 = invalid!
|
||||
// [1:0] must be b01!
|
||||
16'hA2A4, // ADI required Write.
|
||||
16'hA3A4, // ADI required Write.
|
||||
16'hE0D0, // ADI required Write.
|
||||
|
||||
|
||||
16'h35_40,
|
||||
16'h36_D9,
|
||||
16'h37_0A,
|
||||
16'h38_00,
|
||||
16'h39_2D,
|
||||
16'h3A_00,
|
||||
|
||||
{8'h16, 8'b0011_1000}, // Output Format 444 [7]=0.
|
||||
// [6] must be 0!
|
||||
// Colour Depth for Input Video data [5:4] b11 = 8-bit.
|
||||
// Input Style [3:2] b10 = Style 1 (ignored when using 444 input).
|
||||
// DDR Input Edge falling [1]=0 (not using DDR atm).
|
||||
// Output Colour Space RGB [0]=0.
|
||||
|
||||
{8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0
|
||||
|
||||
{8'h18, ypbpr ? 8'h86 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited.
|
||||
{8'h19, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide.
|
||||
{8'h1A, ypbpr ? 8'h1A : 8'h00}, // CSC Channel A.
|
||||
{8'h1B, ypbpr ? 8'h3F : 8'h00},
|
||||
{8'h1C, ypbpr ? 8'h1E : 8'h00},
|
||||
{8'h1D, ypbpr ? 8'hE2 : 8'h00},
|
||||
{8'h1E, ypbpr ? 8'h07 : 8'h01},
|
||||
{8'h1F, ypbpr ? 8'hE7 : 8'h00},
|
||||
|
||||
{8'h20, ypbpr ? 8'h04 : 8'h00}, // CSC Channel B.
|
||||
{8'h21, ypbpr ? 8'h1C : 8'h00},
|
||||
{8'h22, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E},
|
||||
{8'h23, ypbpr ? 8'h11 : limited[0] ? 8'hBC : 8'hFE},
|
||||
{8'h24, ypbpr ? 8'h01 : 8'h00},
|
||||
{8'h25, ypbpr ? 8'h91 : 8'h00},
|
||||
{8'h26, ypbpr ? 8'h01 : 8'h01},
|
||||
{8'h27, 8'h00},
|
||||
|
||||
{8'h28, ypbpr ? 8'h1D : 8'h00}, // CSC Channel C.
|
||||
{8'h29, ypbpr ? 8'hAE : 8'h00},
|
||||
{8'h2A, ypbpr ? 8'h1B : 8'h00},
|
||||
{8'h2B, ypbpr ? 8'h73 : 8'h00},
|
||||
{8'h2C, ypbpr ? 8'h06 : limited[0] ? 8'h0D : 8'h0E},
|
||||
{8'h2D, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE},
|
||||
{8'h2E, ypbpr ? 8'h07 : 8'h01},
|
||||
{8'h2F, ypbpr ? 8'hE7 : 8'h00},
|
||||
|
||||
{8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx.
|
||||
|
||||
16'h4000, // General Control Packet Enable
|
||||
|
||||
{8'h48, 8'b0000_1000}, // [6]=0 Normal bus order!
|
||||
// [5] DDR Alignment.
|
||||
// [4:3] b01 Data right justified (for YCbCr 422 input modes).
|
||||
|
||||
16'h49A8, // ADI required Write.
|
||||
16'h4C00, // ADI required Write.
|
||||
|
||||
{8'h55, 8'b0001_0000}, // [7] must be 0!. Set RGB444 in AVinfo Frame [6:5], Set active format [4].
|
||||
// AVI InfoFrame Valid [4].
|
||||
// Bar Info [3:2] b00 Bars invalid. b01 Bars vertical. b10 Bars horizontal. b11 Bars both.
|
||||
// Scan Info [1:0] b00 (No data). b01 TV. b10 PC. b11 None.
|
||||
|
||||
{8'h57, 1'b0, // [7] IT Content. 0 - No. 1 - Yes (type set in register h59).
|
||||
3'b000, // [6:4] Color space (ignored for RGB)
|
||||
(ypbpr | limited) ? 2'b01 : 2'b10, // [3:2] RGB Quantization range
|
||||
2'b00}, // [1:0] Non-Uniform Scaled: 00 - None. 01 - Horiz. 10 - Vert. 11 - Both.
|
||||
|
||||
16'h7301,
|
||||
|
||||
{8'h94, 8'b1000_0000}, // [7]=1 HPD Interrupt ENabled.
|
||||
|
||||
16'h9902, // ADI required Write.
|
||||
16'h9B18, // ADI required Write.
|
||||
|
||||
16'h9F00, // ADI required Write.
|
||||
|
||||
{8'hA1, 8'b0000_0000}, // [6]=1 Monitor Sense Power Down DISabled.
|
||||
|
||||
16'hA408, // ADI required Write.
|
||||
16'hA504, // ADI required Write.
|
||||
16'hA600, // ADI required Write.
|
||||
16'hA700, // ADI required Write.
|
||||
16'hA800, // ADI required Write.
|
||||
16'hA900, // ADI required Write.
|
||||
16'hAA00, // ADI required Write.
|
||||
16'hAB40, // ADI required Write.
|
||||
|
||||
{8'hAF, 6'b0000_01,~dvi_mode,1'b0}, // [7]=0 HDCP Disabled.
|
||||
// [6:5] must be b00!
|
||||
// [4]=0 Current frame is unencrypted
|
||||
// [3:2] must be b01!
|
||||
// [1]=1 HDMI Mode.
|
||||
// [0] must be b0!
|
||||
|
||||
16'hB900, // ADI required Write.
|
||||
|
||||
{8'hBA, 8'b0110_0000}, // [7:5] Input Clock delay...
|
||||
// b000 = -1.2ns.
|
||||
// b001 = -0.8ns.
|
||||
// b010 = -0.4ns.
|
||||
// b011 = No delay.
|
||||
// b100 = 0.4ns.
|
||||
// b101 = 0.8ns.
|
||||
// b110 = 1.2ns.
|
||||
// b111 = 1.6ns.
|
||||
|
||||
16'hBB00, // ADI required Write.
|
||||
|
||||
16'hDE9C, // ADI required Write.
|
||||
16'hE460, // ADI required Write.
|
||||
16'hFA7D, // Nbr of times to search for good phase
|
||||
|
||||
|
||||
// (Audio stuff on Programming Guide, Page 66)...
|
||||
|
||||
{8'h0A, 8'b0000_0000}, // [6:4] Audio Select. b000 = I2S.
|
||||
// [3:2] Audio Mode. (HBR stuff, leave at 00!).
|
||||
|
||||
{8'h0B, 8'b0000_1110}, //
|
||||
|
||||
{8'h0C, 8'b0000_0100}, // [7] 0 = Use sampling rate from I2S stream. 1 = Use samp rate from I2C Register.
|
||||
// [6] 0 = Use Channel Status bits from stream. 1 = Use Channel Status bits from I2C register.
|
||||
// [2] 1 = I2S0 Enable.
|
||||
// [1:0] I2S Format: 00 = Standard. 01 = Right Justified. 10 = Left Justified. 11 = AES.
|
||||
|
||||
{8'h0D, 8'b0001_0000}, // [4:0] I2S Bit (Word) Width for Right-Justified.
|
||||
{8'h14, 8'b0000_0010}, // [3:0] Audio Word Length. b0010 = 16 bits.
|
||||
{8'h15, audio_96k, 7'b010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz.
|
||||
// Input ID [3:1] b000 (0) = 24-bit RGB 444 or YCrCb 444 with Separate Syncs.
|
||||
|
||||
// Audio Clock Config
|
||||
16'h0100, //
|
||||
audio_96k ? 16'h0230 : 16'h0218, // Set N Value 12288/6144
|
||||
16'h0300, //
|
||||
|
||||
16'h0701, //
|
||||
16'h0822, // Set CTS Value 74250
|
||||
16'h090A, //
|
||||
|
||||
16'hFFFF // END
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
endmodule
|
||||
938
sys/hps_io.v
Normal file
938
sys/hps_io.v
Normal file
@@ -0,0 +1,938 @@
|
||||
//
|
||||
// hps_io.v
|
||||
//
|
||||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||||
// Copyright (c) 2017-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 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// altera message_off 10665
|
||||
|
||||
//
|
||||
// Use buffer to access SD card. It's time-critical part.
|
||||
//
|
||||
// WIDE=1 for 16 bit file I/O
|
||||
// VDNUM 1-4
|
||||
module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
|
||||
(
|
||||
input clk_sys,
|
||||
inout [45:0] HPS_BUS,
|
||||
|
||||
// parameter STRLEN and the actual length of conf_str have to match
|
||||
input [(8*STRLEN)-1:0] conf_str,
|
||||
|
||||
// buttons up to 32
|
||||
output reg [31:0] joystick_0,
|
||||
output reg [31:0] joystick_1,
|
||||
output reg [31:0] joystick_2,
|
||||
output reg [31:0] joystick_3,
|
||||
output reg [31:0] joystick_4,
|
||||
output reg [31:0] joystick_5,
|
||||
|
||||
// analog -127..+127, Y: [15:8], X: [7:0]
|
||||
output reg [15:0] joystick_analog_0,
|
||||
output reg [15:0] joystick_analog_1,
|
||||
output reg [15:0] joystick_analog_2,
|
||||
output reg [15:0] joystick_analog_3,
|
||||
output reg [15:0] joystick_analog_4,
|
||||
output reg [15:0] joystick_analog_5,
|
||||
|
||||
// paddle 0..255
|
||||
output reg [7:0] paddle_0,
|
||||
output reg [7:0] paddle_1,
|
||||
output reg [7:0] paddle_2,
|
||||
output reg [7:0] paddle_3,
|
||||
output reg [7:0] paddle_4,
|
||||
output reg [7:0] paddle_5,
|
||||
|
||||
// spinner [7:0] -128..+127, [8] - toggle with every update
|
||||
output reg [8:0] spinner_0,
|
||||
output reg [8:0] spinner_1,
|
||||
output reg [8:0] spinner_2,
|
||||
output reg [8:0] spinner_3,
|
||||
output reg [8:0] spinner_4,
|
||||
output reg [8:0] spinner_5,
|
||||
|
||||
output [1:0] buttons,
|
||||
output forced_scandoubler,
|
||||
output direct_video,
|
||||
|
||||
output reg [63:0] status,
|
||||
input [63:0] status_in,
|
||||
input status_set,
|
||||
input [15:0] status_menumask,
|
||||
|
||||
input info_req,
|
||||
input [7:0] info,
|
||||
|
||||
//toggle to force notify of video mode change
|
||||
input new_vmode,
|
||||
|
||||
// SD config
|
||||
output reg [VD:0] img_mounted, // signaling that new image has been mounted
|
||||
output reg img_readonly, // mounted as read only. valid only for active bit in img_mounted
|
||||
output reg [63:0] img_size, // size of image in bytes. valid only for active bit in img_mounted
|
||||
|
||||
// SD block level access
|
||||
input [31:0] sd_lba,
|
||||
input [VD:0] sd_rd, // only single sd_rd can be active at any given time
|
||||
input [VD:0] sd_wr, // only single sd_wr can be active at any given time
|
||||
output reg sd_ack,
|
||||
|
||||
// do not use in new projects.
|
||||
// CID and CSD are fake except CSD image size field.
|
||||
input sd_conf,
|
||||
output reg sd_ack_conf,
|
||||
|
||||
// SD byte level access. Signals for 2-PORT altsyncram.
|
||||
output reg [AW:0] sd_buff_addr,
|
||||
output reg [DW:0] sd_buff_dout,
|
||||
input [DW:0] sd_buff_din,
|
||||
output reg sd_buff_wr,
|
||||
input [15:0] sd_req_type,
|
||||
|
||||
// ARM -> FPGA download
|
||||
output reg ioctl_download = 0, // signal indicating an active download
|
||||
output reg [15:0] ioctl_index, // menu index used to upload the file
|
||||
output reg ioctl_wr,
|
||||
output reg [26:0] ioctl_addr, // in WIDE mode address will be incremented by 2
|
||||
output reg [DW:0] ioctl_dout,
|
||||
output reg ioctl_upload = 0, // signal indicating an active upload
|
||||
input [DW:0] ioctl_din,
|
||||
output reg ioctl_rd,
|
||||
output reg [31:0] ioctl_file_ext,
|
||||
input ioctl_wait,
|
||||
|
||||
// [15]: 0 - unset, 1 - set. [1:0]: 0 - none, 1 - 32MB, 2 - 64MB, 3 - 128MB
|
||||
// [14]: debug mode: [8]: 1 - phase up, 0 - phase down. [7:0]: amount of shift.
|
||||
output reg [15:0] sdram_sz,
|
||||
|
||||
// RTC MSM6242B layout
|
||||
output reg [64:0] RTC,
|
||||
|
||||
// Seconds since 1970-01-01 00:00:00
|
||||
output reg [32:0] TIMESTAMP,
|
||||
|
||||
// UART flags
|
||||
output reg [7:0] uart_mode,
|
||||
output reg [31:0] uart_speed,
|
||||
|
||||
// ps2 keyboard emulation
|
||||
output ps2_kbd_clk_out,
|
||||
output ps2_kbd_data_out,
|
||||
input ps2_kbd_clk_in,
|
||||
input ps2_kbd_data_in,
|
||||
|
||||
input [2:0] ps2_kbd_led_status,
|
||||
input [2:0] ps2_kbd_led_use,
|
||||
|
||||
output ps2_mouse_clk_out,
|
||||
output ps2_mouse_data_out,
|
||||
input ps2_mouse_clk_in,
|
||||
input ps2_mouse_data_in,
|
||||
|
||||
// ps2 alternative interface.
|
||||
|
||||
// [8] - extended, [9] - pressed, [10] - toggles with every press/release
|
||||
output reg [10:0] ps2_key = 0,
|
||||
|
||||
// [24] - toggles with every event
|
||||
output reg [24:0] ps2_mouse = 0,
|
||||
output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements
|
||||
|
||||
inout [21:0] gamma_bus,
|
||||
|
||||
// for core-specific extensions
|
||||
inout [35:0] EXT_BUS
|
||||
);
|
||||
|
||||
assign EXT_BUS[31:16] = HPS_BUS[31:16];
|
||||
assign EXT_BUS[35:33] = HPS_BUS[35:33];
|
||||
|
||||
localparam MAX_W = $clog2((512 > (STRLEN+1)) ? 512 : (STRLEN+1))-1;
|
||||
|
||||
localparam DW = (WIDE) ? 15 : 7;
|
||||
localparam AW = (WIDE) ? 7 : 8;
|
||||
localparam VD = VDNUM-1;
|
||||
|
||||
wire io_strobe= HPS_BUS[33];
|
||||
wire io_enable= HPS_BUS[34];
|
||||
wire fp_enable= HPS_BUS[35];
|
||||
wire io_wide = (WIDE) ? 1'b1 : 1'b0;
|
||||
wire [15:0] io_din = HPS_BUS[31:16];
|
||||
reg [15:0] io_dout;
|
||||
|
||||
assign HPS_BUS[37] = ioctl_wait;
|
||||
assign HPS_BUS[36] = clk_sys;
|
||||
assign HPS_BUS[32] = io_wide;
|
||||
assign HPS_BUS[15:0] = EXT_BUS[32] ? EXT_BUS[15:0] : fp_enable ? fp_dout : io_dout;
|
||||
|
||||
reg [15:0] cfg;
|
||||
assign buttons = cfg[1:0];
|
||||
//cfg[2] - vga_scaler handled in sys_top
|
||||
//cfg[3] - csync handled in sys_top
|
||||
assign forced_scandoubler = cfg[4];
|
||||
//cfg[5] - ypbpr handled in sys_top
|
||||
assign direct_video = cfg[10];
|
||||
|
||||
// command byte read by the io controller
|
||||
wire [15:0] sd_cmd =
|
||||
{
|
||||
2'b00,
|
||||
(VDNUM>=4) ? sd_wr[3] : 1'b0,
|
||||
(VDNUM>=3) ? sd_wr[2] : 1'b0,
|
||||
(VDNUM>=2) ? sd_wr[1] : 1'b0,
|
||||
|
||||
(VDNUM>=4) ? sd_rd[3] : 1'b0,
|
||||
(VDNUM>=3) ? sd_rd[2] : 1'b0,
|
||||
(VDNUM>=2) ? sd_rd[1] : 1'b0,
|
||||
|
||||
4'h5, sd_conf, 1'b1,
|
||||
sd_wr[0],
|
||||
sd_rd[0]
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
wire [15:0] vc_dout;
|
||||
video_calc video_calc
|
||||
(
|
||||
.clk_100(HPS_BUS[43]),
|
||||
.clk_vid(HPS_BUS[42]),
|
||||
.clk_sys(clk_sys),
|
||||
.ce_pix(HPS_BUS[41]),
|
||||
.de(HPS_BUS[40]),
|
||||
.hs(HPS_BUS[39]),
|
||||
.vs(HPS_BUS[38]),
|
||||
.vs_hdmi(HPS_BUS[44]),
|
||||
.f1(HPS_BUS[45]),
|
||||
.new_vmode(new_vmode),
|
||||
|
||||
.par_num(byte_cnt[3:0]),
|
||||
.dout(vc_dout)
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
assign gamma_bus[20:0] = {clk_sys, gamma_en, gamma_wr, gamma_wr_addr, gamma_value};
|
||||
reg gamma_en;
|
||||
reg gamma_wr;
|
||||
reg [9:0] gamma_wr_addr;
|
||||
reg [7:0] gamma_value;
|
||||
|
||||
reg [31:0] ps2_key_raw = 0;
|
||||
wire pressed = (ps2_key_raw[15:8] != 8'hf0);
|
||||
wire extended = (~pressed ? (ps2_key_raw[23:16] == 8'he0) : (ps2_key_raw[15:8] == 8'he0));
|
||||
|
||||
reg [MAX_W:0] byte_cnt;
|
||||
|
||||
always@(posedge clk_sys) begin : uio_block
|
||||
reg [15:0] cmd;
|
||||
reg [2:0] b_wr;
|
||||
reg [3:0] stick_idx;
|
||||
reg [3:0] pdsp_idx;
|
||||
reg ps2skip = 0;
|
||||
reg [3:0] stflg = 0;
|
||||
reg [63:0] status_req;
|
||||
reg old_status_set = 0;
|
||||
reg old_info = 0;
|
||||
reg [7:0] info_n = 0;
|
||||
reg [15:0] tmp1;
|
||||
reg [7:0] tmp2;
|
||||
|
||||
old_status_set <= status_set;
|
||||
if(~old_status_set & status_set) begin
|
||||
stflg <= stflg + 1'd1;
|
||||
status_req <= status_in;
|
||||
end
|
||||
|
||||
old_info <= info_req;
|
||||
if(~old_info & info_req) info_n <= info;
|
||||
|
||||
sd_buff_wr <= b_wr[0];
|
||||
if(b_wr[2] && (~&sd_buff_addr)) sd_buff_addr <= sd_buff_addr + 1'b1;
|
||||
b_wr <= (b_wr<<1);
|
||||
|
||||
if(PS2DIV) {kbd_rd,kbd_we,mouse_rd,mouse_we} <= 0;
|
||||
|
||||
gamma_wr <= 0;
|
||||
|
||||
if(~io_enable) begin
|
||||
if(cmd == 4 && !ps2skip) ps2_mouse[24] <= ~ps2_mouse[24];
|
||||
if(cmd == 5 && !ps2skip) begin
|
||||
ps2_key <= {~ps2_key[10], pressed, extended, ps2_key_raw[7:0]};
|
||||
if(ps2_key_raw == 'hE012E07C) ps2_key[9:0] <= 'h37C; // prnscr pressed
|
||||
if(ps2_key_raw == 'h7CE0F012) ps2_key[9:0] <= 'h17C; // prnscr released
|
||||
if(ps2_key_raw == 'hF014F077) ps2_key[9:0] <= 'h377; // pause pressed
|
||||
end
|
||||
if(cmd == 'h22) RTC[64] <= ~RTC[64];
|
||||
if(cmd == 'h24) TIMESTAMP[32] <= ~TIMESTAMP[32];
|
||||
cmd <= 0;
|
||||
byte_cnt <= 0;
|
||||
sd_ack <= 0;
|
||||
sd_ack_conf <= 0;
|
||||
io_dout <= 0;
|
||||
ps2skip <= 0;
|
||||
img_mounted <= 0;
|
||||
end
|
||||
else if(io_strobe) begin
|
||||
|
||||
io_dout <= 0;
|
||||
if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1;
|
||||
|
||||
if(byte_cnt == 0) begin
|
||||
cmd <= io_din;
|
||||
|
||||
case(io_din)
|
||||
'h19: sd_ack_conf <= 1;
|
||||
'h17,
|
||||
'h18: sd_ack <= 1;
|
||||
'h29: io_dout <= {4'hA, stflg};
|
||||
'h2B: io_dout <= 1;
|
||||
'h2F: io_dout <= 1;
|
||||
'h32: io_dout <= gamma_bus[21];
|
||||
'h36: begin io_dout <= info_n; info_n <= 0; end
|
||||
'h39: io_dout <= 1;
|
||||
endcase
|
||||
|
||||
sd_buff_addr <= 0;
|
||||
if(io_din == 5) ps2_key_raw <= 0;
|
||||
end else begin
|
||||
|
||||
case(cmd)
|
||||
// buttons and switches
|
||||
'h01: cfg <= io_din;
|
||||
'h02: if(byte_cnt==1) joystick_0[15:0] <= io_din; else joystick_0[31:16] <= io_din;
|
||||
'h03: if(byte_cnt==1) joystick_1[15:0] <= io_din; else joystick_1[31:16] <= io_din;
|
||||
'h10: if(byte_cnt==1) joystick_2[15:0] <= io_din; else joystick_2[31:16] <= io_din;
|
||||
'h11: if(byte_cnt==1) joystick_3[15:0] <= io_din; else joystick_3[31:16] <= io_din;
|
||||
'h12: if(byte_cnt==1) joystick_4[15:0] <= io_din; else joystick_4[31:16] <= io_din;
|
||||
'h13: if(byte_cnt==1) joystick_5[15:0] <= io_din; else joystick_5[31:16] <= io_din;
|
||||
|
||||
// store incoming ps2 mouse bytes
|
||||
'h04: begin
|
||||
if(PS2DIV) begin
|
||||
mouse_data <= io_din[7:0];
|
||||
mouse_we <= 1;
|
||||
end
|
||||
if(&io_din[15:8]) ps2skip <= 1;
|
||||
if(~&io_din[15:8] && ~ps2skip && !byte_cnt[MAX_W:2]) begin
|
||||
case(byte_cnt[1:0])
|
||||
1: ps2_mouse[7:0] <= io_din[7:0];
|
||||
2: ps2_mouse[15:8] <= io_din[7:0];
|
||||
3: ps2_mouse[23:16] <= io_din[7:0];
|
||||
endcase
|
||||
case(byte_cnt[1:0])
|
||||
1: ps2_mouse_ext[7:0] <= {io_din[14], io_din[14:8]};
|
||||
2: ps2_mouse_ext[11:8] <= io_din[11:8];
|
||||
3: ps2_mouse_ext[15:12]<= io_din[11:8];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// store incoming ps2 keyboard bytes
|
||||
'h05: begin
|
||||
if(&io_din[15:8]) ps2skip <= 1;
|
||||
if(~&io_din[15:8] & ~ps2skip) ps2_key_raw[31:0] <= {ps2_key_raw[23:0], io_din[7:0]};
|
||||
if(PS2DIV) begin
|
||||
kbd_data <= io_din[7:0];
|
||||
kbd_we <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
// reading config string, returning a byte from string
|
||||
'h14: if(byte_cnt < STRLEN + 1) io_dout[7:0] <= conf_str[(STRLEN - byte_cnt)<<3 +:8];
|
||||
|
||||
// reading sd card status
|
||||
'h16: if(!byte_cnt[MAX_W:3]) begin
|
||||
case(byte_cnt[2:0])
|
||||
1: io_dout <= sd_cmd;
|
||||
2: io_dout <= sd_lba[15:0];
|
||||
3: io_dout <= sd_lba[31:16];
|
||||
4: io_dout <= sd_req_type;
|
||||
endcase
|
||||
end
|
||||
|
||||
// send SD config IO -> FPGA
|
||||
// flag that download begins
|
||||
// sd card knows data is config if sd_dout_strobe is asserted
|
||||
// with sd_ack still being inactive (low)
|
||||
'h19,
|
||||
// send sector IO -> FPGA
|
||||
// flag that download begins
|
||||
'h17: begin
|
||||
sd_buff_dout <= io_din[DW:0];
|
||||
b_wr <= 1;
|
||||
end
|
||||
|
||||
// reading sd card write data
|
||||
'h18: begin
|
||||
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
|
||||
io_dout <= sd_buff_din;
|
||||
end
|
||||
|
||||
// joystick analog
|
||||
'h1a: if(!byte_cnt[MAX_W:2]) begin
|
||||
case(byte_cnt[1:0])
|
||||
1: {pdsp_idx,stick_idx} <= io_din[7:0]; // first byte is joystick index
|
||||
2: case(stick_idx)
|
||||
0: joystick_analog_0 <= io_din;
|
||||
1: joystick_analog_1 <= io_din;
|
||||
2: joystick_analog_2 <= io_din;
|
||||
3: joystick_analog_3 <= io_din;
|
||||
4: joystick_analog_4 <= io_din;
|
||||
5: joystick_analog_5 <= io_din;
|
||||
15: case(pdsp_idx)
|
||||
0: paddle_0 <= io_din[7:0];
|
||||
1: paddle_1 <= io_din[7:0];
|
||||
2: paddle_2 <= io_din[7:0];
|
||||
3: paddle_3 <= io_din[7:0];
|
||||
4: paddle_4 <= io_din[7:0];
|
||||
5: paddle_5 <= io_din[7:0];
|
||||
8: spinner_0 <= {~spinner_0[8],io_din[7:0]};
|
||||
9: spinner_1 <= {~spinner_1[8],io_din[7:0]};
|
||||
10: spinner_2 <= {~spinner_2[8],io_din[7:0]};
|
||||
11: spinner_3 <= {~spinner_3[8],io_din[7:0]};
|
||||
12: spinner_4 <= {~spinner_4[8],io_din[7:0]};
|
||||
13: spinner_5 <= {~spinner_5[8],io_din[7:0]};
|
||||
endcase
|
||||
endcase
|
||||
endcase
|
||||
end
|
||||
|
||||
// notify image selection
|
||||
'h1c: begin
|
||||
img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1;
|
||||
img_readonly <= io_din[7];
|
||||
end
|
||||
|
||||
// send image info
|
||||
'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din;
|
||||
|
||||
// status, 64bit version
|
||||
'h1e: if(!byte_cnt[MAX_W:3]) begin
|
||||
case(byte_cnt[2:0])
|
||||
1: status[15:00] <= io_din;
|
||||
2: status[31:16] <= io_din;
|
||||
3: status[47:32] <= io_din;
|
||||
4: status[63:48] <= io_din;
|
||||
endcase
|
||||
end
|
||||
|
||||
// reading keyboard LED status
|
||||
'h1f: io_dout <= {|PS2WE, 2'b01, ps2_kbd_led_status[2], ps2_kbd_led_use[2], ps2_kbd_led_status[1], ps2_kbd_led_use[1], ps2_kbd_led_status[0], ps2_kbd_led_use[0]};
|
||||
|
||||
// reading ps2 keyboard/mouse control
|
||||
'h21: if(PS2DIV) begin
|
||||
if(byte_cnt == 1) begin
|
||||
io_dout <= kbd_data_host;
|
||||
kbd_rd <= 1;
|
||||
end
|
||||
else
|
||||
if(byte_cnt == 2) begin
|
||||
io_dout <= mouse_data_host;
|
||||
mouse_rd <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
//RTC
|
||||
'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din;
|
||||
|
||||
//Video res.
|
||||
'h23: if(!byte_cnt[MAX_W:4]) io_dout <= vc_dout;
|
||||
|
||||
//RTC
|
||||
'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din;
|
||||
|
||||
//status set
|
||||
'h29: if(!byte_cnt[MAX_W:3]) begin
|
||||
case(byte_cnt[2:0])
|
||||
1: io_dout <= status_req[15:00];
|
||||
2: io_dout <= status_req[31:16];
|
||||
3: io_dout <= status_req[47:32];
|
||||
4: io_dout <= status_req[63:48];
|
||||
endcase
|
||||
end
|
||||
|
||||
//menu mask
|
||||
'h2E: if(byte_cnt == 1) io_dout <= status_menumask;
|
||||
|
||||
//sdram size set
|
||||
'h31: if(byte_cnt == 1) sdram_sz <= io_din;
|
||||
|
||||
// Gamma
|
||||
'h32: gamma_en <= io_din[0];
|
||||
'h33: begin
|
||||
gamma_wr_addr <= {(byte_cnt[1:0]-1'b1),io_din[15:8]};
|
||||
{gamma_wr, gamma_value} <= {1'b1,io_din[7:0]};
|
||||
if (byte_cnt[1:0] == 3) byte_cnt <= 1;
|
||||
end
|
||||
|
||||
// UART
|
||||
'h3b: if(!byte_cnt[MAX_W:2]) begin
|
||||
case(byte_cnt[1:0])
|
||||
1: tmp2 <= io_din[7:0];
|
||||
2: tmp1 <= io_din;
|
||||
3: {uart_speed, uart_mode} <= {io_din, tmp1, tmp2};
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/////////////////////////////// PS2 ///////////////////////////////
|
||||
generate
|
||||
if(PS2DIV) begin
|
||||
reg clk_ps2;
|
||||
always @(posedge clk_sys) begin
|
||||
integer cnt;
|
||||
cnt <= cnt + 1'd1;
|
||||
if(cnt == PS2DIV) begin
|
||||
clk_ps2 <= ~clk_ps2;
|
||||
cnt <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
reg [7:0] kbd_data;
|
||||
reg kbd_we;
|
||||
wire [8:0] kbd_data_host;
|
||||
reg kbd_rd;
|
||||
|
||||
ps2_device keyboard
|
||||
(
|
||||
.clk_sys(clk_sys),
|
||||
|
||||
.wdata(kbd_data),
|
||||
.we(kbd_we),
|
||||
|
||||
.ps2_clk(clk_ps2),
|
||||
.ps2_clk_out(ps2_kbd_clk_out),
|
||||
.ps2_dat_out(ps2_kbd_data_out),
|
||||
|
||||
.ps2_clk_in(ps2_kbd_clk_in || !PS2WE),
|
||||
.ps2_dat_in(ps2_kbd_data_in || !PS2WE),
|
||||
|
||||
.rdata(kbd_data_host),
|
||||
.rd(kbd_rd)
|
||||
);
|
||||
|
||||
reg [7:0] mouse_data;
|
||||
reg mouse_we;
|
||||
wire [8:0] mouse_data_host;
|
||||
reg mouse_rd;
|
||||
|
||||
ps2_device mouse
|
||||
(
|
||||
.clk_sys(clk_sys),
|
||||
|
||||
.wdata(mouse_data),
|
||||
.we(mouse_we),
|
||||
|
||||
.ps2_clk(clk_ps2),
|
||||
.ps2_clk_out(ps2_mouse_clk_out),
|
||||
.ps2_dat_out(ps2_mouse_data_out),
|
||||
|
||||
.ps2_clk_in(ps2_mouse_clk_in || !PS2WE),
|
||||
.ps2_dat_in(ps2_mouse_data_in || !PS2WE),
|
||||
|
||||
.rdata(mouse_data_host),
|
||||
.rd(mouse_rd)
|
||||
);
|
||||
end
|
||||
else begin
|
||||
assign ps2_kbd_clk_out = 0;
|
||||
assign ps2_kbd_data_out = 0;
|
||||
assign ps2_mouse_clk_out = 0;
|
||||
assign ps2_mouse_data_out = 0;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
/////////////////////////////// DOWNLOADING ///////////////////////////////
|
||||
|
||||
localparam FIO_FILE_TX = 8'h53;
|
||||
localparam FIO_FILE_TX_DAT = 8'h54;
|
||||
localparam FIO_FILE_INDEX = 8'h55;
|
||||
localparam FIO_FILE_INFO = 8'h56;
|
||||
|
||||
reg [15:0] fp_dout;
|
||||
always@(posedge clk_sys) begin : fio_block
|
||||
reg [15:0] cmd;
|
||||
reg [2:0] cnt;
|
||||
reg has_cmd;
|
||||
reg [26:0] addr;
|
||||
reg wr;
|
||||
|
||||
ioctl_rd <= 0;
|
||||
ioctl_wr <= wr;
|
||||
wr <= 0;
|
||||
|
||||
if(~fp_enable) has_cmd <= 0;
|
||||
else begin
|
||||
if(io_strobe) begin
|
||||
|
||||
if(!has_cmd) begin
|
||||
cmd <= io_din;
|
||||
has_cmd <= 1;
|
||||
cnt <= 0;
|
||||
end else begin
|
||||
|
||||
case(cmd)
|
||||
FIO_FILE_INFO:
|
||||
if(~cnt[1]) begin
|
||||
case(cnt)
|
||||
0: ioctl_file_ext[31:16] <= io_din;
|
||||
1: ioctl_file_ext[15:00] <= io_din;
|
||||
endcase
|
||||
cnt <= cnt + 1'd1;
|
||||
end
|
||||
|
||||
FIO_FILE_INDEX:
|
||||
begin
|
||||
ioctl_index <= io_din[15:0];
|
||||
end
|
||||
|
||||
FIO_FILE_TX:
|
||||
begin
|
||||
cnt <= cnt + 1'd1;
|
||||
case(cnt)
|
||||
0: if(io_din[7:0] == 8'hAA) begin
|
||||
ioctl_addr <= 0;
|
||||
ioctl_upload <= 1;
|
||||
ioctl_rd <= 1;
|
||||
end
|
||||
else if(io_din[7:0]) begin
|
||||
addr <= 0;
|
||||
ioctl_download <= 1;
|
||||
end
|
||||
else begin
|
||||
if(ioctl_download) ioctl_addr <= addr;
|
||||
ioctl_download <= 0;
|
||||
ioctl_upload <= 0;
|
||||
end
|
||||
|
||||
1: begin
|
||||
ioctl_addr[15:0] <= io_din;
|
||||
addr[15:0] <= io_din;
|
||||
end
|
||||
|
||||
2: begin
|
||||
ioctl_addr[26:16] <= io_din[10:0];
|
||||
addr[26:16] <= io_din[10:0];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
FIO_FILE_TX_DAT:
|
||||
if(ioctl_download) begin
|
||||
ioctl_addr <= addr;
|
||||
ioctl_dout <= io_din[DW:0];
|
||||
wr <= 1;
|
||||
addr <= addr + (WIDE ? 2'd2 : 2'd1);
|
||||
end
|
||||
else begin
|
||||
ioctl_addr <= ioctl_addr + (WIDE ? 2'd2 : 2'd1);
|
||||
fp_dout <= ioctl_din;
|
||||
ioctl_rd <= 1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
module ps2_device #(parameter PS2_FIFO_BITS=5)
|
||||
(
|
||||
input clk_sys,
|
||||
|
||||
input [7:0] wdata,
|
||||
input we,
|
||||
|
||||
input ps2_clk,
|
||||
output reg ps2_clk_out,
|
||||
output reg ps2_dat_out,
|
||||
output reg tx_empty,
|
||||
|
||||
input ps2_clk_in,
|
||||
input ps2_dat_in,
|
||||
|
||||
output [8:0] rdata,
|
||||
input rd
|
||||
);
|
||||
|
||||
|
||||
(* ramstyle = "logic" *) reg [7:0] fifo[1<<PS2_FIFO_BITS];
|
||||
|
||||
reg [PS2_FIFO_BITS-1:0] wptr;
|
||||
reg [PS2_FIFO_BITS-1:0] rptr;
|
||||
|
||||
reg [2:0] rx_state = 0;
|
||||
reg [3:0] tx_state = 0;
|
||||
|
||||
reg has_data;
|
||||
reg [7:0] data;
|
||||
assign rdata = {has_data, data};
|
||||
|
||||
always@(posedge clk_sys) begin
|
||||
reg [7:0] tx_byte;
|
||||
reg parity;
|
||||
reg r_inc;
|
||||
reg old_clk;
|
||||
reg [1:0] timeout;
|
||||
|
||||
reg [3:0] rx_cnt;
|
||||
|
||||
reg c1,c2,d1;
|
||||
|
||||
tx_empty <= ((wptr == rptr) && (tx_state == 0));
|
||||
|
||||
if(we && !has_data) begin
|
||||
fifo[wptr] <= wdata;
|
||||
wptr <= wptr + 1'd1;
|
||||
end
|
||||
|
||||
if(rd) has_data <= 0;
|
||||
|
||||
c1 <= ps2_clk_in;
|
||||
c2 <= c1;
|
||||
d1 <= ps2_dat_in;
|
||||
if(!rx_state && !tx_state && ~c2 && c1 && ~d1) begin
|
||||
rx_state <= rx_state + 1'b1;
|
||||
ps2_dat_out <= 1;
|
||||
end
|
||||
|
||||
old_clk <= ps2_clk;
|
||||
if(~old_clk & ps2_clk) begin
|
||||
|
||||
if(rx_state) begin
|
||||
case(rx_state)
|
||||
1: begin
|
||||
rx_state <= rx_state + 1'b1;
|
||||
rx_cnt <= 0;
|
||||
end
|
||||
|
||||
2: begin
|
||||
if(rx_cnt <= 7) data <= {d1, data[7:1]};
|
||||
else rx_state <= rx_state + 1'b1;
|
||||
rx_cnt <= rx_cnt + 1'b1;
|
||||
end
|
||||
|
||||
3: if(d1) begin
|
||||
rx_state <= rx_state + 1'b1;
|
||||
ps2_dat_out <= 0;
|
||||
end
|
||||
|
||||
4: begin
|
||||
ps2_dat_out <= 1;
|
||||
has_data <= 1;
|
||||
rx_state <= 0;
|
||||
rptr <= 0;
|
||||
wptr <= 0;
|
||||
end
|
||||
endcase
|
||||
end else begin
|
||||
|
||||
// transmitter is idle?
|
||||
if(tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(c2 && c1 && d1 && wptr != rptr) begin
|
||||
|
||||
timeout <= timeout - 1'd1;
|
||||
if(!timeout) begin
|
||||
tx_byte <= fifo[rptr];
|
||||
rptr <= rptr + 1'd1;
|
||||
|
||||
// reset parity
|
||||
parity <= 1;
|
||||
|
||||
// start transmitter
|
||||
tx_state <= 1;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_dat_out <= 0; // start bit is 0
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((tx_state >= 1)&&(tx_state < 9)) begin
|
||||
ps2_dat_out <= tx_byte[0]; // data bits
|
||||
tx_byte[6:0] <= tx_byte[7:1]; // shift down
|
||||
if(tx_byte[0])
|
||||
parity <= !parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(tx_state == 9) ps2_dat_out <= parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(tx_state == 10) ps2_dat_out <= 1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(tx_state < 11) tx_state <= tx_state + 1'd1;
|
||||
else tx_state <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(~old_clk & ps2_clk) ps2_clk_out <= 1;
|
||||
if(old_clk & ~ps2_clk) ps2_clk_out <= ((tx_state == 0) && (rx_state<2));
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
///////////////// calc video parameters //////////////////
|
||||
module video_calc
|
||||
(
|
||||
input clk_100,
|
||||
input clk_vid,
|
||||
input clk_sys,
|
||||
|
||||
input ce_pix,
|
||||
input de,
|
||||
input hs,
|
||||
input vs,
|
||||
input vs_hdmi,
|
||||
input f1,
|
||||
input new_vmode,
|
||||
|
||||
input [3:0] par_num,
|
||||
output reg [15:0] dout
|
||||
);
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
case(par_num)
|
||||
1: dout <= {|vid_int, vid_nres};
|
||||
2: dout <= vid_hcnt[15:0];
|
||||
3: dout <= vid_hcnt[31:16];
|
||||
4: dout <= vid_vcnt[15:0];
|
||||
5: dout <= vid_vcnt[31:16];
|
||||
6: dout <= vid_htime[15:0];
|
||||
7: dout <= vid_htime[31:16];
|
||||
8: dout <= vid_vtime[15:0];
|
||||
9: dout <= vid_vtime[31:16];
|
||||
10: dout <= vid_pix[15:0];
|
||||
11: dout <= vid_pix[31:16];
|
||||
12: dout <= vid_vtime_hdmi[15:0];
|
||||
13: dout <= vid_vtime_hdmi[31:16];
|
||||
default dout <= 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [31:0] vid_hcnt = 0;
|
||||
reg [31:0] vid_vcnt = 0;
|
||||
reg [7:0] vid_nres = 0;
|
||||
reg [1:0] vid_int = 0;
|
||||
|
||||
always @(posedge clk_vid) begin
|
||||
integer hcnt;
|
||||
integer vcnt;
|
||||
reg old_vs= 0, old_de = 0, old_vmode = 0;
|
||||
reg [3:0] resto = 0;
|
||||
reg calch = 0;
|
||||
|
||||
if(ce_pix) begin
|
||||
old_vs <= vs;
|
||||
old_de <= de;
|
||||
|
||||
if(~vs & ~old_de & de) vcnt <= vcnt + 1;
|
||||
if(calch & de) hcnt <= hcnt + 1;
|
||||
if(old_de & ~de) calch <= 0;
|
||||
|
||||
if(old_vs & ~vs) begin
|
||||
vid_int <= {vid_int[0],f1};
|
||||
if(~f1) begin
|
||||
if(hcnt && vcnt) begin
|
||||
old_vmode <= new_vmode;
|
||||
|
||||
//report new resolution after timeout
|
||||
if(resto) resto <= resto + 1'd1;
|
||||
if(vid_hcnt != hcnt || vid_vcnt != vcnt || old_vmode != new_vmode) resto <= 1;
|
||||
if(&resto) vid_nres <= vid_nres + 1'd1;
|
||||
vid_hcnt <= hcnt;
|
||||
vid_vcnt <= vcnt;
|
||||
end
|
||||
vcnt <= 0;
|
||||
hcnt <= 0;
|
||||
calch <= 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg [31:0] vid_htime = 0;
|
||||
reg [31:0] vid_vtime = 0;
|
||||
reg [31:0] vid_pix = 0;
|
||||
|
||||
always @(posedge clk_100) begin
|
||||
integer vtime, htime, hcnt;
|
||||
reg old_vs, old_hs, old_vs2, old_hs2, old_de, old_de2;
|
||||
reg calch = 0;
|
||||
|
||||
old_vs <= vs;
|
||||
old_hs <= hs;
|
||||
|
||||
old_vs2 <= old_vs;
|
||||
old_hs2 <= old_hs;
|
||||
|
||||
vtime <= vtime + 1'd1;
|
||||
htime <= htime + 1'd1;
|
||||
|
||||
if(~old_vs2 & old_vs) begin
|
||||
vid_pix <= hcnt;
|
||||
vid_vtime <= vtime;
|
||||
vtime <= 0;
|
||||
hcnt <= 0;
|
||||
end
|
||||
|
||||
if(old_vs2 & ~old_vs) calch <= 1;
|
||||
|
||||
if(~old_hs2 & old_hs) begin
|
||||
vid_htime <= htime;
|
||||
htime <= 0;
|
||||
end
|
||||
|
||||
old_de <= de;
|
||||
old_de2 <= old_de;
|
||||
|
||||
if(calch & old_de) hcnt <= hcnt + 1;
|
||||
if(old_de2 & ~old_de) calch <= 0;
|
||||
end
|
||||
|
||||
reg [31:0] vid_vtime_hdmi;
|
||||
always @(posedge clk_100) begin
|
||||
integer vtime;
|
||||
reg old_vs, old_vs2;
|
||||
|
||||
old_vs <= vs_hdmi;
|
||||
old_vs2 <= old_vs;
|
||||
|
||||
vtime <= vtime + 1'd1;
|
||||
|
||||
if(~old_vs2 & old_vs) begin
|
||||
vid_vtime_hdmi <= vtime;
|
||||
vtime <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
371
sys/hq2x.sv
Normal file
371
sys/hq2x.sv
Normal file
@@ -0,0 +1,371 @@
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2012-2013 Ludvig Strigeus
|
||||
// Copyright (c) 2017,2018 Sorgelig
|
||||
//
|
||||
// This program is GPL Licensed. See COPYING for the full license.
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// altera message_off 10030
|
||||
|
||||
module Hq2x #(parameter LENGTH, parameter HALF_DEPTH)
|
||||
(
|
||||
input clk,
|
||||
|
||||
input ce_in,
|
||||
input [DWIDTH:0] inputpixel,
|
||||
input mono,
|
||||
input disable_hq2x,
|
||||
input reset_frame,
|
||||
input reset_line,
|
||||
|
||||
input ce_out,
|
||||
input [1:0] read_y,
|
||||
input hblank,
|
||||
output [DWIDTH:0] outpixel
|
||||
);
|
||||
|
||||
|
||||
localparam AWIDTH = $clog2(LENGTH)-1;
|
||||
localparam DWIDTH = HALF_DEPTH ? 11 : 23;
|
||||
localparam DWIDTH1 = DWIDTH+1;
|
||||
|
||||
(* romstyle = "MLAB" *) reg [5:0] hqTable[256];
|
||||
initial begin
|
||||
hqTable = '{
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39,
|
||||
19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43,
|
||||
19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43
|
||||
};
|
||||
end
|
||||
|
||||
wire [5:0] hqrule = hqTable[nextpatt];
|
||||
|
||||
reg [23:0] Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2;
|
||||
reg [23:0] A, B, D, F, G, H;
|
||||
reg [7:0] pattern, nextpatt;
|
||||
reg [1:0] cyc;
|
||||
|
||||
reg curbuf;
|
||||
reg prevbuf = 0;
|
||||
wire iobuf = !curbuf;
|
||||
|
||||
wire diff0, diff1;
|
||||
DiffCheck diffcheck0(Curr1, (cyc == 0) ? Prev0 : (cyc == 1) ? Curr0 : (cyc == 2) ? Prev2 : Next1, diff0);
|
||||
DiffCheck diffcheck1(Curr1, (cyc == 0) ? Prev1 : (cyc == 1) ? Next0 : (cyc == 2) ? Curr2 : Next2, diff1);
|
||||
|
||||
wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]};
|
||||
|
||||
wire [23:0] X = (cyc == 0) ? A : (cyc == 1) ? Prev1 : (cyc == 2) ? Next1 : G;
|
||||
wire [23:0] blend_result_pre;
|
||||
Blend blender(clk, ce_in, disable_hq2x ? 6'd0 : hqrule, Curr0, X, B, D, F, H, blend_result_pre);
|
||||
|
||||
wire [DWIDTH:0] Curr20tmp;
|
||||
wire [23:0] Curr20 = HALF_DEPTH ? h2rgb(Curr20tmp) : Curr20tmp;
|
||||
wire [DWIDTH:0] Curr21tmp;
|
||||
wire [23:0] Curr21 = HALF_DEPTH ? h2rgb(Curr21tmp) : Curr21tmp;
|
||||
|
||||
reg [AWIDTH:0] wrin_addr2;
|
||||
reg [DWIDTH:0] wrpix;
|
||||
reg wrin_en;
|
||||
|
||||
function [23:0] h2rgb;
|
||||
input [11:0] v;
|
||||
begin
|
||||
h2rgb = mono ? {v[7:0], v[7:0], v[7:0]} : {v[11:8],v[11:8],v[7:4],v[7:4],v[3:0],v[3:0]};
|
||||
end
|
||||
endfunction
|
||||
|
||||
function [11:0] rgb2h;
|
||||
input [23:0] v;
|
||||
begin
|
||||
rgb2h = mono ? {4'b0000, v[23:20], v[19:16]} : {v[23:20], v[15:12], v[7:4]};
|
||||
end
|
||||
endfunction
|
||||
|
||||
hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in
|
||||
(
|
||||
.clk(clk),
|
||||
|
||||
.rdaddr(offs),
|
||||
.rdbuf0(prevbuf),
|
||||
.rdbuf1(curbuf),
|
||||
.q0(Curr20tmp),
|
||||
.q1(Curr21tmp),
|
||||
|
||||
.wraddr(wrin_addr2),
|
||||
.wrbuf(iobuf),
|
||||
.data(wrpix),
|
||||
.wren(wrin_en)
|
||||
);
|
||||
|
||||
reg [AWIDTH+1:0] read_x;
|
||||
reg [AWIDTH+1:0] wrout_addr;
|
||||
reg wrout_en;
|
||||
reg [DWIDTH1*4-1:0] wrdata, wrdata_pre;
|
||||
wire [DWIDTH1*4-1:0] outpixel_x4;
|
||||
reg [DWIDTH1*2-1:0] outpixel_x2;
|
||||
|
||||
assign outpixel = read_x[0] ? outpixel_x2[DWIDTH1*2-1:DWIDTH1] : outpixel_x2[DWIDTH:0];
|
||||
|
||||
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH+1), .DWIDTH(DWIDTH1*4-1)) hq2x_out
|
||||
(
|
||||
.clock(clk),
|
||||
|
||||
.rdaddress({read_x[AWIDTH+1:1],read_y[1]}),
|
||||
.q(outpixel_x4),
|
||||
|
||||
.data(wrdata),
|
||||
.wraddress(wrout_addr),
|
||||
.wren(wrout_en)
|
||||
);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(ce_out) begin
|
||||
if(read_x[0]) outpixel_x2 <= read_y[0] ? outpixel_x4[DWIDTH1*4-1:DWIDTH1*2] : outpixel_x4[DWIDTH1*2-1:0];
|
||||
if(~hblank & ~&read_x) read_x <= read_x + 1'd1;
|
||||
if(hblank) read_x <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
wire [DWIDTH:0] blend_result = HALF_DEPTH ? rgb2h(blend_result_pre) : blend_result_pre[DWIDTH:0];
|
||||
|
||||
reg [AWIDTH:0] offs;
|
||||
always @(posedge clk) begin
|
||||
reg old_reset_line;
|
||||
reg old_reset_frame;
|
||||
reg [3:0] wrdata_finished;
|
||||
reg [AWIDTH+1:0] waddr;
|
||||
|
||||
wrout_en <= 0;
|
||||
wrin_en <= 0;
|
||||
|
||||
if(ce_in) begin
|
||||
|
||||
// blend_result has been delayed by 4 cycles
|
||||
case(cyc)
|
||||
0: wrdata[DWIDTH:0] <= blend_result;
|
||||
1: wrdata[DWIDTH1+DWIDTH:DWIDTH1] <= blend_result;
|
||||
2: wrdata[DWIDTH1*3+DWIDTH:DWIDTH1*3] <= blend_result;
|
||||
3: wrdata[DWIDTH1*2+DWIDTH:DWIDTH1*2] <= blend_result;
|
||||
endcase
|
||||
|
||||
wrdata_finished <= wrdata_finished << 1;
|
||||
if(wrdata_finished[3]) begin
|
||||
wrout_en <= 1;
|
||||
wrout_addr <= waddr;
|
||||
end
|
||||
|
||||
if(~&offs) begin
|
||||
if (cyc == 1) begin
|
||||
Prev2 <= Curr20;
|
||||
Curr2 <= Curr21;
|
||||
Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel;
|
||||
wrpix <= inputpixel;
|
||||
wrin_addr2 <= offs;
|
||||
wrin_en <= 1;
|
||||
end
|
||||
|
||||
if(cyc==3) begin
|
||||
offs <= offs + 1'd1;
|
||||
waddr <= {offs, curbuf};
|
||||
wrdata_finished[0] <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
pattern <= new_pattern;
|
||||
if(cyc==3) begin
|
||||
nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]};
|
||||
{A, G} <= {Prev0, Next0};
|
||||
{B, F, H, D} <= {Prev1, Curr2, Next1, Curr0};
|
||||
{Prev0, Prev1} <= {Prev1, Prev2};
|
||||
{Curr0, Curr1} <= {Curr1, Curr2};
|
||||
{Next0, Next1} <= {Next1, Next2};
|
||||
end else begin
|
||||
nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]};
|
||||
{B, F, H, D} <= {F, H, D, B};
|
||||
end
|
||||
|
||||
cyc <= cyc + 1'b1;
|
||||
if(old_reset_line && ~reset_line) begin
|
||||
old_reset_frame <= reset_frame;
|
||||
offs <= 0;
|
||||
cyc <= 0;
|
||||
curbuf <= ~curbuf;
|
||||
prevbuf <= curbuf;
|
||||
{Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2} <= '0;
|
||||
if(old_reset_frame & ~reset_frame) begin
|
||||
curbuf <= 0;
|
||||
prevbuf <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
old_reset_line <= reset_line;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module hq2x_in #(parameter LENGTH, parameter DWIDTH)
|
||||
(
|
||||
input clk,
|
||||
|
||||
input [AWIDTH:0] rdaddr,
|
||||
input rdbuf0, rdbuf1,
|
||||
output[DWIDTH:0] q0,q1,
|
||||
|
||||
input [AWIDTH:0] wraddr,
|
||||
input wrbuf,
|
||||
input [DWIDTH:0] data,
|
||||
input wren
|
||||
);
|
||||
|
||||
localparam AWIDTH = $clog2(LENGTH)-1;
|
||||
wire [DWIDTH:0] out[2];
|
||||
assign q0 = out[rdbuf0];
|
||||
assign q1 = out[rdbuf1];
|
||||
|
||||
hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]);
|
||||
hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]);
|
||||
|
||||
endmodule
|
||||
|
||||
module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH)
|
||||
(
|
||||
input clock,
|
||||
input [DWIDTH:0] data,
|
||||
input [AWIDTH:0] rdaddress,
|
||||
input [AWIDTH:0] wraddress,
|
||||
input wren,
|
||||
output reg [DWIDTH:0] q
|
||||
);
|
||||
|
||||
reg [DWIDTH:0] ram[0:NUMWORDS-1];
|
||||
|
||||
always_ff@(posedge clock) begin
|
||||
if(wren) ram[wraddress] <= data;
|
||||
q <= ram[rdaddress];
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module DiffCheck
|
||||
(
|
||||
input [23:0] rgb1,
|
||||
input [23:0] rgb2,
|
||||
output result
|
||||
);
|
||||
|
||||
wire [7:0] r = rgb1[7:1] - rgb2[7:1];
|
||||
wire [7:0] g = rgb1[15:9] - rgb2[15:9];
|
||||
wire [7:0] b = rgb1[23:17] - rgb2[23:17];
|
||||
wire [8:0] t = $signed(r) + $signed(b);
|
||||
wire [9:0] y = $signed(t) + $signed({g[7], g});
|
||||
wire [8:0] u = $signed(r) - $signed(b);
|
||||
wire [9:0] v = $signed({g, 1'b0}) - $signed(t);
|
||||
|
||||
// if y is inside (-96..96)
|
||||
wire y_inside = (y < 10'h60 || y >= 10'h3a0);
|
||||
|
||||
// if u is inside (-16, 16)
|
||||
wire u_inside = (!u[8:4] || &u[8:4]); //(u < 9'h10 || u >= 9'h1f0);
|
||||
|
||||
// if v is inside (-24, 24)
|
||||
wire v_inside = (v < 10'h18 || v >= 10'h3e8);
|
||||
assign result = !(y_inside && u_inside && v_inside);
|
||||
|
||||
endmodule
|
||||
|
||||
module Blend
|
||||
(
|
||||
input clk,
|
||||
input clk_en,
|
||||
input [5:0] rule,
|
||||
input [23:0] E,
|
||||
input [23:0] A,
|
||||
input [23:0] B,
|
||||
input [23:0] D,
|
||||
input [23:0] F,
|
||||
input [23:0] H,
|
||||
output [23:0] Result
|
||||
);
|
||||
|
||||
localparam BLEND1 = 7'b110_10_00; // (A * 12 + B * 4 ) >> 4
|
||||
localparam BLEND2 = 7'b100_10_10; // (A * 8 + B * 4 + C * 4) >> 4
|
||||
localparam BLEND3 = 7'b101_10_01; // (A * 10 + B * 4 + C * 2) >> 4
|
||||
localparam BLEND4 = 7'b110_01_01; // (A * 12 + B * 2 + C * 2) >> 4
|
||||
localparam BLEND5 = 7'b010_11_11; // (A * 4 + B * 6 + C * 6) >> 4
|
||||
localparam BLEND6 = 7'b111_00_00; // (A * 14 + B * 1 + C * 1) >> 4
|
||||
|
||||
reg [23:0] a,b,d,e,h,f;
|
||||
reg [3:0] bl_rule;
|
||||
reg [1:0] df_rule;
|
||||
always @(posedge clk) if (clk_en) begin
|
||||
{bl_rule,df_rule} <= rule;
|
||||
a <= A; b <= B; d <= D; e <= E; f <= F; h <= H;
|
||||
end
|
||||
|
||||
wire is_diff;
|
||||
DiffCheck diff_checker(df_rule[1] ? b : h, df_rule[0] ? d : f, is_diff);
|
||||
|
||||
reg [23:0] i10,i20,i30;
|
||||
reg [6:0] op0;
|
||||
always @(posedge clk) if (clk_en) begin
|
||||
i10 <= e;
|
||||
case({!is_diff, bl_rule})
|
||||
1,11,12,13,17: {op0, i20, i30} <= {BLEND1, a, 24'd0};
|
||||
2,14,18: {op0, i20, i30} <= {BLEND1, d, 24'd0};
|
||||
3,15,19: {op0, i20, i30} <= {BLEND1, b, 24'd0};
|
||||
4,20,24,27: {op0, i20, i30} <= {BLEND2, d, b};
|
||||
5,21: {op0, i20, i30} <= {BLEND2, a, b};
|
||||
6,22: {op0, i20, i30} <= {BLEND2, a, d};
|
||||
25,29: {op0, i20, i30} <= {BLEND5, d, b};
|
||||
26: {op0, i20, i30} <= {BLEND6, d, b};
|
||||
28: {op0, i20, i30} <= {BLEND4, d, b};
|
||||
30: {op0, i20, i30} <= {BLEND3, b, d};
|
||||
31: {op0, i20, i30} <= {BLEND3, d, b};
|
||||
default: {op0, i20, i30} <= {BLEND1, e, 24'd0};
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [23:0] i1,i2,i3;
|
||||
reg [6:0] op;
|
||||
always @(posedge clk) if (clk_en) begin
|
||||
op <= op0; i1 <= i10; i2 <= i20; i3 <= i30;
|
||||
end
|
||||
|
||||
function [34:0] mul24x3;
|
||||
input [23:0] op1;
|
||||
input [2:0] op2;
|
||||
begin
|
||||
mul24x3 = 0;
|
||||
if(op2[0]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0]};
|
||||
if(op2[1]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0], 1'b0};
|
||||
if(op2[2]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0], 2'b00};
|
||||
end
|
||||
endfunction
|
||||
|
||||
wire [35:0] res = {mul24x3(i1, op[6:4]), 1'b0} + mul24x3(i2, {op[3:2], !op[3:2]}) + mul24x3(i3, {op[1:0], !op[3:2]});
|
||||
|
||||
always @(posedge clk) if (clk_en) Result <= {res[35:28],res[23:16],res[11:4]};
|
||||
|
||||
endmodule
|
||||
103
sys/i2c.v
Normal file
103
sys/i2c.v
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
module i2c
|
||||
(
|
||||
input CLK,
|
||||
|
||||
input START,
|
||||
input READ,
|
||||
input [6:0] I2C_ADDR,
|
||||
input I2C_WLEN, // 0 - one byte, 1 - two bytes
|
||||
input [7:0] I2C_WDATA1,
|
||||
input [7:0] I2C_WDATA2,
|
||||
output [7:0] I2C_RDATA,
|
||||
output reg END = 1,
|
||||
output reg ACK = 0,
|
||||
|
||||
//I2C bus
|
||||
output I2C_SCL,
|
||||
inout I2C_SDA
|
||||
);
|
||||
|
||||
|
||||
// Clock Setting
|
||||
parameter CLK_Freq = 50_000_000; // 50 MHz
|
||||
parameter I2C_Freq = 400_000; // 400 KHz
|
||||
|
||||
localparam I2C_FreqX2 = I2C_Freq*2;
|
||||
|
||||
reg I2C_CLOCK;
|
||||
reg [31:0] cnt;
|
||||
wire [31:0] cnt_next = cnt + I2C_FreqX2;
|
||||
|
||||
always @(posedge CLK) begin
|
||||
cnt <= cnt_next;
|
||||
if(cnt_next >= CLK_Freq) begin
|
||||
cnt <= cnt_next - CLK_Freq;
|
||||
I2C_CLOCK <= ~I2C_CLOCK;
|
||||
end
|
||||
end
|
||||
|
||||
assign I2C_SCL = (SCLK | I2C_CLOCK) ? 1'bZ : 1'b0;
|
||||
assign I2C_SDA = SDO[3] ? 1'bz : 1'b0;
|
||||
|
||||
reg SCLK;
|
||||
reg [3:0] SDO;
|
||||
reg [0:7] rdata;
|
||||
|
||||
reg [5:0] SD_COUNTER;
|
||||
reg [0:31] SD;
|
||||
|
||||
initial begin
|
||||
SD_COUNTER = 'b111111;
|
||||
SD = 'hFFFF;
|
||||
SCLK = 1;
|
||||
SDO = 4'b1111;
|
||||
end
|
||||
|
||||
assign I2C_RDATA = rdata;
|
||||
|
||||
always @(posedge CLK) begin
|
||||
reg old_clk;
|
||||
reg old_st;
|
||||
reg rd,len;
|
||||
|
||||
old_clk <= I2C_CLOCK;
|
||||
old_st <= START;
|
||||
|
||||
// delay to make sure SDA changed while SCL is stabilized at low
|
||||
if(old_clk && ~I2C_CLOCK && ~SD_COUNTER[5]) SDO[0] <= SD[SD_COUNTER[4:0]];
|
||||
SDO[3:1] <= SDO[2:0];
|
||||
|
||||
if(~old_st && START) begin
|
||||
SCLK <= 1;
|
||||
SDO <= 4'b1111;
|
||||
ACK <= 0;
|
||||
END <= 0;
|
||||
rd <= READ;
|
||||
len <= I2C_WLEN;
|
||||
if(READ) SD <= {2'b10, I2C_ADDR, 1'b1, 1'b1, 8'b11111111, 1'b0, 3'b011, 9'b111111111};
|
||||
else SD <= {2'b10, I2C_ADDR, 1'b0, 1'b1, I2C_WDATA1, 1'b1, I2C_WDATA2, 4'b1011};
|
||||
SD_COUNTER <= 0;
|
||||
end else begin
|
||||
if(~old_clk && I2C_CLOCK && ~&SD_COUNTER) begin
|
||||
SD_COUNTER <= SD_COUNTER + 6'd1;
|
||||
case(SD_COUNTER)
|
||||
01: SCLK <= 0;
|
||||
10: ACK <= ACK | I2C_SDA;
|
||||
19: if(~rd) begin
|
||||
ACK <= ACK | I2C_SDA;
|
||||
if(~len) SD_COUNTER <= 29;
|
||||
end
|
||||
20: if(rd) SCLK <= 1;
|
||||
23: if(rd) END <= 1;
|
||||
28: if(~rd) ACK <= ACK | I2C_SDA;
|
||||
29: if(~rd) SCLK <= 1;
|
||||
32: if(~rd) END <= 1;
|
||||
endcase
|
||||
|
||||
if(SD_COUNTER >= 11 && SD_COUNTER <= 18) rdata[SD_COUNTER[4:0]-11] <= I2C_SDA;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
54
sys/i2s.v
Normal file
54
sys/i2s.v
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
module i2s
|
||||
#(
|
||||
parameter AUDIO_DW = 16
|
||||
)
|
||||
(
|
||||
input reset,
|
||||
input clk,
|
||||
input ce,
|
||||
|
||||
output reg sclk,
|
||||
output reg lrclk,
|
||||
output reg sdata,
|
||||
|
||||
input [AUDIO_DW-1:0] left_chan,
|
||||
input [AUDIO_DW-1:0] right_chan
|
||||
);
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [7:0] bit_cnt;
|
||||
reg msclk;
|
||||
|
||||
reg [AUDIO_DW-1:0] left;
|
||||
reg [AUDIO_DW-1:0] right;
|
||||
|
||||
if (reset) begin
|
||||
bit_cnt <= 1;
|
||||
lrclk <= 1;
|
||||
sclk <= 1;
|
||||
msclk <= 1;
|
||||
end
|
||||
else begin
|
||||
sclk <= msclk;
|
||||
if(ce) begin
|
||||
msclk <= ~msclk;
|
||||
if(msclk) begin
|
||||
if(bit_cnt >= AUDIO_DW) begin
|
||||
bit_cnt <= 1;
|
||||
lrclk <= ~lrclk;
|
||||
if(lrclk) begin
|
||||
left <= left_chan;
|
||||
right <= right_chan;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
bit_cnt <= bit_cnt + 1'd1;
|
||||
end
|
||||
sdata <= lrclk ? right[AUDIO_DW - bit_cnt] : left[AUDIO_DW - bit_cnt];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
213
sys/iir_filter.v
Normal file
213
sys/iir_filter.v
Normal file
@@ -0,0 +1,213 @@
|
||||
|
||||
// 3-tap IIR filter for 2 channels.
|
||||
// Copyright (C) 2020 Sorgelig
|
||||
//
|
||||
// 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.
|
||||
|
||||
//
|
||||
// Can be converted to 2-tap (coeff_x2 = 0, coeff_y2 = 0) or 1-tap (coeff_x1,2 = 0, coeff_y1,2 = 0)
|
||||
//
|
||||
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) 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
|
||||
|
||||
reg [31:0] out;
|
||||
always @(posedge clk) if (sample_ce) out <= {out_l, out_r};
|
||||
|
||||
assign {output_l, output_r} = out;
|
||||
|
||||
endmodule
|
||||
|
||||
module iir_filter_tap
|
||||
(
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
input ce,
|
||||
input ch,
|
||||
|
||||
input [7:0] cx,
|
||||
input [23:0] cy,
|
||||
|
||||
input [39:0] x,
|
||||
input [39:0] y,
|
||||
input [39:0] z,
|
||||
output [39:0] tap
|
||||
);
|
||||
|
||||
wire signed [60:0] y_mul = $signed(y[36:0]) * $signed(cy);
|
||||
|
||||
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]};
|
||||
if(cx[1]) x_mul = x_mul + {{3{x[39]}}, x[39:3]};
|
||||
if(cx[2]) x_mul = x_mul + {{2{x[39]}}, x[39:2]};
|
||||
if(cx[7]) x_mul = ~x_mul; //cheap NEG
|
||||
end
|
||||
endfunction
|
||||
|
||||
(* ramstyle = "logic" *) reg [39:0] intreg[2];
|
||||
always @(posedge clk, posedge reset) begin
|
||||
if(reset) {intreg[0],intreg[1]} <= 80'd0;
|
||||
else if(ce) intreg[ch] <= x_mul(x) - y_mul[60:21] + z;
|
||||
end
|
||||
|
||||
assign tap = intreg[ch];
|
||||
|
||||
endmodule
|
||||
|
||||
// simplified IIR 1-tap.
|
||||
module DC_blocker
|
||||
(
|
||||
input clk,
|
||||
input ce, // 48/96 KHz
|
||||
input mute,
|
||||
|
||||
input sample_rate,
|
||||
input [15:0] din,
|
||||
output [15:0] dout
|
||||
);
|
||||
|
||||
wire [39:0] x = {din[15], din, 23'd0};
|
||||
wire [39:0] x0 = x - (sample_rate ? {{11{x[39]}}, x[39:11]} : {{10{x[39]}}, x[39:10]});
|
||||
wire [39:0] y1 = y - (sample_rate ? {{10{y[39]}}, y[39:10]} : {{09{y[39]}}, y[39:09]});
|
||||
wire [39:0] y0 = x0 - x1 + y1;
|
||||
|
||||
reg [39:0] x1, y;
|
||||
always @(posedge clk) if(ce) begin
|
||||
x1 <= x0;
|
||||
y <= ^y0[39:38] ? {{2{y0[39]}},{38{y0[38]}}} : y0;
|
||||
end
|
||||
|
||||
assign dout = mute ? 16'd0 : y[38:23];
|
||||
|
||||
endmodule
|
||||
162
sys/ltc2308.sv
Normal file
162
sys/ltc2308.sv
Normal file
@@ -0,0 +1,162 @@
|
||||
//============================================================================
|
||||
//
|
||||
// LTC2308 controller
|
||||
// Copyright (C) 2019 Sorgelig
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
|
||||
// NUM_CH 1..8
|
||||
// Sampling rate = ADC_RATE/NUM_CH
|
||||
// ADC_RATE max is ~500KHz
|
||||
// CLK_RATE max is ~80MHz
|
||||
module ltc2308 #(parameter NUM_CH = 2, ADC_RATE = 96000, CLK_RATE = 50000000)
|
||||
(
|
||||
input reset,
|
||||
input clk,
|
||||
|
||||
inout [3:0] ADC_BUS,
|
||||
|
||||
output reg dout_sync, // toggle with every ADC round
|
||||
output reg [(NUM_CH*12)-1:0] dout // 12 bits per channel (unsigned)
|
||||
);
|
||||
|
||||
localparam TCONV = CLK_RATE/625000;
|
||||
|
||||
reg sck;
|
||||
wire sdo = cfg[5];
|
||||
|
||||
assign ADC_BUS[3] = sck;
|
||||
wire sdi = ADC_BUS[2];
|
||||
assign ADC_BUS[1] = sdo;
|
||||
assign ADC_BUS[0] = convst;
|
||||
|
||||
reg convst;
|
||||
reg [5:0] cfg;
|
||||
|
||||
reg [31:0] sum;
|
||||
wire [31:0] next_sum = sum + ADC_RATE;
|
||||
|
||||
reg [2:0] pin;
|
||||
wire [2:0] next_pin = (pin == (NUM_CH-1)) ? 3'd0 : (pin + 1'd1);
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [7:0] tconv;
|
||||
reg [3:0] bitcnt;
|
||||
reg [10:0] adcin;
|
||||
|
||||
convst <= 0;
|
||||
|
||||
if(reset) begin
|
||||
sum <= 0;
|
||||
tconv <= 0;
|
||||
bitcnt <= 0;
|
||||
sck <= 0;
|
||||
cfg <= 0;
|
||||
dout <= 0;
|
||||
pin <= NUM_CH[2:0]-1'd1;
|
||||
end
|
||||
else begin
|
||||
sum <= next_sum;
|
||||
if(next_sum >= CLK_RATE) begin
|
||||
sum <= next_sum - CLK_RATE;
|
||||
tconv <= TCONV[7:0];
|
||||
convst <= 1;
|
||||
bitcnt <= 12;
|
||||
cfg <= {1'b1, next_pin[0], next_pin[2:1], 1'b1, 1'b0};
|
||||
if(!next_pin) dout_sync <= ~dout_sync;
|
||||
end
|
||||
|
||||
if(tconv) tconv <= tconv - 1'd1;
|
||||
else if(bitcnt) begin
|
||||
sck <= ~sck;
|
||||
|
||||
if(sck) cfg <= cfg<<1;
|
||||
else begin
|
||||
adcin <= {adcin[9:0],sdi};
|
||||
bitcnt <= bitcnt - 1'd1;
|
||||
if(bitcnt == 1) begin
|
||||
dout[pin*12 +:12] <= {adcin,sdi};
|
||||
pin <= next_pin;
|
||||
end
|
||||
end
|
||||
end
|
||||
else sck <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module ltc2308_tape #(parameter HIST_LOW = 16, HIST_HIGH = 64, ADC_RATE = 48000, CLK_RATE = 50000000)
|
||||
(
|
||||
input reset,
|
||||
input clk,
|
||||
|
||||
inout [3:0] ADC_BUS,
|
||||
output reg dout,
|
||||
output active
|
||||
);
|
||||
|
||||
wire [11:0] adc_data;
|
||||
wire adc_sync;
|
||||
ltc2308 #(1, ADC_RATE, CLK_RATE) adc
|
||||
(
|
||||
.reset(reset),
|
||||
.clk(clk),
|
||||
|
||||
.ADC_BUS(ADC_BUS),
|
||||
.dout(adc_data),
|
||||
.dout_sync(adc_sync)
|
||||
);
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [13:0] data1,data2,data3,data4, sum;
|
||||
reg adc_sync_d;
|
||||
|
||||
adc_sync_d<=adc_sync;
|
||||
if(adc_sync_d ^ adc_sync) begin
|
||||
data1 <= data2;
|
||||
data2 <= data3;
|
||||
data3 <= data4;
|
||||
data4 <= adc_data;
|
||||
|
||||
sum <= data1+data2+data3+data4;
|
||||
|
||||
if(sum[13:2]<HIST_LOW) dout <= 0;
|
||||
if(sum[13:2]>HIST_HIGH) dout <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
assign active = |act;
|
||||
|
||||
reg [1:0] act;
|
||||
always @(posedge clk) begin
|
||||
reg [31:0] onesec;
|
||||
reg old_dout;
|
||||
|
||||
onesec <= onesec + 1;
|
||||
if(onesec>CLK_RATE) begin
|
||||
onesec <= 0;
|
||||
if(act) act <= act - 1'd1;
|
||||
end
|
||||
|
||||
old_dout <= dout;
|
||||
if(old_dout ^ dout) act <= 2;
|
||||
end
|
||||
|
||||
endmodule
|
||||
109
sys/math.sv
Normal file
109
sys/math.sv
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
// result = num/div
|
||||
module sys_udiv
|
||||
#(
|
||||
parameter NB_NUM,
|
||||
parameter NB_DIV
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input start,
|
||||
output busy,
|
||||
|
||||
input [NB_NUM-1:0] num,
|
||||
input [NB_DIV-1:0] div,
|
||||
output reg [NB_NUM-1:0] result,
|
||||
output reg [NB_DIV-1:0] remainder
|
||||
);
|
||||
|
||||
reg run;
|
||||
assign busy = run;
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [5:0] cpt;
|
||||
reg [NB_NUM+NB_DIV+1:0] rem;
|
||||
|
||||
if (start) begin
|
||||
cpt <= 0;
|
||||
run <= 1;
|
||||
rem <= num;
|
||||
end
|
||||
else if (run) begin
|
||||
cpt <= cpt + 1'd1;
|
||||
run <= (cpt != NB_NUM + 1'd1);
|
||||
remainder <= rem[NB_NUM+NB_DIV:NB_NUM+1];
|
||||
if (!rem[NB_DIV + NB_NUM + 1'd1])
|
||||
rem <= {rem[NB_DIV+NB_NUM:0] - (div << NB_NUM),1'b0};
|
||||
else
|
||||
rem <= {rem[NB_DIV+NB_NUM:0] + (div << NB_NUM),1'b0};
|
||||
result <= {result[NB_NUM-2:0], !rem[NB_DIV + NB_NUM + 1'd1]};
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
// result = mul1*mul2
|
||||
module sys_umul
|
||||
#(
|
||||
parameter NB_MUL1,
|
||||
parameter NB_MUL2
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input start,
|
||||
output busy,
|
||||
|
||||
input [NB_MUL1-1:0] mul1,
|
||||
input [NB_MUL2-1:0] mul2,
|
||||
output reg [NB_MUL1+NB_MUL2-1:0] result
|
||||
);
|
||||
|
||||
reg run;
|
||||
assign busy = run;
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [NB_MUL1+NB_MUL2-1:0] add;
|
||||
reg [NB_MUL2-1:0] map;
|
||||
|
||||
if (start) begin
|
||||
run <= 1;
|
||||
result <= 0;
|
||||
add <= mul1;
|
||||
map <= mul2;
|
||||
end
|
||||
else if (run) begin
|
||||
if(!map) run <= 0;
|
||||
if(map[0]) result <= result + add;
|
||||
add <= add << 1;
|
||||
map <= map >> 1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
// result = (mul1*mul2)/div
|
||||
module sys_umuldiv
|
||||
#(
|
||||
parameter NB_MUL1,
|
||||
parameter NB_MUL2,
|
||||
parameter NB_DIV
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input start,
|
||||
output busy,
|
||||
|
||||
input [NB_MUL1-1:0] mul1,
|
||||
input [NB_MUL2-1:0] mul2,
|
||||
input [NB_DIV-1:0] div,
|
||||
output [NB_MUL1+NB_MUL2-1:0] result,
|
||||
output [NB_DIV-1:0] remainder
|
||||
);
|
||||
|
||||
wire mul_run;
|
||||
wire [NB_MUL1+NB_MUL2-1:0] mul_res;
|
||||
sys_umul #(NB_MUL1,NB_MUL2) umul(clk,start,mul_run,mul1,mul2,mul_res);
|
||||
|
||||
sys_udiv #(NB_MUL1+NB_MUL2,NB_DIV) udiv(clk,start|mul_run,busy,mul_res,div,result,remainder);
|
||||
|
||||
endmodule
|
||||
113
sys/mcp23009.sv
Normal file
113
sys/mcp23009.sv
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// MCP23009
|
||||
// (C) 2019 Alexey Melnikov
|
||||
//
|
||||
module mcp23009
|
||||
(
|
||||
input clk,
|
||||
|
||||
output reg [2:0] btn,
|
||||
input [2:0] led,
|
||||
output reg sd_cd,
|
||||
|
||||
output scl,
|
||||
inout sda
|
||||
);
|
||||
|
||||
|
||||
reg start = 0;
|
||||
wire ready;
|
||||
wire error;
|
||||
reg rw;
|
||||
wire [7:0] dout;
|
||||
reg [15:0] din;
|
||||
|
||||
i2c #(50_000_000, 500_000) i2c
|
||||
(
|
||||
.CLK(clk),
|
||||
.START(start),
|
||||
.READ(rw),
|
||||
.I2C_ADDR('h20),
|
||||
.I2C_WLEN(1),
|
||||
.I2C_WDATA1(din[15:8]),
|
||||
.I2C_WDATA2(din[7:0]),
|
||||
.I2C_RDATA(dout),
|
||||
.END(ready),
|
||||
.ACK(error),
|
||||
.I2C_SCL(scl),
|
||||
.I2C_SDA(sda)
|
||||
);
|
||||
|
||||
always@(posedge clk) begin
|
||||
reg [3:0] idx = 0;
|
||||
reg [1:0] state = 0;
|
||||
reg [15:0] timeout = 0;
|
||||
|
||||
if(~&timeout) begin
|
||||
timeout <= timeout + 1'd1;
|
||||
start <= 0;
|
||||
state <= 0;
|
||||
idx <= 0;
|
||||
btn <= 0;
|
||||
rw <= 0;
|
||||
sd_cd <= 1;
|
||||
end
|
||||
else begin
|
||||
if(~&init_data[idx]) begin
|
||||
case(state)
|
||||
0: begin
|
||||
start <= 1;
|
||||
state <= 1;
|
||||
din <= init_data[idx];
|
||||
end
|
||||
1: if(~ready) state <= 2;
|
||||
2: begin
|
||||
start <= 0;
|
||||
if(ready) begin
|
||||
state <= 0;
|
||||
if(!error) idx <= idx + 1'd1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
else begin
|
||||
case(state)
|
||||
0: begin
|
||||
start <= 1;
|
||||
state <= 1;
|
||||
din <= {8'h09,5'b00000,led};
|
||||
end
|
||||
1: if(~ready) state <= 2;
|
||||
2: begin
|
||||
start <= 0;
|
||||
if(ready) begin
|
||||
state <= 0;
|
||||
rw <= 0;
|
||||
if(!error) begin
|
||||
if(rw) {sd_cd, btn} <= {dout[7], dout[5:3]};
|
||||
rw <= ~rw;
|
||||
end
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire [15:0] init_data[12] =
|
||||
'{
|
||||
16'h00F8,
|
||||
16'h0138,
|
||||
16'h0200,
|
||||
16'h0300,
|
||||
16'h0400,
|
||||
16'h0524,
|
||||
16'h06FF,
|
||||
16'h0700,
|
||||
16'h0800,
|
||||
16'h0900,
|
||||
16'h0A00,
|
||||
16'hFFFF
|
||||
};
|
||||
|
||||
endmodule
|
||||
283
sys/mt32pi.sv
Normal file
283
sys/mt32pi.sv
Normal file
@@ -0,0 +1,283 @@
|
||||
//
|
||||
// Communication module to MT32-pi (external MIDI emulator on RPi)
|
||||
// (C) 2020 Sorgelig, Kitrinx
|
||||
//
|
||||
// https://github.com/dwhinham/mt32-pi
|
||||
//
|
||||
|
||||
module mt32pi
|
||||
(
|
||||
input CLK_AUDIO,
|
||||
|
||||
input CLK_VIDEO,
|
||||
input CE_PIXEL,
|
||||
input VGA_VS,
|
||||
input VGA_DE,
|
||||
|
||||
input [6:0] USER_IN,
|
||||
output [6:0] USER_OUT,
|
||||
|
||||
input reset,
|
||||
input midi_tx,
|
||||
output midi_rx,
|
||||
|
||||
output reg [15:0] mt32_i2s_r,
|
||||
output reg [15:0] mt32_i2s_l,
|
||||
|
||||
output reg mt32_available,
|
||||
|
||||
input mt32_mode_req,
|
||||
input [1:0] mt32_rom_req,
|
||||
input [7:0] mt32_sf_req,
|
||||
|
||||
output reg [7:0] mt32_mode,
|
||||
output reg [7:0] mt32_rom,
|
||||
output reg [7:0] mt32_sf,
|
||||
output reg mt32_newmode,
|
||||
|
||||
output reg mt32_lcd_en,
|
||||
output reg mt32_lcd_pix,
|
||||
output reg mt32_lcd_update
|
||||
);
|
||||
|
||||
//
|
||||
// Pin | USB Name | Signal
|
||||
// ----+----------+--------------
|
||||
// 0 | D+ | I/O I2C_SDA / RX (midi in)
|
||||
// 1 | D- | O TX (midi out)
|
||||
// 2 | TX- | I I2S_WS (1 == right)
|
||||
// 3 | GND_d | I I2C_SCL
|
||||
// 4 | RX+ | I I2S_BCLK
|
||||
// 5 | RX- | I I2S_DAT
|
||||
// 6 | TX+ | - none
|
||||
//
|
||||
|
||||
assign USER_OUT[0] = sda_out;
|
||||
assign USER_OUT[1] = midi_tx;
|
||||
assign USER_OUT[6:2] = '1;
|
||||
|
||||
|
||||
//
|
||||
// crossed/straight cable selection
|
||||
//
|
||||
|
||||
generate
|
||||
genvar i;
|
||||
for(i = 0; i<2; i++) begin : clk_rate
|
||||
wire clk_in = i ? USER_IN[6] : USER_IN[4];
|
||||
reg [4:0] cnt;
|
||||
always @(posedge CLK_AUDIO) begin : clkr
|
||||
reg clk_sr, clk, old_clk;
|
||||
reg [4:0] cnt_tmp;
|
||||
|
||||
clk_sr <= clk_in;
|
||||
if (clk_sr == clk_in) clk <= clk_sr;
|
||||
|
||||
if(~&cnt_tmp) cnt_tmp <= cnt_tmp + 1'd1;
|
||||
else cnt <= '1;
|
||||
|
||||
old_clk <= clk;
|
||||
if(~old_clk & clk) begin
|
||||
cnt <= cnt_tmp;
|
||||
cnt_tmp <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg crossed;
|
||||
always @(posedge CLK_AUDIO) crossed <= (clk_rate[0].cnt <= clk_rate[1].cnt);
|
||||
endgenerate
|
||||
|
||||
wire i2s_ws = crossed ? USER_IN[2] : USER_IN[5];
|
||||
wire i2s_data = crossed ? USER_IN[5] : USER_IN[2];
|
||||
wire i2s_bclk = crossed ? USER_IN[4] : USER_IN[6];
|
||||
assign midi_rx = ~mt32_available ? USER_IN[0] : crossed ? USER_IN[6] : USER_IN[4];
|
||||
|
||||
|
||||
//
|
||||
// i2s receiver
|
||||
//
|
||||
|
||||
always @(posedge CLK_AUDIO) begin : i2s_proc
|
||||
reg [15:0] i2s_buf = 0;
|
||||
reg [4:0] i2s_cnt = 0;
|
||||
reg clk_sr;
|
||||
reg i2s_clk = 0;
|
||||
reg old_clk, old_ws;
|
||||
reg i2s_next = 0;
|
||||
|
||||
// Debounce clock
|
||||
clk_sr <= i2s_bclk;
|
||||
if (clk_sr == i2s_bclk) i2s_clk <= clk_sr;
|
||||
|
||||
// Latch data and ws on rising edge
|
||||
old_clk <= i2s_clk;
|
||||
if (i2s_clk && ~old_clk) begin
|
||||
|
||||
if (~i2s_cnt[4]) begin
|
||||
i2s_cnt <= i2s_cnt + 1'd1;
|
||||
i2s_buf[~i2s_cnt[3:0]] <= i2s_data;
|
||||
end
|
||||
|
||||
// Word Select will change 1 clock before the new word starts
|
||||
old_ws <= i2s_ws;
|
||||
if (old_ws != i2s_ws) i2s_next <= 1;
|
||||
end
|
||||
|
||||
if (i2s_next) begin
|
||||
i2s_next <= 0;
|
||||
i2s_cnt <= 0;
|
||||
i2s_buf <= 0;
|
||||
|
||||
if (i2s_ws) mt32_i2s_l <= i2s_buf;
|
||||
else mt32_i2s_r <= i2s_buf;
|
||||
end
|
||||
|
||||
if (reset) begin
|
||||
i2s_buf <= 0;
|
||||
mt32_i2s_l <= 0;
|
||||
mt32_i2s_r <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//
|
||||
// i2c slave
|
||||
//
|
||||
|
||||
reg sda_out;
|
||||
reg [7:0] lcd_data[1024];
|
||||
reg lcd_sz;
|
||||
|
||||
reg reset_r = 0;
|
||||
wire [7:0] mode_req = reset_r ? 8'hA0 : mt32_mode_req ? 8'hA2 : 8'hA1;
|
||||
wire [7:0] rom_req = {6'd0, mt32_rom_req};
|
||||
|
||||
always @(posedge CLK_AUDIO) begin : i2c_slave
|
||||
reg sda_sr, scl_sr;
|
||||
reg old_sda, old_scl;
|
||||
reg sda, scl;
|
||||
reg [7:0] tmp;
|
||||
reg [3:0] cnt = 0;
|
||||
reg [10:0] bcnt = 0;
|
||||
reg ack;
|
||||
reg i2c_rw;
|
||||
reg disp, dispdata;
|
||||
reg [2:0] div;
|
||||
reg old_reset;
|
||||
|
||||
old_reset <= reset;
|
||||
if(old_reset & ~reset) sda_out <= 1;
|
||||
|
||||
div <= div + 1'd1;
|
||||
if(!div) begin
|
||||
sda_sr <= USER_IN[0];
|
||||
if(sda_sr == USER_IN[0]) sda <= sda_sr;
|
||||
old_sda <= sda;
|
||||
|
||||
scl_sr <= USER_IN[3];
|
||||
if(scl_sr == USER_IN[3]) scl <= scl_sr;
|
||||
old_scl <= scl;
|
||||
|
||||
//start
|
||||
if(old_scl & scl & old_sda & ~sda) begin
|
||||
cnt <= 9;
|
||||
bcnt <= 0;
|
||||
ack <= 0;
|
||||
i2c_rw <= 0;
|
||||
disp <= 0;
|
||||
dispdata <= 0;
|
||||
end
|
||||
|
||||
//stop
|
||||
if(old_scl & scl & ~old_sda & sda) begin
|
||||
cnt <= 0;
|
||||
if(dispdata) begin
|
||||
lcd_sz <= ~bcnt[9];
|
||||
mt32_lcd_update <= ~mt32_lcd_update;
|
||||
end
|
||||
end
|
||||
|
||||
//data latch
|
||||
if(~old_scl && scl && cnt) begin
|
||||
tmp <= {tmp[6:0], sda};
|
||||
cnt <= cnt - 1'd1;
|
||||
end
|
||||
|
||||
if(!cnt) sda_out <= 1;
|
||||
|
||||
//data set
|
||||
if(old_scl && ~scl) begin
|
||||
sda_out <= 1;
|
||||
if(cnt == 1) begin
|
||||
if(!bcnt) begin
|
||||
if(tmp[7:1] == 'h45 || tmp[7:1] == 'h3c) begin
|
||||
disp <= (tmp[7:1] == 'h3c);
|
||||
sda_out <= 0;
|
||||
mt32_available <= 1;
|
||||
ack <= 1;
|
||||
i2c_rw <= tmp[0];
|
||||
bcnt <= bcnt + 1'd1;
|
||||
cnt <= 10;
|
||||
end
|
||||
else begin
|
||||
// wrong address, stop
|
||||
cnt <= 0;
|
||||
end
|
||||
end
|
||||
else if(ack) begin
|
||||
if(~i2c_rw) begin
|
||||
if(disp) begin
|
||||
if(bcnt == 1) dispdata <= (tmp[7:6] == 2'b01);
|
||||
else if(dispdata) lcd_data[bcnt[9:0] - 2'd2] <= tmp;
|
||||
end
|
||||
else begin
|
||||
if(bcnt == 1) mt32_mode <= tmp;
|
||||
if(bcnt == 2) mt32_rom <= tmp;
|
||||
if(bcnt == 3) mt32_sf <= tmp;
|
||||
if(bcnt == 3) mt32_newmode <= ~mt32_newmode;
|
||||
end
|
||||
end
|
||||
if(~&bcnt) bcnt <= bcnt + 1'd1;
|
||||
sda_out <= 0;
|
||||
cnt <= 10;
|
||||
end
|
||||
end
|
||||
else if(i2c_rw && ack && cnt && ~disp) begin
|
||||
if(bcnt == 1) sda_out <= mode_req[cnt[2:0] - 2'd2];
|
||||
if(bcnt == 2) sda_out <= rom_req[cnt[2:0] - 2'd2];
|
||||
if(bcnt == 3) sda_out <= mt32_sf_req[cnt[2:0] - 2'd2];
|
||||
if(bcnt == 3) reset_r <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(reset) begin
|
||||
reset_r <= 1;
|
||||
mt32_available <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg old_de, old_vs;
|
||||
reg [7:0] hcnt;
|
||||
reg [6:0] vcnt;
|
||||
reg [7:0] sh;
|
||||
|
||||
if(CE_PIXEL) begin
|
||||
old_de <= VGA_DE;
|
||||
old_vs <= VGA_VS;
|
||||
|
||||
if(~&hcnt) hcnt <= hcnt + 1'd1;
|
||||
sh <= (sh << 1) | (~old_de & VGA_DE);
|
||||
if(sh[7]) hcnt <= 0;
|
||||
|
||||
if(old_de & ~VGA_DE & ~&vcnt) vcnt <= vcnt + 1'd1;
|
||||
if(~old_vs & VGA_VS) vcnt <= 0;
|
||||
|
||||
mt32_lcd_en <= mt32_available & ~hcnt[7] && (lcd_sz ? !vcnt[6] : !vcnt[6:5]);
|
||||
mt32_lcd_pix <= lcd_data[{vcnt[5:3],hcnt[6:0]}][vcnt[2:0]];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
286
sys/osd.v
Normal file
286
sys/osd.v
Normal file
@@ -0,0 +1,286 @@
|
||||
// A simple OSD implementation. Can be hooked up between a cores
|
||||
// VGA output and the physical VGA pins
|
||||
|
||||
module osd
|
||||
(
|
||||
input clk_sys,
|
||||
input io_osd,
|
||||
input io_strobe,
|
||||
input [15:0] io_din,
|
||||
|
||||
input clk_video,
|
||||
input [23:0] din,
|
||||
input de_in,
|
||||
input vs_in,
|
||||
input hs_in,
|
||||
output [23:0] dout,
|
||||
output reg de_out,
|
||||
output reg vs_out,
|
||||
output reg hs_out,
|
||||
|
||||
output reg osd_status
|
||||
);
|
||||
|
||||
parameter OSD_COLOR = 3'd4;
|
||||
|
||||
localparam OSD_WIDTH = 12'd256;
|
||||
localparam OSD_HEIGHT = 12'd64;
|
||||
|
||||
`ifdef OSD_HEADER
|
||||
localparam OSD_HDR = 12'd24;
|
||||
`else
|
||||
localparam OSD_HDR = 12'd0;
|
||||
`endif
|
||||
|
||||
reg osd_enable;
|
||||
(* ramstyle="no_rw_check" *) reg [7:0] osd_buffer[OSD_HDR ? (4096+1024) : 4096];
|
||||
|
||||
reg info = 0;
|
||||
reg [8:0] infoh;
|
||||
reg [8:0] infow;
|
||||
reg [21:0] infox;
|
||||
reg [21:0] infoy;
|
||||
reg [21:0] osd_h;
|
||||
reg [21:0] osd_t;
|
||||
reg [21:0] osd_w;
|
||||
|
||||
reg [1:0] rot = 0;
|
||||
|
||||
always@(posedge clk_sys) begin
|
||||
reg [12:0] bcnt;
|
||||
reg [7:0] cmd;
|
||||
reg has_cmd;
|
||||
reg old_strobe;
|
||||
reg highres = 0;
|
||||
|
||||
osd_t <= rot[0] ? OSD_WIDTH : (OSD_HEIGHT<<1);
|
||||
osd_h <= rot[0] ? (info ? infow : OSD_WIDTH) : info ? infoh : (OSD_HEIGHT<<highres);
|
||||
osd_w <= rot[0] ? (info ? infoh : (OSD_HEIGHT<<highres)) : (info ? infow : OSD_WIDTH);
|
||||
|
||||
old_strobe <= io_strobe;
|
||||
|
||||
if(~io_osd) begin
|
||||
bcnt <= 0;
|
||||
has_cmd <= 0;
|
||||
cmd <= 0;
|
||||
if(cmd[7:4] == 4) osd_enable <= cmd[0];
|
||||
end else begin
|
||||
if(~old_strobe & io_strobe) begin
|
||||
if(!has_cmd) begin
|
||||
has_cmd <= 1;
|
||||
cmd <= io_din[7:0];
|
||||
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
|
||||
if(io_din[7:4] == 4) begin
|
||||
if(!io_din[0]) {osd_status,highres} <= 0;
|
||||
else {osd_status,info} <= {~io_din[2],io_din[2]};
|
||||
bcnt <= 0;
|
||||
end
|
||||
// command 0x20: OSDCMDWRITE
|
||||
if(io_din[7:5] == 'b001) begin
|
||||
if(io_din[3]) highres <= 1;
|
||||
bcnt <= {io_din[4:0], 8'h00};
|
||||
end
|
||||
end else begin
|
||||
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
|
||||
if(cmd[7:4] == 4) begin
|
||||
if(bcnt == 0) infox <= io_din[11:0];
|
||||
if(bcnt == 1) infoy <= io_din[11:0];
|
||||
if(bcnt == 2) infow <= {io_din[5:0], 3'b000};
|
||||
if(bcnt == 3) infoh <= {io_din[5:0], 3'b000};
|
||||
if(bcnt == 4) rot <= io_din[1:0];
|
||||
end
|
||||
|
||||
// command 0x20: OSDCMDWRITE
|
||||
if(cmd[7:5] == 'b001) osd_buffer[bcnt] <= io_din[7:0];
|
||||
|
||||
bcnt <= bcnt + 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
(* direct_enable *) reg ce_pix;
|
||||
always @(posedge clk_video) begin
|
||||
reg [21:0] cnt = 0;
|
||||
reg [21:0] pixsz, pixcnt;
|
||||
reg deD;
|
||||
|
||||
cnt <= cnt + 1'd1;
|
||||
deD <= de_in;
|
||||
|
||||
pixcnt <= pixcnt + 1'd1;
|
||||
if(pixcnt == pixsz) pixcnt <= 0;
|
||||
ce_pix <= !pixcnt;
|
||||
|
||||
if(~deD && de_in) cnt <= 0;
|
||||
|
||||
if(deD && ~de_in) begin
|
||||
pixsz <= (((cnt+1'b1) >> (9-rot[0])) > 1) ? (((cnt+1'b1) >> (9-rot[0])) - 1'd1) : 22'd0;
|
||||
pixcnt <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
reg [2:0] osd_de;
|
||||
reg osd_pixel;
|
||||
reg [21:0] v_cnt;
|
||||
reg v_cnt_h, v_cnt_1, v_cnt_2, v_cnt_3, v_cnt_4;
|
||||
reg [21:0] v_osd_start_h, v_osd_start_1, v_osd_start_2, v_osd_start_3, v_osd_start_4, v_osd_start_5;
|
||||
reg [21:0] v_info_start_h, v_info_start_1, v_info_start_2, v_info_start_3, v_info_start_4, v_info_start_5;
|
||||
|
||||
wire [21:0] osd_h_hdr = (info || rot) ? osd_h : (osd_h + OSD_HDR);
|
||||
|
||||
// pipeline the comparisons a bit
|
||||
always @(posedge clk_video) if(ce_pix) begin
|
||||
v_cnt_h <= v_cnt < osd_t;
|
||||
v_cnt_1 <= v_cnt < 320;
|
||||
v_cnt_2 <= v_cnt < 640;
|
||||
v_cnt_3 <= v_cnt < 960;
|
||||
v_cnt_4 <= v_cnt < 1280;
|
||||
|
||||
v_osd_start_h <= (v_cnt-(osd_h_hdr>>1))>>1;
|
||||
v_osd_start_1 <= (v_cnt-osd_h_hdr)>>1;
|
||||
v_osd_start_2 <= (v_cnt-(osd_h_hdr<<1))>>1;
|
||||
v_osd_start_3 <= (v_cnt-(osd_h_hdr + (osd_h_hdr<<1)))>>1;
|
||||
v_osd_start_4 <= (v_cnt-(osd_h_hdr<<2))>>1;
|
||||
v_osd_start_5 <= (v_cnt-(osd_h_hdr + (osd_h_hdr<<2)))>>1;
|
||||
|
||||
v_info_start_h <= rot[0] ? infox : infoy;
|
||||
v_info_start_1 <= rot[0] ? infox : infoy;
|
||||
v_info_start_2 <= rot[0] ? (infox<<1) : (infoy<<1);
|
||||
v_info_start_3 <= rot[0] ? (infox + (infox << 1)) : (infoy + (infoy << 1));
|
||||
v_info_start_4 <= rot[0] ? (infox << 2) : (infoy << 2);
|
||||
v_info_start_5 <= rot[0] ? (infox + (infox << 2)) : (infoy + (infoy << 2));
|
||||
end
|
||||
|
||||
always @(posedge clk_video) begin
|
||||
reg deD;
|
||||
reg [2:0] osd_div;
|
||||
reg [2:0] multiscan;
|
||||
reg [7:0] osd_byte;
|
||||
reg [23:0] h_cnt;
|
||||
reg [21:0] dsp_width;
|
||||
reg [21:0] osd_vcnt;
|
||||
reg [21:0] h_osd_start;
|
||||
reg [21:0] v_osd_start;
|
||||
reg [21:0] osd_hcnt;
|
||||
reg [21:0] osd_hcnt2;
|
||||
reg osd_de1,osd_de2;
|
||||
reg [1:0] osd_en;
|
||||
reg f1;
|
||||
reg half;
|
||||
|
||||
if(ce_pix) begin
|
||||
|
||||
deD <= de_in;
|
||||
if(~&h_cnt) h_cnt <= h_cnt + 1'd1;
|
||||
|
||||
if(~&osd_hcnt) osd_hcnt <= osd_hcnt + 1'd1;
|
||||
if(~&osd_hcnt2) osd_hcnt2 <= osd_hcnt2 + 1'd1;
|
||||
|
||||
if (h_cnt == h_osd_start) begin
|
||||
osd_de[0] <= osd_en[1] && osd_h && (
|
||||
osd_vcnt[11] ? (osd_vcnt[7] && (osd_vcnt[6:0] >= 4) && (osd_vcnt[6:0] < 19)) :
|
||||
(info && (rot == 3)) ? !osd_vcnt[21:8] :
|
||||
(osd_vcnt < osd_h)
|
||||
);
|
||||
osd_hcnt <= 0;
|
||||
osd_hcnt2 <= 0;
|
||||
if(info && rot == 1) osd_hcnt2 <= 22'd128-infoh;
|
||||
end
|
||||
if (osd_hcnt+1 == osd_w) osd_de[0] <= 0;
|
||||
|
||||
// falling edge of de
|
||||
if(!de_in && deD) dsp_width <= h_cnt[21:0];
|
||||
|
||||
// rising edge of de
|
||||
if(de_in && !deD) begin
|
||||
h_cnt <= 0;
|
||||
v_cnt <= v_cnt + 1'd1;
|
||||
h_osd_start <= info ? (rot[0] ? infoy : infox) : (((dsp_width - osd_w)>>1) - 2'd2);
|
||||
|
||||
if(h_cnt > {dsp_width, 2'b00}) begin
|
||||
v_cnt <= 1;
|
||||
f1 <= ~f1; // skip every other frame for interlace compatibility.
|
||||
if(~f1) begin
|
||||
|
||||
osd_en <= (osd_en << 1) | osd_enable;
|
||||
if(~osd_enable) osd_en <= 0;
|
||||
|
||||
half <= 0;
|
||||
if(v_cnt_h) begin
|
||||
multiscan <= 0;
|
||||
v_osd_start <= info ? v_info_start_h : v_osd_start_h;
|
||||
half <= 1;
|
||||
end
|
||||
else if(v_cnt_1 | (rot[0] & v_cnt_2)) begin
|
||||
multiscan <= 0;
|
||||
v_osd_start <= info ? v_info_start_1 : v_osd_start_1;
|
||||
end
|
||||
else if(rot[0] ? v_cnt_3 : v_cnt_2) begin
|
||||
multiscan <= 1;
|
||||
v_osd_start <= info ? v_info_start_2 : v_osd_start_2;
|
||||
end
|
||||
else if(rot[0] ? v_cnt_4 : v_cnt_3) begin
|
||||
multiscan <= 2;
|
||||
v_osd_start <= info ? v_info_start_3 : v_osd_start_3;
|
||||
end
|
||||
else if(rot[0] | v_cnt_4) begin
|
||||
multiscan <= 3;
|
||||
v_osd_start <= info ? v_info_start_4 : v_osd_start_4;
|
||||
end
|
||||
else begin
|
||||
multiscan <= 4;
|
||||
v_osd_start <= info ? v_info_start_5 : v_osd_start_5;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
osd_div <= osd_div + 1'd1;
|
||||
if(osd_div == multiscan) begin
|
||||
osd_div <= 0;
|
||||
if(~osd_vcnt[10]) osd_vcnt <= osd_vcnt + 1'd1 + half;
|
||||
if(osd_vcnt == 'b100010011111 && ~info) osd_vcnt <= 0;
|
||||
end
|
||||
if(v_osd_start == v_cnt) begin
|
||||
{osd_div,osd_vcnt} <= 0;
|
||||
if(info && rot == 3) osd_vcnt <= 22'd256-infow;
|
||||
else if(OSD_HDR && !rot) osd_vcnt <= {~info, 3'b000, ~info, 7'b0000000};
|
||||
end
|
||||
end
|
||||
|
||||
osd_byte <= osd_buffer[rot[0] ? ({osd_hcnt2[6:3], osd_vcnt[7:0]} ^ { {4{~rot[1]}}, {8{rot[1]}} }) : {osd_vcnt[7:3], osd_hcnt[7:0]}];
|
||||
osd_pixel <= osd_byte[rot[0] ? ((osd_hcnt2[2:0]-1'd1) ^ {3{~rot[1]}}) : osd_vcnt[2:0]];
|
||||
osd_de[2:1] <= osd_de[1:0];
|
||||
end
|
||||
end
|
||||
|
||||
reg [23:0] rdout;
|
||||
assign dout = rdout;
|
||||
|
||||
always @(posedge clk_video) begin
|
||||
reg [23:0] ordout1, nrdout1, rdout2, rdout3;
|
||||
reg de1,de2,de3;
|
||||
reg osd_mux;
|
||||
reg vs1,vs2,vs3;
|
||||
reg hs1,hs2,hs3;
|
||||
|
||||
nrdout1 <= din;
|
||||
ordout1 <= {{osd_pixel, osd_pixel, OSD_COLOR[2], din[23:19]},// 23:16
|
||||
{osd_pixel, osd_pixel, OSD_COLOR[1], din[15:11]},// 15:8
|
||||
{osd_pixel, osd_pixel, OSD_COLOR[0], din[7:3]}}; // 7:0
|
||||
|
||||
osd_mux <= ~osd_de[2];
|
||||
rdout2 <= osd_mux ? nrdout1 : ordout1;
|
||||
rdout3 <= rdout2;
|
||||
|
||||
de1 <= de_in; de2 <= de1; de3 <= de2;
|
||||
hs1 <= hs_in; hs2 <= hs1; hs3 <= hs2;
|
||||
vs1 <= vs_in; vs2 <= vs1; vs3 <= vs2;
|
||||
|
||||
rdout <= rdout3;
|
||||
de_out <= de3;
|
||||
hs_out <= hs3;
|
||||
vs_out <= vs3;
|
||||
end
|
||||
|
||||
endmodule
|
||||
17
sys/pll.13.qip
Normal file
17
sys/pll.13.qip
Normal file
@@ -0,0 +1,17 @@
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_NAME "altera_pll"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim"
|
||||
set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"]
|
||||
set_global_assignment -name SYNTHESIS_ONLY_QIP ON
|
||||
|
||||
set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll.v
|
||||
set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll/pll_0002.v
|
||||
|
||||
set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*"
|
||||
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_ENV "mwpim"
|
||||
17
sys/pll_audio.13.qip
Normal file
17
sys/pll_audio.13.qip
Normal file
@@ -0,0 +1,17 @@
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_NAME "altera_pll"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_ENV "mwpim"
|
||||
set_global_assignment -library "pll_audio" -name MISC_FILE [file join $::quartus(qip_path) "pll_audio.cmp"]
|
||||
set_global_assignment -name SYNTHESIS_ONLY_QIP ON
|
||||
|
||||
set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio.v"]
|
||||
set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.v"]
|
||||
|
||||
set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*"
|
||||
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_NAME "altera_pll"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_ENV "mwpim"
|
||||
337
sys/pll_audio.qip
Normal file
337
sys/pll_audio.qip
Normal file
@@ -0,0 +1,337 @@
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_NAME "altera_pll"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_VERSION "17.0"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_ENV "mwpim"
|
||||
set_global_assignment -library "pll_audio" -name MISC_FILE [file join $::quartus(qip_path) "pll_audio.cmp"]
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_QSYS_MODE "UNKNOWN"
|
||||
set_global_assignment -name SYNTHESIS_ONLY_QIP ON
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_NAME "cGxsX2F1ZGlv"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA=="
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_INTERNAL "Off"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u"
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_VERSION "MTcuMA=="
|
||||
set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_NAME "cGxsX2F1ZGlvXzAwMDI="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_INTERNAL "Off"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_VERSION "MTcuMA=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::ZmFsc2U=::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::MQ==::TnVtYmVyIE9mIENsb2Nrcw=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::MQ==::bnVtYmVyX29mX2Nsb2Nrcw=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MjQuNTc2::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MTUyODMyMTE2Mw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::MTc=::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MjQuNTc2MDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NCw0LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSw5LDgsMSwwLHBoX211eF9jbGssZmFsc2UsdHJ1ZSwyLDIwLDQwMDAsNDE3Ljc5MiBNSHosMTUyODMyMTE2Myxub25lLGdsYixtX2NudCxwaF9tdXhfY2xrLHRydWU=::UGFyYW1ldGVyIFZhbHVlcw=="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw="
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw="
|
||||
|
||||
set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio.v"]
|
||||
set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.v"]
|
||||
set_global_assignment -library "pll_audio" -name QIP_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.qip"]
|
||||
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_NAME "altera_pll"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_VERSION "17.0"
|
||||
set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_ENV "mwpim"
|
||||
252
sys/pll_audio.v
Normal file
252
sys/pll_audio.v
Normal file
@@ -0,0 +1,252 @@
|
||||
// megafunction wizard: %Altera PLL v17.0%
|
||||
// GENERATION: XML
|
||||
// pll_audio.v
|
||||
|
||||
// Generated using ACDS version 17.0 602
|
||||
|
||||
`timescale 1 ps / 1 ps
|
||||
module pll_audio (
|
||||
input wire refclk, // refclk.clk
|
||||
input wire rst, // reset.reset
|
||||
output wire outclk_0 // outclk0.clk
|
||||
);
|
||||
|
||||
pll_audio_0002 pll_audio_inst (
|
||||
.refclk (refclk), // refclk.clk
|
||||
.rst (rst), // reset.reset
|
||||
.outclk_0 (outclk_0), // outclk0.clk
|
||||
.locked () // (terminated)
|
||||
);
|
||||
|
||||
endmodule
|
||||
// Retrieval info: <?xml version="1.0"?>
|
||||
//<!--
|
||||
// Generated by Altera MegaWizard Launcher Utility version 1.0
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
// ************************************************************
|
||||
// Copyright (C) 1991-2020 Altera Corporation
|
||||
// Any megafunction design, and related net list (encrypted or decrypted),
|
||||
// support information, device programming or simulation file, and any other
|
||||
// associated documentation or information provided by Altera or a partner
|
||||
// under Altera's Megafunction Partnership Program may be used only to
|
||||
// program PLD devices (but not masked PLD devices) from Altera. Any other
|
||||
// use of such megafunction design, net list, support information, device
|
||||
// programming or simulation file, or any other related documentation or
|
||||
// information is prohibited for any other purpose, including, but not
|
||||
// limited to modification, reverse engineering, de-compiling, or use with
|
||||
// any other silicon devices, unless such use is explicitly licensed under
|
||||
// a separate agreement with Altera or a megafunction partner. Title to
|
||||
// the intellectual property, including patents, copyrights, trademarks,
|
||||
// trade secrets, or maskworks, embodied in any such megafunction design,
|
||||
// net list, support information, device programming or simulation file, or
|
||||
// any other related documentation or information provided by Altera or a
|
||||
// megafunction partner, remains with Altera, the megafunction partner, or
|
||||
// their respective licensors. No other licenses, including any licenses
|
||||
// needed under any third party's intellectual property, are provided herein.
|
||||
//-->
|
||||
// Retrieval info: <instance entity-name="altera_pll" version="17.0" >
|
||||
// Retrieval info: <generic name="debug_print_output" value="false" />
|
||||
// Retrieval info: <generic name="debug_use_rbc_taf_method" value="false" />
|
||||
// Retrieval info: <generic name="device_family" value="Cyclone V" />
|
||||
// Retrieval info: <generic name="device" value="5CEBA2F17A7" />
|
||||
// Retrieval info: <generic name="gui_device_speed_grade" value="1" />
|
||||
// Retrieval info: <generic name="gui_pll_mode" value="Fractional-N PLL" />
|
||||
// Retrieval info: <generic name="gui_reference_clock_frequency" value="50.0" />
|
||||
// Retrieval info: <generic name="gui_channel_spacing" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_operation_mode" value="direct" />
|
||||
// Retrieval info: <generic name="gui_feedback_clock" value="Global Clock" />
|
||||
// Retrieval info: <generic name="gui_fractional_cout" value="32" />
|
||||
// Retrieval info: <generic name="gui_dsm_out_sel" value="1st_order" />
|
||||
// Retrieval info: <generic name="gui_use_locked" value="false" />
|
||||
// Retrieval info: <generic name="gui_en_adv_params" value="false" />
|
||||
// Retrieval info: <generic name="gui_number_of_clocks" value="1" />
|
||||
// Retrieval info: <generic name="gui_multiply_factor" value="1" />
|
||||
// Retrieval info: <generic name="gui_frac_multiply_factor" value="1" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_n" value="1" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter0" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency0" value="24.576" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c0" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency0" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units0" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift0" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg0" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift0" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle0" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter1" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency1" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c1" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency1" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units1" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift1" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg1" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift1" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle1" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter2" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency2" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c2" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency2" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units2" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift2" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg2" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift2" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle2" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter3" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency3" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c3" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency3" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units3" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift3" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg3" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift3" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle3" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter4" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency4" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c4" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency4" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units4" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift4" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg4" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift4" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle4" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter5" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency5" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c5" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency5" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units5" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift5" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg5" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift5" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle5" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter6" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency6" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c6" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency6" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units6" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift6" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg6" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift6" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle6" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter7" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency7" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c7" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency7" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units7" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift7" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg7" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift7" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle7" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter8" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency8" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c8" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency8" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units8" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift8" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg8" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift8" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle8" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter9" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency9" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c9" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency9" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units9" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift9" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg9" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift9" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle9" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter10" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency10" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c10" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency10" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units10" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift10" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg10" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift10" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle10" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter11" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency11" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c11" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency11" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units11" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift11" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg11" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift11" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle11" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter12" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency12" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c12" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency12" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units12" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift12" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg12" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift12" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle12" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter13" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency13" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c13" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency13" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units13" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift13" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg13" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift13" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle13" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter14" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency14" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c14" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency14" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units14" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift14" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg14" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift14" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle14" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter15" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency15" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c15" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency15" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units15" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift15" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg15" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift15" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle15" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter16" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency16" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c16" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency16" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units16" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift16" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg16" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift16" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle16" value="50" />
|
||||
// Retrieval info: <generic name="gui_cascade_counter17" value="false" />
|
||||
// Retrieval info: <generic name="gui_output_clock_frequency17" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_divide_factor_c17" value="1" />
|
||||
// Retrieval info: <generic name="gui_actual_output_clock_frequency17" value="0 MHz" />
|
||||
// Retrieval info: <generic name="gui_ps_units17" value="ps" />
|
||||
// Retrieval info: <generic name="gui_phase_shift17" value="0" />
|
||||
// Retrieval info: <generic name="gui_phase_shift_deg17" value="0.0" />
|
||||
// Retrieval info: <generic name="gui_actual_phase_shift17" value="0" />
|
||||
// Retrieval info: <generic name="gui_duty_cycle17" value="50" />
|
||||
// Retrieval info: <generic name="gui_pll_auto_reset" value="On" />
|
||||
// Retrieval info: <generic name="gui_pll_bandwidth_preset" value="Auto" />
|
||||
// Retrieval info: <generic name="gui_en_reconf" value="false" />
|
||||
// Retrieval info: <generic name="gui_en_dps_ports" value="false" />
|
||||
// Retrieval info: <generic name="gui_en_phout_ports" value="false" />
|
||||
// Retrieval info: <generic name="gui_phout_division" value="1" />
|
||||
// Retrieval info: <generic name="gui_mif_generate" value="false" />
|
||||
// Retrieval info: <generic name="gui_enable_mif_dps" value="false" />
|
||||
// Retrieval info: <generic name="gui_dps_cntr" value="C0" />
|
||||
// Retrieval info: <generic name="gui_dps_num" value="1" />
|
||||
// Retrieval info: <generic name="gui_dps_dir" value="Positive" />
|
||||
// Retrieval info: <generic name="gui_refclk_switch" value="false" />
|
||||
// Retrieval info: <generic name="gui_refclk1_frequency" value="100.0" />
|
||||
// Retrieval info: <generic name="gui_switchover_mode" value="Automatic Switchover" />
|
||||
// Retrieval info: <generic name="gui_switchover_delay" value="0" />
|
||||
// Retrieval info: <generic name="gui_active_clk" value="false" />
|
||||
// Retrieval info: <generic name="gui_clk_bad" value="false" />
|
||||
// Retrieval info: <generic name="gui_enable_cascade_out" value="false" />
|
||||
// Retrieval info: <generic name="gui_cascade_outclk_index" value="0" />
|
||||
// Retrieval info: <generic name="gui_enable_cascade_in" value="false" />
|
||||
// Retrieval info: <generic name="gui_pll_cascading_mode" value="Create an adjpllin signal to connect with an upstream PLL" />
|
||||
// Retrieval info: </instance>
|
||||
// IPFS_FILES : pll_audio.vo
|
||||
// RELATED_FILES: pll_audio.v, pll_audio_0002.v
|
||||
4
sys/pll_audio/pll_audio_0002.qip
Normal file
4
sys/pll_audio/pll_audio_0002.qip
Normal file
@@ -0,0 +1,4 @@
|
||||
set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*"
|
||||
set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*"
|
||||
87
sys/pll_audio/pll_audio_0002.v
Normal file
87
sys/pll_audio/pll_audio_0002.v
Normal file
@@ -0,0 +1,87 @@
|
||||
`timescale 1ns/10ps
|
||||
module pll_audio_0002(
|
||||
|
||||
// interface 'refclk'
|
||||
input wire refclk,
|
||||
|
||||
// interface 'reset'
|
||||
input wire rst,
|
||||
|
||||
// interface 'outclk0'
|
||||
output wire outclk_0,
|
||||
|
||||
// interface 'locked'
|
||||
output wire locked
|
||||
);
|
||||
|
||||
altera_pll #(
|
||||
.fractional_vco_multiplier("true"),
|
||||
.reference_clock_frequency("50.0 MHz"),
|
||||
.operation_mode("direct"),
|
||||
.number_of_clocks(1),
|
||||
.output_clock_frequency0("24.576000 MHz"),
|
||||
.phase_shift0("0 ps"),
|
||||
.duty_cycle0(50),
|
||||
.output_clock_frequency1("0 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_0}),
|
||||
.locked (locked),
|
||||
.fboutclk ( ),
|
||||
.fbclk (1'b0),
|
||||
.refclk (refclk)
|
||||
);
|
||||
endmodule
|
||||
|
||||
44
sys/pll_cfg.qip
Normal file
44
sys/pll_cfg.qip
Normal file
@@ -0,0 +1,44 @@
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_NAME "altera_pll_reconfig"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_VERSION "17.0"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_ENV "mwpim"
|
||||
set_global_assignment -library "pll_cfg" -name MISC_FILE [file join $::quartus(qip_path) "pll_cfg.cmp"]
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_QSYS_MODE "UNKNOWN"
|
||||
set_global_assignment -name SYNTHESIS_ONLY_QIP ON
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_NAME "cGxsX2hkbWlfY2Zn"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw=="
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_INTERNAL "Off"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_VERSION "MTcuMA=="
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ=="
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA=="
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA=="
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA=="
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA=="
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo"
|
||||
set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_NAME "YWx0ZXJhX3BsbF9yZWNvbmZpZ190b3A="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_INTERNAL "Off"
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u"
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_VERSION "MTcuMA=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "ZGV2aWNlX2ZhbWlseQ==::Q3ljbG9uZSBW::ZGV2aWNlX2ZhbWlseQ=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX01JRg==::ZmFsc2U=::RW5hYmxlIE1JRiBTdHJlYW1pbmc="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA=="
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo"
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw=="
|
||||
|
||||
set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg.v"]
|
||||
set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_top.v"]
|
||||
set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_core.v"]
|
||||
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_NAME "altera_pll_reconfig"
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_VERSION "17.0"
|
||||
set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_ENV "mwpim"
|
||||
86
sys/pll_cfg.v
Normal file
86
sys/pll_cfg.v
Normal file
@@ -0,0 +1,86 @@
|
||||
// megafunction wizard: %Altera PLL Reconfig v17.0%
|
||||
// GENERATION: XML
|
||||
// pll_cfg.v
|
||||
|
||||
// Generated using ACDS version 17.0 598
|
||||
|
||||
`timescale 1 ps / 1 ps
|
||||
module pll_cfg #(
|
||||
parameter ENABLE_BYTEENABLE = 0,
|
||||
parameter BYTEENABLE_WIDTH = 4,
|
||||
parameter RECONFIG_ADDR_WIDTH = 6,
|
||||
parameter RECONFIG_DATA_WIDTH = 32,
|
||||
parameter reconf_width = 64,
|
||||
parameter WAIT_FOR_LOCK = 1
|
||||
) (
|
||||
input wire mgmt_clk, // mgmt_clk.clk
|
||||
input wire mgmt_reset, // mgmt_reset.reset
|
||||
output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest
|
||||
input wire mgmt_read, // .read
|
||||
input wire mgmt_write, // .write
|
||||
output wire [31:0] mgmt_readdata, // .readdata
|
||||
input wire [5:0] mgmt_address, // .address
|
||||
input wire [31:0] mgmt_writedata, // .writedata
|
||||
output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll
|
||||
input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll
|
||||
);
|
||||
|
||||
altera_pll_reconfig_top #(
|
||||
.device_family ("Cyclone V"),
|
||||
.ENABLE_MIF (0),
|
||||
.MIF_FILE_NAME ("sys/pll_cfg.mif"),
|
||||
.ENABLE_BYTEENABLE (ENABLE_BYTEENABLE),
|
||||
.BYTEENABLE_WIDTH (BYTEENABLE_WIDTH),
|
||||
.RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH),
|
||||
.RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH),
|
||||
.reconf_width (reconf_width),
|
||||
.WAIT_FOR_LOCK (WAIT_FOR_LOCK)
|
||||
) pll_cfg_inst (
|
||||
.mgmt_clk (mgmt_clk), // mgmt_clk.clk
|
||||
.mgmt_reset (mgmt_reset), // mgmt_reset.reset
|
||||
.mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest
|
||||
.mgmt_read (mgmt_read), // .read
|
||||
.mgmt_write (mgmt_write), // .write
|
||||
.mgmt_readdata (mgmt_readdata), // .readdata
|
||||
.mgmt_address (mgmt_address), // .address
|
||||
.mgmt_writedata (mgmt_writedata), // .writedata
|
||||
.reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll
|
||||
.reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll
|
||||
.mgmt_byteenable (4'b0000) // (terminated)
|
||||
);
|
||||
|
||||
endmodule
|
||||
// Retrieval info: <?xml version="1.0"?>
|
||||
//<!--
|
||||
// Generated by Altera MegaWizard Launcher Utility version 1.0
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
// ************************************************************
|
||||
// Copyright (C) 1991-2018 Altera Corporation
|
||||
// Any megafunction design, and related net list (encrypted or decrypted),
|
||||
// support information, device programming or simulation file, and any other
|
||||
// associated documentation or information provided by Altera or a partner
|
||||
// under Altera's Megafunction Partnership Program may be used only to
|
||||
// program PLD devices (but not masked PLD devices) from Altera. Any other
|
||||
// use of such megafunction design, net list, support information, device
|
||||
// programming or simulation file, or any other related documentation or
|
||||
// information is prohibited for any other purpose, including, but not
|
||||
// limited to modification, reverse engineering, de-compiling, or use with
|
||||
// any other silicon devices, unless such use is explicitly licensed under
|
||||
// a separate agreement with Altera or a megafunction partner. Title to
|
||||
// the intellectual property, including patents, copyrights, trademarks,
|
||||
// trade secrets, or maskworks, embodied in any such megafunction design,
|
||||
// net list, support information, device programming or simulation file, or
|
||||
// any other related documentation or information provided by Altera or a
|
||||
// megafunction partner, remains with Altera, the megafunction partner, or
|
||||
// their respective licensors. No other licenses, including any licenses
|
||||
// needed under any third party's intellectual property, are provided herein.
|
||||
//-->
|
||||
// Retrieval info: <instance entity-name="altera_pll_reconfig" version="17.0" >
|
||||
// Retrieval info: <generic name="device_family" value="Cyclone V" />
|
||||
// Retrieval info: <generic name="ENABLE_MIF" value="false" />
|
||||
// Retrieval info: <generic name="MIF_FILE_NAME" value="sys/pll_cfg.mif" />
|
||||
// Retrieval info: <generic name="ENABLE_BYTEENABLE" value="false" />
|
||||
// Retrieval info: </instance>
|
||||
// IPFS_FILES : pll_cfg.vo
|
||||
// RELATED_FILES: pll_cfg.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user