Compare commits
1 Commits
feature/fp
...
master
Author | SHA1 | Date | |
---|---|---|---|
263f9c566a |
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -1,6 +0,0 @@
|
||||||
[submodule "fpga/hdl/serv"]
|
|
||||||
path = fpga/hdl/serv
|
|
||||||
url = https://github.com/olofk/serv.git
|
|
||||||
[submodule "fpga/hdl/trashernet"]
|
|
||||||
path = fpga/hdl/trashernet
|
|
||||||
url = https://git.notsyncing.net/fpga/trashernet.git
|
|
|
@ -1,373 +0,0 @@
|
||||||
Mozilla Public License Version 2.0
|
|
||||||
==================================
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
--------------
|
|
||||||
|
|
||||||
1.1. "Contributor"
|
|
||||||
means each individual or legal entity that creates, contributes to
|
|
||||||
the creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. "Contributor Version"
|
|
||||||
means the combination of the Contributions of others (if any) used
|
|
||||||
by a Contributor and that particular Contributor's Contribution.
|
|
||||||
|
|
||||||
1.3. "Contribution"
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. "Covered Software"
|
|
||||||
means Source Code Form to which the initial Contributor has attached
|
|
||||||
the notice in Exhibit A, the Executable Form of such Source Code
|
|
||||||
Form, and Modifications of such Source Code Form, in each case
|
|
||||||
including portions thereof.
|
|
||||||
|
|
||||||
1.5. "Incompatible With Secondary Licenses"
|
|
||||||
means
|
|
||||||
|
|
||||||
(a) that the initial Contributor has attached the notice described
|
|
||||||
in Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
(b) that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the
|
|
||||||
terms of a Secondary License.
|
|
||||||
|
|
||||||
1.6. "Executable Form"
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. "Larger Work"
|
|
||||||
means a work that combines Covered Software with other material, in
|
|
||||||
a separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. "License"
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. "Licensable"
|
|
||||||
means having the right to grant, to the maximum extent possible,
|
|
||||||
whether at the time of the initial grant or subsequently, any and
|
|
||||||
all of the rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. "Modifications"
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
(a) any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered
|
|
||||||
Software; or
|
|
||||||
|
|
||||||
(b) any new file in Source Code Form that contains any Covered
|
|
||||||
Software.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" of a Contributor
|
|
||||||
means any patent claim(s), including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by such
|
|
||||||
Contributor that would be infringed, but for the grant of the
|
|
||||||
License, by the making, using, selling, offering for sale, having
|
|
||||||
made, import, or transfer of either its Contributions or its
|
|
||||||
Contributor Version.
|
|
||||||
|
|
||||||
1.12. "Secondary License"
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU
|
|
||||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
|
||||||
Public License, Version 3.0, or any later versions of those
|
|
||||||
licenses.
|
|
||||||
|
|
||||||
1.13. "Source Code Form"
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. "You" (or "Your")
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, "You" includes any entity that
|
|
||||||
controls, is controlled by, or is under common control with You. For
|
|
||||||
purposes of this definition, "control" means (a) the power, direct
|
|
||||||
or indirect, to cause the direction or management of such entity,
|
|
||||||
whether by contract or otherwise, or (b) ownership of more than
|
|
||||||
fifty percent (50%) of the outstanding shares or beneficial
|
|
||||||
ownership of such entity.
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
(a) under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or
|
|
||||||
as part of a Larger Work; and
|
|
||||||
|
|
||||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
|
||||||
for sale, have made, import, and otherwise transfer either its
|
|
||||||
Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor first
|
|
||||||
distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under
|
|
||||||
this License. No additional rights or licenses will be implied from the
|
|
||||||
distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
|
||||||
Contributor:
|
|
||||||
|
|
||||||
(a) for any code that a Contributor has removed from Covered Software;
|
|
||||||
or
|
|
||||||
|
|
||||||
(b) for infringements caused by: (i) Your and any other third party's
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
|
||||||
its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
|
||||||
permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights
|
|
||||||
to grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing, or other
|
|
||||||
equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
|
||||||
in Section 2.1.
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under
|
|
||||||
the terms of this License. You must inform recipients that the Source
|
|
||||||
Code Form of the Covered Software is governed by the terms of this
|
|
||||||
License, and how they can obtain a copy of this License. You may not
|
|
||||||
attempt to alter or restrict the recipients' rights in the Source Code
|
|
||||||
Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
(a) such Covered Software must also be made available in Source Code
|
|
||||||
Form, as described in Section 3.1, and You must inform recipients of
|
|
||||||
the Executable Form how they can obtain a copy of such Source Code
|
|
||||||
Form by reasonable means in a timely manner, at a charge no more
|
|
||||||
than the cost of distribution to the recipient; and
|
|
||||||
|
|
||||||
(b) You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter
|
|
||||||
the recipients' rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of Covered
|
|
||||||
Software with a work governed by one or more Secondary Licenses, and the
|
|
||||||
Covered Software is not Incompatible With Secondary Licenses, this
|
|
||||||
License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the Covered
|
|
||||||
Software under the terms of either this License or such Secondary
|
|
||||||
License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty,
|
|
||||||
or limitations of liability) contained within the Source Code Form of
|
|
||||||
the Covered Software, except that You may alter any license notices to
|
|
||||||
the extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on
|
|
||||||
behalf of any Contributor. You must make it absolutely clear that any
|
|
||||||
such warranty, support, indemnity, or liability obligation is offered by
|
|
||||||
You alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this
|
|
||||||
License with respect to some or all of the Covered Software due to
|
|
||||||
statute, judicial order, or regulation then You must: (a) comply with
|
|
||||||
the terms of this License to the maximum extent possible; and (b)
|
|
||||||
describe the limitations and the code they affect. Such description must
|
|
||||||
be placed in a text file included with all distributions of the Covered
|
|
||||||
Software under this License. Except to the extent prohibited by statute
|
|
||||||
or regulation, such description must be sufficiently detailed for a
|
|
||||||
recipient of ordinary skill to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
--------------
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically
|
|
||||||
if You fail to comply with any of its terms. However, if You become
|
|
||||||
compliant, then the rights granted under this License from a particular
|
|
||||||
Contributor are reinstated (a) provisionally, unless and until such
|
|
||||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
|
||||||
ongoing basis, if such Contributor fails to notify You of the
|
|
||||||
non-compliance by some reasonable means prior to 60 days after You have
|
|
||||||
come back into compliance. Moreover, Your grants from a particular
|
|
||||||
Contributor are reinstated on an ongoing basis if such Contributor
|
|
||||||
notifies You of the non-compliance by some reasonable means, this is the
|
|
||||||
first time You have received notice of non-compliance with this License
|
|
||||||
from such Contributor, and You become compliant prior to 30 days after
|
|
||||||
Your receipt of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted to
|
|
||||||
You by any and all Contributors for the Covered Software under Section
|
|
||||||
2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
|
||||||
end user license agreements (excluding distributors and resellers) which
|
|
||||||
have been validly granted by You or Your distributors under this License
|
|
||||||
prior to termination shall survive termination.
|
|
||||||
|
|
||||||
************************************************************************
|
|
||||||
* *
|
|
||||||
* 6. Disclaimer of Warranty *
|
|
||||||
* ------------------------- *
|
|
||||||
* *
|
|
||||||
* Covered Software is provided under this License on an "as is" *
|
|
||||||
* basis, without warranty of any kind, either expressed, implied, or *
|
|
||||||
* statutory, including, without limitation, warranties that the *
|
|
||||||
* Covered Software is free of defects, merchantable, fit for a *
|
|
||||||
* particular purpose or non-infringing. The entire risk as to the *
|
|
||||||
* quality and performance of the Covered Software is with You. *
|
|
||||||
* Should any Covered Software prove defective in any respect, You *
|
|
||||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
|
||||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
|
||||||
* essential part of this License. No use of any Covered Software is *
|
|
||||||
* authorized under this License except under this disclaimer. *
|
|
||||||
* *
|
|
||||||
************************************************************************
|
|
||||||
|
|
||||||
************************************************************************
|
|
||||||
* *
|
|
||||||
* 7. Limitation of Liability *
|
|
||||||
* -------------------------- *
|
|
||||||
* *
|
|
||||||
* Under no circumstances and under no legal theory, whether tort *
|
|
||||||
* (including negligence), contract, or otherwise, shall any *
|
|
||||||
* Contributor, or anyone who distributes Covered Software as *
|
|
||||||
* permitted above, be liable to You for any direct, indirect, *
|
|
||||||
* special, incidental, or consequential damages of any character *
|
|
||||||
* including, without limitation, damages for lost profits, loss of *
|
|
||||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
|
||||||
* and all other commercial damages or losses, even if such party *
|
|
||||||
* shall have been informed of the possibility of such damages. This *
|
|
||||||
* limitation of liability shall not apply to liability for death or *
|
|
||||||
* personal injury resulting from such party's negligence to the *
|
|
||||||
* extent applicable law prohibits such limitation. Some *
|
|
||||||
* jurisdictions do not allow the exclusion or limitation of *
|
|
||||||
* incidental or consequential damages, so this exclusion and *
|
|
||||||
* limitation may not apply to You. *
|
|
||||||
* *
|
|
||||||
************************************************************************
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the
|
|
||||||
courts of a jurisdiction where the defendant maintains its principal
|
|
||||||
place of business and such litigation shall be governed by laws of that
|
|
||||||
jurisdiction, without reference to its conflict-of-law provisions.
|
|
||||||
Nothing in this Section shall prevent a party's ability to bring
|
|
||||||
cross-claims or counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
----------------
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. Any law or regulation which provides
|
|
||||||
that the language of a contract shall be construed against the drafter
|
|
||||||
shall not be used to construe this License against a Contributor.
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a
|
|
||||||
modified version of this License if you rename the license and remove
|
|
||||||
any references to the name of the license steward (except to note that
|
|
||||||
such modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
|
||||||
Licenses
|
|
||||||
|
|
||||||
If You choose to distribute Source Code Form that is Incompatible With
|
|
||||||
Secondary Licenses under the terms of this version of the License, the
|
|
||||||
notice described in Exhibit B of this License must be attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular
|
|
||||||
file, then You may include the notice in a location (such as a LICENSE
|
|
||||||
file in a relevant directory) where a recipient would be likely to look
|
|
||||||
for such a notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
|
||||||
defined by the Mozilla Public License, v. 2.0.
|
|
|
@ -12,14 +12,7 @@ You can find a copy of the full license in [LICENSE-CC-BY-SA-4.0.TXT](./LICENSE-
|
||||||
|
|
||||||
### FPGA
|
### FPGA
|
||||||
|
|
||||||
The FPGA Source Code Form in `/fpga` is subject to the terms of the Mozilla Public License, v. 2.0.
|
TBD.
|
||||||
|
|
||||||
You can find a copy of the full license in [LICENSE-MPL-2.0.txt](./LICENSE-MPL-2.0.txt).
|
|
||||||
|
|
||||||
Note that this design incorporates code from third-party projects, which may come with further restrictions. For details, refer to the individual projects's licensing terms:
|
|
||||||
|
|
||||||
* [SERV](https://github.com/olofk/serv/blob/main/LICENSE): ISC License
|
|
||||||
* [Trashernet](https://git.notsyncing.net/fpga/trashernet/src/branch/master/README.MD#license): Mozilla Public License, v. 2.0.
|
|
||||||
|
|
||||||
### SW
|
### SW
|
||||||
|
|
||||||
|
|
4
fpga/.gitignore
vendored
4
fpga/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
||||||
build/**
|
|
||||||
*.bak
|
|
||||||
wave.fst
|
|
||||||
vunit_out
|
|
|
@ -1,79 +0,0 @@
|
||||||
# -------------------------------------------------------------------------- --
|
|
||||||
# TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
# -------------------------------------------------------------------------- --
|
|
||||||
# TODO
|
|
||||||
# -------------------------------------------------------------------------- --
|
|
||||||
# Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
# Contributors : None
|
|
||||||
# License : Mozilla Public License (MPL) Version 2
|
|
||||||
# -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
BUILD_DIR=./build
|
|
||||||
VU_DIR=$(BUILD_DIR)/vunit_out
|
|
||||||
VU_FLAG=$(VU_DIR)/flag
|
|
||||||
|
|
||||||
# Collect VHDL sources using VUnit
|
|
||||||
SOURCES_VHDL=$(shell VUNIT_SIMULATOR=ghdl ./run_physical.py -o $(VU_DIR) -f 2>/dev/null | sed -n 's/^\w\+, \(.\+\)$$/\1/p')
|
|
||||||
|
|
||||||
# Collect Verilog sources using bash
|
|
||||||
SERV_DIR=hdl/serv
|
|
||||||
SOURCES_VERILOG=$(SERV_DIR)/rtl/*.v
|
|
||||||
SOURCES_VERILOG+=$(SERV_DIR)/servant/servant_ram.v $(SERV_DIR)/servant/servant_timer.v
|
|
||||||
|
|
||||||
# Miscellaneous sources that when changed must trigger a rebuild
|
|
||||||
SOURCES_MISC=../sw/bootrom/bootrom.vhex
|
|
||||||
|
|
||||||
# Constraints
|
|
||||||
CONSTRAINTS=constraints.pcf
|
|
||||||
|
|
||||||
# HW Settings
|
|
||||||
YOSYS_DEVICE=u
|
|
||||||
DEVICE?=up5k # up5k, u4k
|
|
||||||
PACKAGE?=sg48
|
|
||||||
|
|
||||||
# Programmer Settings
|
|
||||||
PROGRAMMER=ft2232
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------- #
|
|
||||||
|
|
||||||
default: $(BUILD_DIR)/bitstream.bin
|
|
||||||
|
|
||||||
$(VU_FLAG): $(SOURCES_VHDL) $(SOURCES_MISC)
|
|
||||||
VUNIT_SIMULATOR=ghdl ./run_physical.py --compile -o $(VU_DIR)
|
|
||||||
touch $@
|
|
||||||
|
|
||||||
$(BUILD_DIR)/netlist-post-synthesis.json: $(VU_FLAG) $(SOURCES_VERILOG)
|
|
||||||
# Collect GHDL sources from VUnit
|
|
||||||
$(eval GHDLINCDIRS=$(shell find "$(VU_DIR)/ghdl/libraries" -maxdepth 1 -mindepth 1 -type d | sed "s/^/-P/" | tr '\n' ' '))
|
|
||||||
yosys -m ghdl -p "read_verilog $(SOURCES_VERILOG); ghdl --std=08 $(GHDLINCDIRS) design.top; synth_ice40 -abc9 -device $(YOSYS_DEVICE) -top top -json $@"
|
|
||||||
|
|
||||||
$(BUILD_DIR)/netlist-post-pnr.asc: $(BUILD_DIR)/netlist-post-synthesis.json $(CONSTRAINTS)
|
|
||||||
nextpnr-ice40 --$(DEVICE) --package $(PACKAGE) --asc $(BUILD_DIR)/netlist-post-pnr.asc --report $(BUILD_DIR)/report.json --detailed-timing-report --json $(BUILD_DIR)/netlist-post-synthesis.json --pcf $(CONSTRAINTS)
|
|
||||||
|
|
||||||
$(BUILD_DIR)/timing.rpt: $(BUILD_DIR)/netlist-post-pnr.asc $(CONSTRAINTS)
|
|
||||||
icetime -d $(DEVICE) -P $(PACKAGE) -p $(CONSTRAINTS) -mtr $@ $(BUILD_DIR)/netlist-post-pnr.asc
|
|
||||||
|
|
||||||
$(BUILD_DIR)/bitstream.bin: $(BUILD_DIR)/netlist-post-pnr.asc
|
|
||||||
icepack $< $@
|
|
||||||
|
|
||||||
flash: $(BUILD_DIR)/bitstream.bin
|
|
||||||
openFPGALoader --unprotect-flash -f -c $(PROGRAMMER) -b ice40_generic $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
# Build artifacts
|
|
||||||
rm -rf $(BUILD_DIR)
|
|
||||||
# Simulation artifacts
|
|
||||||
rm -rf vunit_out
|
|
||||||
rm -rf wave.fst*
|
|
||||||
|
|
||||||
simulation:
|
|
||||||
./run.py
|
|
||||||
|
|
||||||
.phony: flash clean simulation
|
|
||||||
|
|
||||||
# Useful aliases
|
|
||||||
compile_vhdl: $(VU_FLAG)
|
|
||||||
synth: $(BUILD_DIR)/netlist-post-synthesis.json
|
|
||||||
pnr: $(BUILD_DIR)/netlist-post-pnr.asc
|
|
||||||
pack: $(BUILD_DIR)/bitstream.bin
|
|
||||||
timing: $(BUILD_DIR)/timing.rpt
|
|
|
@ -1,47 +0,0 @@
|
||||||
set_io psram_ce_n 13
|
|
||||||
set_io psram_sclk 9
|
|
||||||
set_io psram_sio[0] 6
|
|
||||||
set_io psram_sio[1] 11
|
|
||||||
set_io psram_sio[2] 12
|
|
||||||
set_io psram_sio[3] 10
|
|
||||||
|
|
||||||
set_io flash_ce_n 16
|
|
||||||
set_io flash_sclk 15
|
|
||||||
set_io flash_sio[0] 14
|
|
||||||
set_io flash_sio[1] 17
|
|
||||||
set_io flash_sio[2] 18
|
|
||||||
set_io flash_sio[3] 19
|
|
||||||
|
|
||||||
set_io pmod[0] 20
|
|
||||||
set_io pmod[1] 21
|
|
||||||
set_io pmod[2] 23
|
|
||||||
set_io pmod[3] 25
|
|
||||||
set_io pmod[4] 26
|
|
||||||
set_io pmod[5] 27
|
|
||||||
set_io pmod[6] 28
|
|
||||||
set_io pmod[7] 31
|
|
||||||
|
|
||||||
set_io uart_rx 37
|
|
||||||
set_io uart_tx 36
|
|
||||||
set_io clk_in 35
|
|
||||||
|
|
||||||
#set_io eth_rx_n 38
|
|
||||||
set_io eth_rx_p 42
|
|
||||||
|
|
||||||
set_io eth_tx_n[0] 46
|
|
||||||
set_io eth_tx_n[1] 47
|
|
||||||
set_io eth_tx_n[2] 44
|
|
||||||
set_io eth_tx_n[3] 45
|
|
||||||
|
|
||||||
set_io eth_tx_p[0] 48
|
|
||||||
set_io eth_tx_p[1] 2
|
|
||||||
set_io eth_tx_p[2] 4
|
|
||||||
set_io eth_tx_p[3] 3
|
|
||||||
|
|
||||||
set_io eth_led_green_n 40
|
|
||||||
set_io eth_led_orange_n 41
|
|
||||||
|
|
||||||
set_io led_user 34
|
|
||||||
|
|
||||||
set_frequency clk 25
|
|
||||||
set_frequency clk_phy 50
|
|
|
@ -1,117 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library device_models;
|
|
||||||
library design;
|
|
||||||
|
|
||||||
entity bench_aps6404l_controller is
|
|
||||||
end entity bench_aps6404l_controller;
|
|
||||||
|
|
||||||
architecture bench of bench_aps6404l_controller is
|
|
||||||
signal rst : std_logic;
|
|
||||||
signal clk : std_logic;
|
|
||||||
signal psram_ce_n : std_logic;
|
|
||||||
signal psram_sclk : std_logic;
|
|
||||||
signal psram_sio : std_logic_vector(3 downto 0);
|
|
||||||
signal addr : std_logic_vector(23 downto 0);
|
|
||||||
signal data_in : std_logic_vector(7 downto 0);
|
|
||||||
signal data_in_next : std_logic;
|
|
||||||
signal write_en : std_logic;
|
|
||||||
signal read_en : std_logic;
|
|
||||||
signal data_out : std_logic_vector(7 downto 0);
|
|
||||||
signal data_out_valid : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
aps6404l_controller_inst : entity design.aps6404l_controller
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
addr => addr,
|
|
||||||
data_in => data_in,
|
|
||||||
data_in_next => data_in_next,
|
|
||||||
data_out => data_out,
|
|
||||||
data_out_valid => data_out_valid,
|
|
||||||
write_en => write_en,
|
|
||||||
read_en => read_en,
|
|
||||||
psram_ce_n => psram_ce_n,
|
|
||||||
psram_sclk => psram_sclk,
|
|
||||||
psram_sio => psram_sio
|
|
||||||
);
|
|
||||||
|
|
||||||
aps6404l_inst : entity device_models.aps6404l
|
|
||||||
port map(
|
|
||||||
ce_n => psram_ce_n,
|
|
||||||
sclk => psram_sclk,
|
|
||||||
sio => psram_sio
|
|
||||||
);
|
|
||||||
|
|
||||||
clock_driver : process
|
|
||||||
constant period : time := 20 ns;
|
|
||||||
begin
|
|
||||||
clk <= '0';
|
|
||||||
wait for period / 2;
|
|
||||||
clk <= '1';
|
|
||||||
wait for period / 2;
|
|
||||||
end process clock_driver;
|
|
||||||
|
|
||||||
test : process is
|
|
||||||
begin
|
|
||||||
rst <= '1';
|
|
||||||
data_in <= (others => '0');
|
|
||||||
read_en <= '0';
|
|
||||||
write_en <= '0';
|
|
||||||
|
|
||||||
wait for 1 ns;
|
|
||||||
rst <= '0';
|
|
||||||
|
|
||||||
wait for 3 us;
|
|
||||||
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
addr <= x"ABCDEF";
|
|
||||||
read_en <= '1';
|
|
||||||
|
|
||||||
wait for 2 us;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
read_en <= '0';
|
|
||||||
|
|
||||||
wait for 1 us;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
addr <= x"ABCDEF";
|
|
||||||
write_en <= '1';
|
|
||||||
|
|
||||||
for i in 10 to 15 loop
|
|
||||||
data_in <= std_logic_vector(to_unsigned(160 + i, 8));
|
|
||||||
loop
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
exit when data_in_next = '1';
|
|
||||||
end loop;
|
|
||||||
end loop;
|
|
||||||
write_en <= '0';
|
|
||||||
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
write_en <= '1';
|
|
||||||
|
|
||||||
for i in 10 to 15 loop
|
|
||||||
data_in <= std_logic_vector(to_unsigned(160 + i, 8));
|
|
||||||
loop
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
exit when data_in_next = '1';
|
|
||||||
end loop;
|
|
||||||
end loop;
|
|
||||||
write_en <= '0';
|
|
||||||
|
|
||||||
wait;
|
|
||||||
end process test;
|
|
||||||
|
|
||||||
end architecture bench;
|
|
|
@ -1,177 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- VUnit test bench for the aps6404l Wishbone IF
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library design;
|
|
||||||
use design.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
|
|
||||||
library device_models;
|
|
||||||
use device_models.all;
|
|
||||||
|
|
||||||
library vunit_lib;
|
|
||||||
context vunit_lib.vunit_context;
|
|
||||||
|
|
||||||
entity bench_aps6404l_wb is
|
|
||||||
generic(
|
|
||||||
runner_cfg : string := runner_cfg_default
|
|
||||||
);
|
|
||||||
end entity bench_aps6404l_wb;
|
|
||||||
|
|
||||||
architecture RTL of bench_aps6404l_wb is
|
|
||||||
signal wbi_o : wishbone_slave_out;
|
|
||||||
signal wbi_i : wishbone_slave_in;
|
|
||||||
signal wb_o : wishbone_slave_out;
|
|
||||||
signal wb_i : wishbone_slave_in;
|
|
||||||
|
|
||||||
signal clk : std_logic;
|
|
||||||
signal rst : std_logic;
|
|
||||||
|
|
||||||
signal psram_ce_n : std_logic;
|
|
||||||
signal psram_sclk : std_logic;
|
|
||||||
signal psram_sio : std_logic_vector(3 downto 0);
|
|
||||||
begin
|
|
||||||
aps6404l_wb_inst : entity design.aps6404l_wb
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
wbi_o => wbi_o,
|
|
||||||
wbi_i => wbi_i,
|
|
||||||
wb_o => wb_o,
|
|
||||||
wb_i => wb_i,
|
|
||||||
psram_ce_n => psram_ce_n,
|
|
||||||
psram_sclk => psram_sclk,
|
|
||||||
psram_sio => psram_sio
|
|
||||||
);
|
|
||||||
|
|
||||||
aps6404l_inst : entity device_models.aps6404l
|
|
||||||
port map(
|
|
||||||
ce_n => psram_ce_n,
|
|
||||||
sclk => psram_sclk,
|
|
||||||
sio => psram_sio
|
|
||||||
);
|
|
||||||
|
|
||||||
test : process is
|
|
||||||
procedure bus_write(
|
|
||||||
signal master_o : out wishbone_master_out;
|
|
||||||
signal master_i : in wishbone_master_in;
|
|
||||||
constant address : in wishbone_address;
|
|
||||||
constant data : in wishbone_data
|
|
||||||
) is
|
|
||||||
begin
|
|
||||||
info("Writing to address 0x" & to_hstring(address));
|
|
||||||
master_o.we <= '1';
|
|
||||||
master_o.adr <= address;
|
|
||||||
master_o.dat <= data;
|
|
||||||
master_o.sel <= (others => '1');
|
|
||||||
master_o.cyc <= '1';
|
|
||||||
master_o.stb <= '1';
|
|
||||||
loop
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
exit when master_i.ack = '1';
|
|
||||||
end loop;
|
|
||||||
master_o.cyc <= '0';
|
|
||||||
master_o.stb <= '0';
|
|
||||||
end procedure bus_write;
|
|
||||||
|
|
||||||
procedure bus_read(
|
|
||||||
signal master_o : out wishbone_master_out;
|
|
||||||
signal master_i : in wishbone_master_in;
|
|
||||||
constant address : in wishbone_address;
|
|
||||||
variable data : out wishbone_data
|
|
||||||
) is
|
|
||||||
begin
|
|
||||||
info("Reading from address 0x" & to_hstring(address));
|
|
||||||
master_o.we <= '0';
|
|
||||||
master_o.adr <= address;
|
|
||||||
master_o.sel <= (others => '1');
|
|
||||||
master_o.cyc <= '1';
|
|
||||||
master_o.stb <= '1';
|
|
||||||
loop
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
exit when master_i.ack = '1';
|
|
||||||
end loop;
|
|
||||||
data := master_i.dat;
|
|
||||||
master_o.cyc <= '0';
|
|
||||||
master_o.stb <= '0';
|
|
||||||
end procedure bus_read;
|
|
||||||
|
|
||||||
procedure readcheck(signal master_o : out wishbone_master_out;
|
|
||||||
signal master_i : in wishbone_master_in;
|
|
||||||
constant address : in wishbone_address;
|
|
||||||
constant expected : in wishbone_data) is
|
|
||||||
variable data : wishbone_data;
|
|
||||||
variable time_start : time;
|
|
||||||
begin
|
|
||||||
time_start := now;
|
|
||||||
bus_read(wbi_i, wbi_o, address, data);
|
|
||||||
info("Read data: 0x" & to_hstring(data) & " after " & time'image(now - time_start));
|
|
||||||
check(data = expected, "Data readback incorrect.");
|
|
||||||
end procedure readcheck;
|
|
||||||
|
|
||||||
variable data : wishbone_data;
|
|
||||||
begin
|
|
||||||
test_runner_setup(runner, runner_cfg);
|
|
||||||
|
|
||||||
wbi_i.sel <= (others => '1');
|
|
||||||
wbi_i.cyc <= '0';
|
|
||||||
wbi_i.stb <= '0';
|
|
||||||
wb_i.cyc <= '0';
|
|
||||||
wb_i.stb <= '0';
|
|
||||||
|
|
||||||
while test_suite loop
|
|
||||||
info("Resetting DUT");
|
|
||||||
rst <= '1';
|
|
||||||
wait for 30 ns;
|
|
||||||
rst <= '0';
|
|
||||||
|
|
||||||
if run("data") then
|
|
||||||
bus_write(wb_i, wb_o, x"00000000", x"12345678");
|
|
||||||
bus_read(wb_i, wb_o, x"00000000", data);
|
|
||||||
info("Read data: 0x" & to_hstring(data));
|
|
||||||
check(data = x"12345678", "Data readback incorrect.");
|
|
||||||
wait for 500 ns;
|
|
||||||
|
|
||||||
elsif run("instruction") then
|
|
||||||
bus_write(wb_i, wb_o, x"00000000", x"11223344");
|
|
||||||
bus_write(wb_i, wb_o, x"00000004", x"55667788");
|
|
||||||
bus_write(wb_i, wb_o, x"00000008", x"99aabbcc");
|
|
||||||
bus_write(wb_i, wb_o, x"0000000c", x"ddeeff00");
|
|
||||||
wait for 1 us;
|
|
||||||
readcheck(wbi_i, wbi_o, x"00000000", x"11223344");
|
|
||||||
wait for 1 us;
|
|
||||||
readcheck(wbi_i, wbi_o, x"00000004", x"55667788");
|
|
||||||
wait for 1 us;
|
|
||||||
readcheck(wbi_i, wbi_o, x"00000008", x"99aabbcc");
|
|
||||||
wait for 1 us;
|
|
||||||
readcheck(wbi_i, wbi_o, x"0000000c", x"ddeeff00");
|
|
||||||
wait for 1 us;
|
|
||||||
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
test_runner_cleanup(runner);
|
|
||||||
end process test;
|
|
||||||
|
|
||||||
test_runner_watchdog(runner, 1 ms);
|
|
||||||
|
|
||||||
clock_driver : process
|
|
||||||
constant period : time := 20 ns;
|
|
||||||
begin
|
|
||||||
clk <= '0';
|
|
||||||
wait for period / 2;
|
|
||||||
clk <= '1';
|
|
||||||
wait for period / 2;
|
|
||||||
end process clock_driver;
|
|
||||||
end architecture RTL;
|
|
|
@ -1,121 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.all;
|
|
||||||
|
|
||||||
entity bench_fifo_block is
|
|
||||||
end entity bench_fifo_block;
|
|
||||||
|
|
||||||
architecture RTL of bench_fifo_block is
|
|
||||||
signal clk : std_logic;
|
|
||||||
signal rst_a : std_logic;
|
|
||||||
signal clr : std_logic;
|
|
||||||
signal data_in : std_logic_vector(7 downto 0);
|
|
||||||
signal write : std_logic;
|
|
||||||
signal commit : std_logic;
|
|
||||||
signal abort : std_logic;
|
|
||||||
signal full : std_logic;
|
|
||||||
signal data_out : std_logic_vector(data_in'range);
|
|
||||||
signal data_first : std_logic;
|
|
||||||
signal empty : std_logic;
|
|
||||||
signal read : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
fifo_block_inst : entity generics.fifo_block
|
|
||||||
generic map(
|
|
||||||
SIZE => 15
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst_a => rst_a,
|
|
||||||
clr => clr,
|
|
||||||
data_in => data_in,
|
|
||||||
write => write,
|
|
||||||
commit => commit,
|
|
||||||
abort => abort,
|
|
||||||
full => full,
|
|
||||||
data_out => data_out,
|
|
||||||
data_first => data_first,
|
|
||||||
empty => empty,
|
|
||||||
read => read
|
|
||||||
);
|
|
||||||
|
|
||||||
clock_driver : process
|
|
||||||
constant period : time := 10 ns;
|
|
||||||
begin
|
|
||||||
clk <= '0';
|
|
||||||
wait for period / 2;
|
|
||||||
clk <= '1';
|
|
||||||
wait for period / 2;
|
|
||||||
end process clock_driver;
|
|
||||||
|
|
||||||
test : process is
|
|
||||||
procedure push(constant data : in std_logic_vector(7 downto 0)) is
|
|
||||||
begin
|
|
||||||
data_in <= data;
|
|
||||||
write <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
write <= '0';
|
|
||||||
end procedure push;
|
|
||||||
|
|
||||||
procedure pop(expected : std_logic_vector(7 downto 0); first : boolean) is
|
|
||||||
begin
|
|
||||||
read <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
report "Read data: " & to_hstring(data_out) & " - " & std_logic'image(data_first);
|
|
||||||
assert (data_first = '1') = first report "Data first was " & std_logic'image(data_first) & " instead of " & boolean'image(first);
|
|
||||||
assert data_out = expected report "Data is " & to_hstring(data_out) & ", should be " & to_hstring(expected) severity error;
|
|
||||||
read <= '0';
|
|
||||||
end procedure;
|
|
||||||
|
|
||||||
procedure commit_data is
|
|
||||||
begin
|
|
||||||
commit <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
commit <= '0';
|
|
||||||
end procedure commit_data;
|
|
||||||
begin
|
|
||||||
rst_a <= '1';
|
|
||||||
clr <= '0';
|
|
||||||
write <= '0';
|
|
||||||
commit <= '0';
|
|
||||||
abort <= '0';
|
|
||||||
read <= '0';
|
|
||||||
|
|
||||||
wait for 10 ns;
|
|
||||||
rst_a <= '0';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
|
|
||||||
report "Pushing 5 items into FIFO";
|
|
||||||
for i in 1 to 5 loop
|
|
||||||
push(std_logic_vector(to_unsigned(i, data_in'length)));
|
|
||||||
assert empty = '1' report "FIFO data present without commit";
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
report "Committing data";
|
|
||||||
commit_data;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
assert empty = '0' report "Commit did not validate data";
|
|
||||||
|
|
||||||
report "Reading data";
|
|
||||||
for i in 1 to 1 loop
|
|
||||||
pop(std_logic_vector(to_unsigned(i, data_in'length)), i = 1);
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
std.env.stop(0);
|
|
||||||
wait;
|
|
||||||
end process test;
|
|
||||||
|
|
||||||
end architecture RTL;
|
|
|
@ -1,221 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library design;
|
|
||||||
use design.all;
|
|
||||||
use std.textio.all;
|
|
||||||
|
|
||||||
library device_models;
|
|
||||||
|
|
||||||
entity bench_top_manual is
|
|
||||||
end entity bench_top_manual;
|
|
||||||
|
|
||||||
architecture bench of bench_top_manual is
|
|
||||||
constant UART_BAUD : real := 38400.0;
|
|
||||||
|
|
||||||
signal clk : std_logic;
|
|
||||||
signal rst_n_a : std_logic;
|
|
||||||
|
|
||||||
signal uart_txd : std_logic;
|
|
||||||
signal uart_rxd : std_logic;
|
|
||||||
|
|
||||||
signal psram_ce_n : std_logic;
|
|
||||||
signal psram_sclk : std_logic;
|
|
||||||
signal psram_sio : std_logic_vector(3 downto 0);
|
|
||||||
|
|
||||||
signal rx_p : std_logic := '0';
|
|
||||||
signal rx_n : std_logic := '1';
|
|
||||||
signal tx_p : std_logic_vector(3 downto 0);
|
|
||||||
signal tx_n : std_logic_vector(3 downto 0);
|
|
||||||
|
|
||||||
procedure print(text : string) is
|
|
||||||
variable lb : line;
|
|
||||||
begin
|
|
||||||
write(lb, text);
|
|
||||||
writeline(output, lb);
|
|
||||||
end procedure print;
|
|
||||||
|
|
||||||
procedure print(text : character) is
|
|
||||||
variable lb : line;
|
|
||||||
begin
|
|
||||||
write(lb, text);
|
|
||||||
write(output, lb.all);
|
|
||||||
flush(output);
|
|
||||||
end procedure print;
|
|
||||||
begin
|
|
||||||
clock_driver : process
|
|
||||||
constant period : time := 1 sec / 48000000;
|
|
||||||
begin
|
|
||||||
clk <= '0';
|
|
||||||
wait for period / 2;
|
|
||||||
clk <= '1';
|
|
||||||
wait for period / 2;
|
|
||||||
end process clock_driver;
|
|
||||||
|
|
||||||
reset_gen : process is
|
|
||||||
begin
|
|
||||||
rst_n_a <= '0';
|
|
||||||
wait for 40 ns;
|
|
||||||
rst_n_a <= '1';
|
|
||||||
wait;
|
|
||||||
end process reset_gen;
|
|
||||||
|
|
||||||
top_inst : entity design.top
|
|
||||||
port map(
|
|
||||||
clk_50m => clk,
|
|
||||||
uart_tx => uart_txd,
|
|
||||||
uart_rx => uart_rxd,
|
|
||||||
eth_rx_p => rx_p,
|
|
||||||
--eth_rx_n => rx_n,
|
|
||||||
eth_tx_p => tx_p,
|
|
||||||
eth_tx_n => tx_n,
|
|
||||||
psram_ce_n => psram_ce_n,
|
|
||||||
psram_sclk => psram_sclk,
|
|
||||||
psram_sio => psram_sio
|
|
||||||
);
|
|
||||||
|
|
||||||
aps6404l_inst : entity device_models.aps6404l
|
|
||||||
port map(
|
|
||||||
ce_n => psram_ce_n,
|
|
||||||
sclk => psram_sclk,
|
|
||||||
sio => psram_sio
|
|
||||||
);
|
|
||||||
|
|
||||||
uart_decoder : process is
|
|
||||||
constant DELAY : time := (1 sec / UART_BAUD);
|
|
||||||
variable d : std_logic_vector(7 downto 0);
|
|
||||||
begin
|
|
||||||
wait until falling_edge(uart_txd);
|
|
||||||
wait for 0.5 * DELAY;
|
|
||||||
for i in 0 to 7 loop
|
|
||||||
wait for DELAY;
|
|
||||||
d(i) := uart_txd;
|
|
||||||
end loop;
|
|
||||||
wait for 1.0 * DELAY;
|
|
||||||
print(character'val(to_integer(unsigned(d))));
|
|
||||||
end process uart_decoder;
|
|
||||||
|
|
||||||
loader : process is
|
|
||||||
procedure uart_tx(d : std_logic_vector(7 downto 0)) is
|
|
||||||
constant DELAY : time := (1 sec / UART_BAUD);
|
|
||||||
begin
|
|
||||||
uart_rxd <= '0';
|
|
||||||
wait for DELAY;
|
|
||||||
for i in d'low to d'high loop
|
|
||||||
uart_rxd <= d(i);
|
|
||||||
wait for DELAY;
|
|
||||||
end loop;
|
|
||||||
uart_rxd <= '1';
|
|
||||||
wait for DELAY;
|
|
||||||
end procedure uart_tx;
|
|
||||||
|
|
||||||
begin
|
|
||||||
uart_rxd <= '1';
|
|
||||||
wait for (1 sec / UART_BAUD) * 10;
|
|
||||||
|
|
||||||
report ("Writing ABCD+jalr0 to RAM...");
|
|
||||||
-- WRITE
|
|
||||||
uart_tx(x"01");
|
|
||||||
|
|
||||||
-- to RAM
|
|
||||||
uart_tx(x"40");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
|
|
||||||
-- 8 bytes
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"08");
|
|
||||||
|
|
||||||
-- with this data ("ABCD", jalr zero)
|
|
||||||
uart_tx(x"41");
|
|
||||||
uart_tx(x"42");
|
|
||||||
uart_tx(x"43");
|
|
||||||
uart_tx(x"44");
|
|
||||||
uart_tx(x"e7");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
|
|
||||||
report ("Reading back from RAM...");
|
|
||||||
-- READ
|
|
||||||
uart_tx(x"02");
|
|
||||||
|
|
||||||
-- from RAM
|
|
||||||
uart_tx(x"40");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
|
|
||||||
-- 4 bytes ("ABCD")
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"04");
|
|
||||||
|
|
||||||
print("RX Data: ");
|
|
||||||
wait for (1 sec / UART_BAUD) * 10 * 5;
|
|
||||||
print("");
|
|
||||||
|
|
||||||
report ("Jumping to RAM+4...");
|
|
||||||
-- JUMP
|
|
||||||
uart_tx(x"03");
|
|
||||||
|
|
||||||
-- to RAM (+4, jalr zero)
|
|
||||||
uart_tx(x"40");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"04");
|
|
||||||
|
|
||||||
-- The program will jump back to the loader, so we should be able to read again
|
|
||||||
wait for 100 us;
|
|
||||||
|
|
||||||
report ("Reading from RAM again...");
|
|
||||||
-- READ
|
|
||||||
uart_tx(x"02");
|
|
||||||
|
|
||||||
-- from RAM
|
|
||||||
uart_tx(x"40");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
|
|
||||||
-- 4 bytes
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"00");
|
|
||||||
uart_tx(x"04");
|
|
||||||
|
|
||||||
print("RX Data: ");
|
|
||||||
wait for (1 sec / UART_BAUD) * 10 * 5;
|
|
||||||
print("");
|
|
||||||
|
|
||||||
wait for 400 us;
|
|
||||||
|
|
||||||
report "Done.";
|
|
||||||
|
|
||||||
std.env.stop;
|
|
||||||
wait;
|
|
||||||
|
|
||||||
end process loader;
|
|
||||||
|
|
||||||
end architecture bench;
|
|
||||||
|
|
||||||
-- Commands to test on real HW
|
|
||||||
-- ---------------------------
|
|
||||||
-- Dump boot ROM : 02 00 00 00 00 00 00 00 FF
|
|
||||||
-- Write four bytes to RAM : 01 40 00 00 00 00 00 00 04 01 02 03 04
|
|
||||||
-- Dump these four bytes : 02 40 00 00 00 00 00 00 04
|
|
|
@ -1,267 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
entity aps6404l_controller is
|
|
||||||
generic(
|
|
||||||
TOGGLE_WRAP_BOUNDARY : boolean := false
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- Max clock 132 MHz -> 66 MHz SPI
|
|
||||||
rst : in std_logic; --
|
|
||||||
|
|
||||||
addr : in std_logic_vector(23 downto 0);
|
|
||||||
data_in : in std_logic_vector(7 downto 0);
|
|
||||||
data_in_next : out std_logic; -- Apply next data word at `data`
|
|
||||||
data_out : out std_logic_vector(7 downto 0);
|
|
||||||
data_out_valid : out std_logic;
|
|
||||||
write_en : in std_logic;
|
|
||||||
read_en : in std_logic; --
|
|
||||||
|
|
||||||
psram_ce_n : out std_logic;
|
|
||||||
psram_sclk : out std_logic; -- Max clock 66 MHz because of RW mode; Else max clock 90 MHz, else we might violate t_ACLK
|
|
||||||
psram_sio : inout std_logic_vector(3 downto 0) --
|
|
||||||
);
|
|
||||||
end entity aps6404l_controller;
|
|
||||||
|
|
||||||
architecture rtl of aps6404l_controller is
|
|
||||||
signal if_latch : std_logic;
|
|
||||||
signal if_write : std_logic;
|
|
||||||
signal if_output : std_logic; -- Actively drive sio
|
|
||||||
|
|
||||||
type opmode_t is (COMMAND, READ, WRITE);
|
|
||||||
signal opmode : opmode_t;
|
|
||||||
constant SR_SIZE : integer := 16;
|
|
||||||
type sr_element_vector is array (natural range <>) of std_logic_vector(psram_sio'range);
|
|
||||||
subtype sr_t is sr_element_vector(0 to SR_SIZE - 1);
|
|
||||||
subtype sr_cnt_t is integer range -SR_SIZE to SR_SIZE - 1;
|
|
||||||
signal sr : sr_t;
|
|
||||||
signal sr_preload : sr_t;
|
|
||||||
signal sr_preload_cnt : sr_cnt_t;
|
|
||||||
signal sr_load : std_logic;
|
|
||||||
signal sr_cnt : sr_cnt_t;
|
|
||||||
signal active : std_logic;
|
|
||||||
signal rd_second_nibble : std_logic;
|
|
||||||
constant RD_WAIT_CNT_MAX : integer := 3 - 1;
|
|
||||||
signal rd_wait_cnt : integer range 0 to RD_WAIT_CNT_MAX;
|
|
||||||
|
|
||||||
type state_t is (QPI_EXIT, SPI_RESET1, SPI_RESET2, SPI_ENABLE_QPI, QPI_SET_BOUNDARY, IDLE, READ, WRITE);
|
|
||||||
signal state : state_t;
|
|
||||||
signal requested : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
clkgen : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
psram_sclk <= '0';
|
|
||||||
if_latch <= '0';
|
|
||||||
if_write <= '0';
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if_latch <= '0';
|
|
||||||
if_write <= '0';
|
|
||||||
|
|
||||||
if (active) then
|
|
||||||
psram_sclk <= not psram_sclk;
|
|
||||||
|
|
||||||
if psram_sclk then -- rising edge
|
|
||||||
if_latch <= '1'; -- is the latch edge for both
|
|
||||||
else -- falling edge
|
|
||||||
if_write <= '1'; -- is a write edge for both
|
|
||||||
end if;
|
|
||||||
|
|
||||||
else
|
|
||||||
psram_sclk <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process clkgen;
|
|
||||||
|
|
||||||
sr_p : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
sr_cnt <= -1;
|
|
||||||
psram_ce_n <= '1';
|
|
||||||
if_output <= '0';
|
|
||||||
active <= '0';
|
|
||||||
rd_second_nibble <= '0';
|
|
||||||
data_out_valid <= '0';
|
|
||||||
data_in_next <= '0';
|
|
||||||
rd_wait_cnt <= RD_WAIT_CNT_MAX;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
data_out_valid <= '0';
|
|
||||||
data_in_next <= '0';
|
|
||||||
|
|
||||||
if active then
|
|
||||||
if if_write then
|
|
||||||
sr <= sr(sr'low + 1 to sr'high) & x"-";
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if sr_cnt = 0 then
|
|
||||||
if if_latch then
|
|
||||||
rd_second_nibble <= not rd_second_nibble;
|
|
||||||
data_out <= data_out(3 downto 0) & psram_sio;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
case opmode is
|
|
||||||
when COMMAND =>
|
|
||||||
if if_write then -- Transaction end only allowed on write edge
|
|
||||||
active <= '0';
|
|
||||||
if_output <= '0';
|
|
||||||
psram_ce_n <= '1';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when READ =>
|
|
||||||
if_output <= '0'; -- Configure as input
|
|
||||||
if if_latch and rd_second_nibble then
|
|
||||||
if rd_wait_cnt = 0 then
|
|
||||||
data_out_valid <= '1';
|
|
||||||
else
|
|
||||||
rd_wait_cnt <= rd_wait_cnt - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when WRITE =>
|
|
||||||
if if_write and not rd_second_nibble then
|
|
||||||
sr(sr'low to sr'low + 1) <= (data_in(7 downto 4), data_in(3 downto 0));
|
|
||||||
data_in_next <= '1';
|
|
||||||
end if;
|
|
||||||
end case;
|
|
||||||
else
|
|
||||||
if if_latch then
|
|
||||||
sr_cnt <= sr_cnt - 1;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
rd_wait_cnt <= RD_WAIT_CNT_MAX;
|
|
||||||
rd_second_nibble <= '0';
|
|
||||||
if_output <= '0';
|
|
||||||
if sr_load then
|
|
||||||
sr <= sr_preload;
|
|
||||||
sr_cnt <= sr_preload_cnt;
|
|
||||||
psram_ce_n <= '0';
|
|
||||||
if_output <= '1';
|
|
||||||
active <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process sr_p;
|
|
||||||
|
|
||||||
psram_sio <= sr(sr'low) when if_output else (others => 'Z');
|
|
||||||
|
|
||||||
fsm : process(clk, rst) is
|
|
||||||
function qpi_to_spi(constant DATA : in sr_element_vector) return sr_element_vector is
|
|
||||||
variable vec : sr_element_vector(0 to DATA'length * 4 - 1);
|
|
||||||
begin
|
|
||||||
vec := (others => (others => '-'));
|
|
||||||
for i in DATA'range loop
|
|
||||||
for j in 0 to 3 loop
|
|
||||||
vec(i * 4 + j)(0) := DATA(i)(3 - j);
|
|
||||||
end loop;
|
|
||||||
end loop;
|
|
||||||
return vec;
|
|
||||||
end function;
|
|
||||||
|
|
||||||
function addr_to_nibbles(constant ADDR : in std_logic_vector) return sr_element_vector is
|
|
||||||
variable vec : sr_element_vector(0 to ADDR'length / 4 - 1);
|
|
||||||
begin
|
|
||||||
for i in vec'range loop
|
|
||||||
vec(i) := ADDR(ADDR'length - (i * 4) - 1 downto ADDR'length - (i + 1) * 4);
|
|
||||||
end loop;
|
|
||||||
return vec;
|
|
||||||
end function addr_to_nibbles;
|
|
||||||
|
|
||||||
impure function qpi_xfer(NIBBLES : sr_element_vector; constant OPM : in opmode_t := COMMAND) return boolean is
|
|
||||||
begin
|
|
||||||
if (requested) then
|
|
||||||
if not active and not sr_load then
|
|
||||||
requested <= '0';
|
|
||||||
return true;
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
if not active then
|
|
||||||
sr_preload <= (others => x"-");
|
|
||||||
sr_preload(NIBBLES'range) <= NIBBLES;
|
|
||||||
sr_preload_cnt <= NIBBLES'length - 1;
|
|
||||||
sr_load <= '1';
|
|
||||||
opmode <= OPM;
|
|
||||||
requested <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
return false;
|
|
||||||
end function qpi_xfer;
|
|
||||||
|
|
||||||
procedure qpi_stop is
|
|
||||||
begin
|
|
||||||
opmode <= COMMAND;
|
|
||||||
end procedure qpi_stop;
|
|
||||||
|
|
||||||
impure function POST_QPI_STATE return state_t is
|
|
||||||
begin
|
|
||||||
if TOGGLE_WRAP_BOUNDARY then
|
|
||||||
return QPI_SET_BOUNDARY;
|
|
||||||
else
|
|
||||||
return IDLE;
|
|
||||||
end if;
|
|
||||||
end function POST_QPI_STATE;
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
state <= QPI_EXIT;
|
|
||||||
sr_load <= '0';
|
|
||||||
requested <= '0';
|
|
||||||
opmode <= COMMAND;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
sr_load <= '0';
|
|
||||||
|
|
||||||
case state is
|
|
||||||
when QPI_EXIT =>
|
|
||||||
state <= SPI_RESET1 when qpi_xfer((x"F", x"5"));
|
|
||||||
|
|
||||||
when SPI_RESET1 =>
|
|
||||||
state <= SPI_RESET2 when qpi_xfer(qpi_to_spi((x"6", x"6")));
|
|
||||||
|
|
||||||
when SPI_RESET2 =>
|
|
||||||
state <= SPI_ENABLE_QPI when qpi_xfer(qpi_to_spi((x"9", x"9")));
|
|
||||||
|
|
||||||
when SPI_ENABLE_QPI =>
|
|
||||||
state <= POST_QPI_STATE when qpi_xfer(qpi_to_spi((x"3", x"5")));
|
|
||||||
|
|
||||||
when QPI_SET_BOUNDARY =>
|
|
||||||
state <= IDLE when qpi_xfer((x"C", x"0"));
|
|
||||||
|
|
||||||
when IDLE =>
|
|
||||||
if read_en then
|
|
||||||
state <= READ;
|
|
||||||
elsif write_en then
|
|
||||||
state <= WRITE;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when READ =>
|
|
||||||
state <= IDLE when qpi_xfer(sr_element_vector'(x"0", x"B") & addr_to_nibbles(addr), READ);
|
|
||||||
if not read_en then
|
|
||||||
qpi_stop;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when WRITE =>
|
|
||||||
state <= IDLE when qpi_xfer(sr_element_vector'(x"0", x"2") & addr_to_nibbles(addr), WRITE);
|
|
||||||
if not write_en then
|
|
||||||
qpi_stop;
|
|
||||||
end if;
|
|
||||||
end case;
|
|
||||||
end if;
|
|
||||||
end process fsm;
|
|
||||||
|
|
||||||
end architecture rtl;
|
|
||||||
|
|
|
@ -1,263 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
-- TODO: By default, some (random) value is placed in cached_address, which may corrupt data if this happens to be the
|
|
||||||
-- first address accessesd after reset.
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
|
|
||||||
entity aps6404l_wb is
|
|
||||||
port(
|
|
||||||
clk : in std_logic;
|
|
||||||
rst : in std_logic; --
|
|
||||||
|
|
||||||
-- Instruction Wishbone IF (32b read access only, caches one instruction ahead)
|
|
||||||
wbi_o : out wishbone_slave_out; -- Instruction Wishbone bus (out)
|
|
||||||
wbi_i : in wishbone_slave_in; -- Instruction Wishbone bus (in)
|
|
||||||
|
|
||||||
-- Wishbone IF
|
|
||||||
wb_o : out wishbone_slave_out; -- Wishbone bus (out)
|
|
||||||
wb_i : in wishbone_slave_in; -- Wishbone bus (in)
|
|
||||||
|
|
||||||
-- PSRAM IF
|
|
||||||
psram_ce_n : out std_logic;
|
|
||||||
psram_sclk : out std_logic;
|
|
||||||
psram_sio : inout std_logic_vector(3 downto 0) --
|
|
||||||
);
|
|
||||||
end entity aps6404l_wb;
|
|
||||||
|
|
||||||
architecture rtl of aps6404l_wb is
|
|
||||||
type apsc_in is record
|
|
||||||
addr : std_logic_vector(23 downto 0);
|
|
||||||
data_in : std_logic_vector(7 downto 0);
|
|
||||||
write_en : std_logic;
|
|
||||||
read_en : std_logic;
|
|
||||||
end record apsc_in;
|
|
||||||
|
|
||||||
type apsc_out is record
|
|
||||||
data_in_next : std_logic;
|
|
||||||
data_out : std_logic_vector(7 downto 0);
|
|
||||||
data_out_valid : std_logic;
|
|
||||||
end record apsc_out;
|
|
||||||
|
|
||||||
signal apsc_i : apsc_in;
|
|
||||||
signal apsc_o : apsc_out;
|
|
||||||
|
|
||||||
signal cached_address : std_logic_vector(apsc_i.addr'range);
|
|
||||||
signal cached_data : wishbone_data;
|
|
||||||
signal api_i : apsc_in;
|
|
||||||
signal api_o : apsc_out;
|
|
||||||
signal api_request_count : integer range 0 to 2;
|
|
||||||
signal api_bit_cnt : integer range 0 to 3;
|
|
||||||
|
|
||||||
signal apd_i : apsc_in;
|
|
||||||
signal apd_o : apsc_out;
|
|
||||||
signal bit_cnt : integer range 0 to 4;
|
|
||||||
signal data : std_logic_vector(wb_i.dat'range);
|
|
||||||
|
|
||||||
signal ap_sel : integer range 0 to 1;
|
|
||||||
|
|
||||||
begin
|
|
||||||
aps6404l_controller_inst : entity work.aps6404l_controller
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
addr => apsc_i.addr,
|
|
||||||
data_in => apsc_i.data_in,
|
|
||||||
data_in_next => apsc_o.data_in_next,
|
|
||||||
data_out => apsc_o.data_out,
|
|
||||||
data_out_valid => apsc_o.data_out_valid,
|
|
||||||
write_en => apsc_i.write_en,
|
|
||||||
read_en => apsc_i.read_en,
|
|
||||||
psram_ce_n => psram_ce_n,
|
|
||||||
psram_sclk => psram_sclk,
|
|
||||||
psram_sio => psram_sio
|
|
||||||
);
|
|
||||||
|
|
||||||
ap_arb : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
ap_sel <= 0;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if ap_sel = 0 then
|
|
||||||
if not (api_i.read_en or api_i.write_en) and (apd_i.read_en or apd_i.write_en) then
|
|
||||||
ap_sel <= 1;
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
if (apd_i.read_en nor apd_i.write_en) then -- lock until APD releases
|
|
||||||
ap_sel <= 0;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process ap_arb;
|
|
||||||
|
|
||||||
ap_mux : process(all) is
|
|
||||||
constant APSC_IN_DEFAULT : apsc_in := (
|
|
||||||
addr => (others => '-'),
|
|
||||||
data_in => (others => '-'),
|
|
||||||
write_en => '0',
|
|
||||||
read_en => '0'
|
|
||||||
);
|
|
||||||
constant APSC_OUT_DEFAULT : apsc_out := (
|
|
||||||
data_in_next => '0',
|
|
||||||
data_out => (others => '-'),
|
|
||||||
data_out_valid => '0'
|
|
||||||
);
|
|
||||||
begin
|
|
||||||
apsc_i <= APSC_IN_DEFAULT;
|
|
||||||
api_o <= APSC_OUT_DEFAULT;
|
|
||||||
apd_o <= APSC_OUT_DEFAULT;
|
|
||||||
|
|
||||||
if ap_sel = 0 then
|
|
||||||
api_o <= apsc_o;
|
|
||||||
apsc_i <= api_i;
|
|
||||||
else
|
|
||||||
apd_o <= apsc_o;
|
|
||||||
apsc_i <= apd_i;
|
|
||||||
end if;
|
|
||||||
end process ap_mux;
|
|
||||||
|
|
||||||
instruction_memory_p : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
wbi_o.ack <= '0';
|
|
||||||
cached_address <= (others => '1'); -- TODO: Set cached_address to 0xFFFFFF
|
|
||||||
api_request_count <= 0;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
wbi_o.ack <= '0';
|
|
||||||
|
|
||||||
if wbi_i.cyc and wbi_i.stb then
|
|
||||||
if wbi_i.adr(cached_address'range) = cached_address then -- cache hit, return current immediately, retrieve next in meantime
|
|
||||||
wbi_o.dat <= cached_data;
|
|
||||||
wbi_o.ack <= '1';
|
|
||||||
|
|
||||||
api_i.addr <= std_logic_vector(unsigned(wbi_i.adr(apsc_i.addr'range)) + 4);
|
|
||||||
if not api_i.read_en then -- If we haven't yet triggered the retrieve from memory, start it now
|
|
||||||
api_request_count <= 1;
|
|
||||||
end if;
|
|
||||||
else -- cache miss, retrieve current (return asap) + next
|
|
||||||
if not api_i.read_en then -- If we haven't yet triggered the retrieve from memory, start it now
|
|
||||||
api_i.addr <= wbi_i.adr(apsc_i.addr'range);
|
|
||||||
api_request_count <= 2;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
if api_o.data_out_valid then
|
|
||||||
cached_data <= api_o.data_out & cached_data(cached_data'high downto 8); -- TODO: this assumes the CPU quickly processes the ACK (within one SPI byte)
|
|
||||||
|
|
||||||
if api_bit_cnt = 3 then
|
|
||||||
cached_address <= api_i.addr;
|
|
||||||
if api_request_count > 0 then
|
|
||||||
api_request_count <= api_request_count - 1;
|
|
||||||
end if;
|
|
||||||
api_bit_cnt <= 0;
|
|
||||||
else
|
|
||||||
api_bit_cnt <= api_bit_cnt + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
if not api_i.read_en then
|
|
||||||
api_bit_cnt <= 0;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process instruction_memory_p;
|
|
||||||
api_i.read_en <= '1' when api_request_count > 0 else '0';
|
|
||||||
api_i.write_en <= '0';
|
|
||||||
wbi_o.err <= '0';
|
|
||||||
wbi_o.rty <= '0';
|
|
||||||
wbi_o.stall <= not wbi_o.ack;
|
|
||||||
|
|
||||||
main : process(clk, rst) is
|
|
||||||
variable start_addr : integer range 0 to 3;
|
|
||||||
variable stop_addr : integer range 0 to 3;
|
|
||||||
variable success : std_logic;
|
|
||||||
variable we : std_logic;
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
wb_o.ack <= '0';
|
|
||||||
bit_cnt <= 0;
|
|
||||||
apd_i.read_en <= '0';
|
|
||||||
apd_i.write_en <= '0';
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
wb_o.ack <= '0';
|
|
||||||
|
|
||||||
if bit_cnt = 0 then
|
|
||||||
apd_i.read_en <= '0';
|
|
||||||
apd_i.write_en <= '0';
|
|
||||||
|
|
||||||
start_addr := 0;
|
|
||||||
for i in 0 to 3 loop
|
|
||||||
if wb_i.sel(i) = '1' then
|
|
||||||
start_addr := i;
|
|
||||||
exit;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
stop_addr := 0;
|
|
||||||
for i in 3 downto 0 loop
|
|
||||||
if wb_i.sel(i) = '1' then
|
|
||||||
stop_addr := i;
|
|
||||||
exit;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
apd_i.addr <= wb_i.adr(apsc_i.addr'length - 1 downto 2) & std_logic_vector(to_unsigned(start_addr, 2));
|
|
||||||
data <= wb_i.dat;
|
|
||||||
|
|
||||||
we := wb_i.we;
|
|
||||||
if not wb_o.ack and wb_i.stb and wb_i.cyc then
|
|
||||||
bit_cnt <= 4;
|
|
||||||
if wb_i.we then
|
|
||||||
wb_o.ack <= '1'; -- We can ack a write immediately
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
success := '0';
|
|
||||||
|
|
||||||
if bit_cnt >= (4 - stop_addr) and bit_cnt <= (4 - start_addr) then
|
|
||||||
apd_i.read_en <= not we;
|
|
||||||
apd_i.write_en <= we;
|
|
||||||
else
|
|
||||||
apd_i.read_en <= '0';
|
|
||||||
apd_i.write_en <= '0';
|
|
||||||
success := '1';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if we and apd_o.data_in_next then
|
|
||||||
success := '1';
|
|
||||||
elsif not we and apd_o.data_out_valid then
|
|
||||||
success := '1';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if success then
|
|
||||||
bit_cnt <= bit_cnt - 1;
|
|
||||||
wb_o.dat <= apd_o.data_out & wb_o.dat(wb_o.dat'high downto 8);
|
|
||||||
data <= x"--" & data(data'high downto 8);
|
|
||||||
if (bit_cnt = 1) and (we = '0') then -- We only need to ack reads, writes were already acked in bit_cnt = 0
|
|
||||||
wb_o.ack <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end if;
|
|
||||||
end process main;
|
|
||||||
apd_i.data_in <= data(apsc_i.data_in'range);
|
|
||||||
|
|
||||||
wb_o.err <= '0';
|
|
||||||
wb_o.rty <= '0';
|
|
||||||
wb_o.stall <= not wb_o.ack;
|
|
||||||
|
|
||||||
end architecture rtl;
|
|
|
@ -1,57 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library IEEE;
|
|
||||||
use IEEE.std_logic_1164.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.ice40_components.all;
|
|
||||||
|
|
||||||
entity pll0 is
|
|
||||||
generic(
|
|
||||||
F_IN : in integer;
|
|
||||||
F_CLK : in integer;
|
|
||||||
F_CLK_PHY : in integer
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk_in : in std_logic;
|
|
||||||
clk_out : out std_logic;
|
|
||||||
clk_out_phy : out std_logic;
|
|
||||||
locked : out std_logic
|
|
||||||
);
|
|
||||||
end pll0;
|
|
||||||
|
|
||||||
architecture Structure of pll0 is
|
|
||||||
signal clk_out_i : std_logic;
|
|
||||||
begin
|
|
||||||
-- Not clean, but it works...
|
|
||||||
ckdiv2 : process(clk_out_phy) is
|
|
||||||
begin
|
|
||||||
if rising_edge(clk_out_phy) then
|
|
||||||
clk_out_i <= not clk_out_i;
|
|
||||||
end if;
|
|
||||||
end process ckdiv2;
|
|
||||||
|
|
||||||
SB_GB_inst : component SB_GB
|
|
||||||
port map(
|
|
||||||
USER_SIGNAL_TO_GLOBAL_BUFFER => clk_out_i,
|
|
||||||
GLOBAL_BUFFER_OUTPUT => clk_out
|
|
||||||
);
|
|
||||||
|
|
||||||
SB_GB2_inst : component SB_GB
|
|
||||||
port map(
|
|
||||||
USER_SIGNAL_TO_GLOBAL_BUFFER => clk_in,
|
|
||||||
GLOBAL_BUFFER_OUTPUT => clk_out_phy
|
|
||||||
);
|
|
||||||
|
|
||||||
assert F_IN = 50000000 report "clk_in: PLL expects clock different from specified." severity failure;
|
|
||||||
assert F_CLK = 25000000 report "clk: PLL generates clock different from specified." severity failure;
|
|
||||||
assert F_CLK_PHY = 50000000 report "clk_phy: PLL generates clock different from specified." severity failure;
|
|
||||||
end Structure;
|
|
|
@ -1,91 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
|
|
||||||
entity serv_top_vhdl is
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- CPU and bus clock
|
|
||||||
clr : in std_logic; -- Synchronous clear (CPU reset)
|
|
||||||
wbi_o : out wishbone_master_out; -- Instruction Wishbone bus (out)
|
|
||||||
wbi_i : in wishbone_master_in; -- Instruction Wishbone bus (in)
|
|
||||||
wbd_o : out wishbone_master_out; -- Data Wishbone bus (out)
|
|
||||||
wbd_i : in wishbone_master_in; -- Data Wishbone bus (in)
|
|
||||||
irq_timer : in std_logic -- System timer interrupt
|
|
||||||
);
|
|
||||||
end entity serv_top_vhdl;
|
|
||||||
|
|
||||||
architecture rtl of serv_top_vhdl is
|
|
||||||
component serv_rf_top
|
|
||||||
port(
|
|
||||||
clk : in std_logic;
|
|
||||||
i_rst : in std_logic;
|
|
||||||
i_timer_irq : in std_logic;
|
|
||||||
o_ibus_adr : out std_logic_vector(31 downto 0);
|
|
||||||
o_ibus_cyc : out std_logic;
|
|
||||||
i_ibus_rdt : in std_logic_vector(31 downto 0);
|
|
||||||
i_ibus_ack : in std_logic;
|
|
||||||
o_dbus_adr : out std_logic_vector(31 downto 0);
|
|
||||||
o_dbus_dat : out std_logic_vector(31 downto 0);
|
|
||||||
o_dbus_sel : out std_logic_vector(3 downto 0);
|
|
||||||
o_dbus_we : out std_logic;
|
|
||||||
o_dbus_cyc : out std_logic;
|
|
||||||
i_dbus_rdt : in std_logic_vector(31 downto 0);
|
|
||||||
i_dbus_ack : in std_logic;
|
|
||||||
o_ext_rs1 : out std_logic_vector(31 downto 0);
|
|
||||||
o_ext_rs2 : out std_logic_vector(31 downto 0);
|
|
||||||
o_ext_funct3 : out std_logic_vector(2 downto 0);
|
|
||||||
i_ext_rd : in std_logic_vector(31 downto 0);
|
|
||||||
i_ext_ready : in std_logic;
|
|
||||||
o_mdu_valid : out std_logic
|
|
||||||
);
|
|
||||||
end component serv_rf_top;
|
|
||||||
|
|
||||||
signal wbd_o_dat_bv : bit_vector(31 downto 0);
|
|
||||||
begin
|
|
||||||
serv_top : serv_rf_top
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
i_rst => clr,
|
|
||||||
i_timer_irq => irq_timer,
|
|
||||||
o_ibus_adr => wbi_o.adr,
|
|
||||||
o_ibus_cyc => wbi_o.cyc,
|
|
||||||
i_ibus_rdt => wbi_i.dat,
|
|
||||||
i_ibus_ack => wbi_i.ack,
|
|
||||||
o_dbus_adr => wbd_o.adr,
|
|
||||||
o_dbus_dat => wbd_o.dat,
|
|
||||||
o_dbus_sel => wbd_o.sel,
|
|
||||||
o_dbus_we => wbd_o.we,
|
|
||||||
o_dbus_cyc => wbd_o.cyc,
|
|
||||||
i_dbus_rdt => wbd_i.dat,
|
|
||||||
i_dbus_ack => wbd_i.ack,
|
|
||||||
o_ext_rs1 => open,
|
|
||||||
o_ext_rs2 => open,
|
|
||||||
o_ext_funct3 => open,
|
|
||||||
i_ext_rd => (others => '0'),
|
|
||||||
i_ext_ready => '0',
|
|
||||||
o_mdu_valid => open
|
|
||||||
);
|
|
||||||
|
|
||||||
--wbd_o.dat <= to_std_logic_vector(wbd_o_dat_bv);
|
|
||||||
|
|
||||||
wbi_o.stb <= wbi_o.cyc;
|
|
||||||
wbi_o.sel <= (others => '1');
|
|
||||||
wbi_o.we <= '0';
|
|
||||||
wbi_o.dat <= (others => '0');
|
|
||||||
|
|
||||||
wbd_o.stb <= wbd_o.cyc;
|
|
||||||
|
|
||||||
end architecture rtl;
|
|
|
@ -1,58 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
|
|
||||||
entity servant_gpio_vhdl is
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- CPU and bus clock
|
|
||||||
clr : in std_logic; -- Synchronous clear (CPU reset)
|
|
||||||
|
|
||||||
wb_o : out wishbone_slave_out; -- Instruction Wishbone bus (out)
|
|
||||||
wb_i : in wishbone_slave_in; -- Instruction Wishbone bus (in)
|
|
||||||
|
|
||||||
output : out std_logic -- System Timer Interrupt
|
|
||||||
);
|
|
||||||
end entity servant_gpio_vhdl;
|
|
||||||
|
|
||||||
architecture rtl of servant_gpio_vhdl is
|
|
||||||
component servant_gpio
|
|
||||||
port(
|
|
||||||
i_wb_clk : in std_logic;
|
|
||||||
i_wb_dat : in std_logic;
|
|
||||||
i_wb_we : in std_logic;
|
|
||||||
i_wb_cyc : in std_logic;
|
|
||||||
o_wb_rdt : out std_logic;
|
|
||||||
o_gpio : out std_logic
|
|
||||||
);
|
|
||||||
end component servant_gpio;
|
|
||||||
|
|
||||||
begin
|
|
||||||
servant_gpio_inst : component servant_gpio
|
|
||||||
port map(
|
|
||||||
i_wb_clk => clk,
|
|
||||||
i_wb_dat => wb_i.dat(0),
|
|
||||||
i_wb_we => wb_i.we,
|
|
||||||
i_wb_cyc => wb_i.cyc and wb_i.stb,
|
|
||||||
o_wb_rdt => wb_o.dat(0),
|
|
||||||
o_gpio => output
|
|
||||||
);
|
|
||||||
|
|
||||||
wb_o.ack <= '1';
|
|
||||||
wb_o.rty <= '0';
|
|
||||||
wb_o.err <= '0';
|
|
||||||
wb_o.stall <= '0';
|
|
||||||
wb_o.dat(31 downto 1) <= (others => '0');
|
|
||||||
end architecture rtl;
|
|
|
@ -1,90 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
|
|
||||||
entity servant_ram_vhdl is
|
|
||||||
generic(
|
|
||||||
memfile : string := "data/empty.hex";
|
|
||||||
read_only : boolean := false;
|
|
||||||
adr_width : integer := 16
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- CPU and bus clock
|
|
||||||
clr : in std_logic; -- Synchronous reset
|
|
||||||
|
|
||||||
wb_o : out wishbone_slave_out; -- Wishbone bus (out)
|
|
||||||
wb_i : in wishbone_slave_in -- Wishbone bus (in)
|
|
||||||
);
|
|
||||||
end entity servant_ram_vhdl;
|
|
||||||
|
|
||||||
architecture rtl of servant_ram_vhdl is
|
|
||||||
component servant_ram
|
|
||||||
generic(
|
|
||||||
depth : integer;
|
|
||||||
aw : integer;
|
|
||||||
memfile : string
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
i_wb_clk : in std_logic;
|
|
||||||
i_wb_rst : in std_logic;
|
|
||||||
i_wb_adr : in std_logic_vector;
|
|
||||||
i_wb_dat : in std_logic_vector;
|
|
||||||
i_wb_sel : in std_logic_vector;
|
|
||||||
i_wb_we : in std_logic;
|
|
||||||
i_wb_cyc : in std_logic;
|
|
||||||
o_wb_rdt : out std_logic_vector;
|
|
||||||
o_wb_ack : out std_logic
|
|
||||||
);
|
|
||||||
end component servant_ram;
|
|
||||||
|
|
||||||
begin
|
|
||||||
servant_ram_inst : component servant_ram
|
|
||||||
generic map(
|
|
||||||
depth => 2 ** adr_width,
|
|
||||||
aw => adr_width,
|
|
||||||
memfile => memfile
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
i_wb_clk => clk,
|
|
||||||
i_wb_rst => clr,
|
|
||||||
i_wb_adr => wb_i.adr(adr_width - 1 downto 2),
|
|
||||||
i_wb_dat => wb_i.dat,
|
|
||||||
i_wb_sel => wb_i.sel,
|
|
||||||
i_wb_we => wb_i.we,
|
|
||||||
i_wb_cyc => wb_i.cyc and wb_i.stb,
|
|
||||||
o_wb_rdt => wb_o.dat,
|
|
||||||
o_wb_ack => wb_o.ack
|
|
||||||
);
|
|
||||||
|
|
||||||
wb_o.rty <= '0';
|
|
||||||
wb_o.err <= '0';
|
|
||||||
wb_o.stall <= '0';
|
|
||||||
|
|
||||||
rowarn : process(clk) is
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if wb_i.cyc and wb_i.stb then
|
|
||||||
if (unsigned(wb_i.adr) > 2 ** adr_width - 1) then
|
|
||||||
report "ERROR: Out of bounds for " & servant_ram_vhdl'path_name & " @0x" & to_hstring(wb_i.adr) severity error;
|
|
||||||
end if;
|
|
||||||
if (wb_i.we = '1' and read_only) then
|
|
||||||
report "ERROR: Write access to ROM @0x" & to_hstring(wb_i.adr) severity warning;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process rowarn;
|
|
||||||
|
|
||||||
end architecture rtl;
|
|
|
@ -1,65 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
|
|
||||||
entity servant_timer_vhdl is
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- CPU and bus clock
|
|
||||||
clr : in std_logic; -- Synchronous clear (CPU reset)
|
|
||||||
|
|
||||||
wb_o : out wishbone_slave_out; -- Wishbone bus (out)
|
|
||||||
wb_i : in wishbone_slave_in; -- Wishbone bus (in)
|
|
||||||
|
|
||||||
irq : out std_logic -- System Timer Interrupt
|
|
||||||
);
|
|
||||||
end entity servant_timer_vhdl;
|
|
||||||
|
|
||||||
architecture rtl of servant_timer_vhdl is
|
|
||||||
component servant_timer
|
|
||||||
generic(
|
|
||||||
WIDTH : integer
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
i_clk : in std_logic;
|
|
||||||
i_rst : in std_logic;
|
|
||||||
o_irq : out std_logic;
|
|
||||||
i_wb_dat : in std_logic_vector;
|
|
||||||
i_wb_we : in std_logic;
|
|
||||||
i_wb_cyc : in std_logic;
|
|
||||||
o_wb_dat : out std_logic_vector
|
|
||||||
);
|
|
||||||
end component servant_timer;
|
|
||||||
|
|
||||||
begin
|
|
||||||
servant_timer_inst : component servant_timer
|
|
||||||
generic map(
|
|
||||||
WIDTH => 32
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
i_clk => clk,
|
|
||||||
i_rst => clr,
|
|
||||||
o_irq => irq,
|
|
||||||
i_wb_dat => wb_i.dat,
|
|
||||||
i_wb_we => wb_i.we,
|
|
||||||
i_wb_cyc => wb_i.cyc and wb_i.stb,
|
|
||||||
o_wb_dat => wb_o.dat
|
|
||||||
);
|
|
||||||
|
|
||||||
wb_o.ack <= '1';
|
|
||||||
wb_o.rty <= '0';
|
|
||||||
wb_o.err <= '0';
|
|
||||||
wb_o.stall <= '0';
|
|
||||||
end architecture rtl;
|
|
|
@ -1,317 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.all;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
use generics.ice40_components.all;
|
|
||||||
|
|
||||||
entity top is
|
|
||||||
generic(
|
|
||||||
-- System configuration
|
|
||||||
F_IN : integer := 50000000;
|
|
||||||
F_CLK : integer := 25000000;
|
|
||||||
F_CLK_PHY : integer := 50000000;
|
|
||||||
UART_BAUD : integer := 250000
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk_in : in std_logic; -- System clock
|
|
||||||
|
|
||||||
-- UART
|
|
||||||
uart_tx : out std_logic; -- UART TX
|
|
||||||
uart_rx : in std_logic; -- UART RX
|
|
||||||
|
|
||||||
-- Trashernet
|
|
||||||
eth_rx_p : in std_logic; -- Ethernet RX+
|
|
||||||
--eth_rx_n : in std_logic; -- Ethernet RX-
|
|
||||||
eth_tx_p : out std_logic_vector(3 downto 0); -- Ethernet TX+
|
|
||||||
eth_tx_n : out std_logic_vector(3 downto 0); -- Ethernet TX-
|
|
||||||
|
|
||||||
-- LEDs
|
|
||||||
eth_led_green_n : out std_logic;
|
|
||||||
eth_led_orange_n : out std_logic;
|
|
||||||
led_user : out std_logic; --
|
|
||||||
|
|
||||||
-- PSRAM IF
|
|
||||||
psram_ce_n : out std_logic;
|
|
||||||
psram_sclk : out std_logic;
|
|
||||||
psram_sio : inout std_logic_vector(3 downto 0); --
|
|
||||||
|
|
||||||
-- Config Flash
|
|
||||||
flash_ce_n : out std_logic;
|
|
||||||
flash_sclk : out std_logic;
|
|
||||||
flash_sio : inout std_logic_vector(3 downto 0); --
|
|
||||||
|
|
||||||
-- PMOD
|
|
||||||
pmod : inout std_logic_vector(7 downto 0)
|
|
||||||
);
|
|
||||||
end entity top;
|
|
||||||
|
|
||||||
architecture rtl of top is
|
|
||||||
-- System
|
|
||||||
signal pll_locked : std_logic;
|
|
||||||
signal clk : std_logic;
|
|
||||||
signal clk_phy : std_logic;
|
|
||||||
signal rst : std_logic := '1'; -- Asynchronous assert, synchronous release reset
|
|
||||||
signal clr : std_logic := '1'; -- Fully synchronous reset
|
|
||||||
|
|
||||||
signal eth_tx_p_i : std_logic;
|
|
||||||
signal eth_tx_n_i : std_logic;
|
|
||||||
signal eth_rx_p_i : std_logic;
|
|
||||||
|
|
||||||
signal eth_led_green : std_logic;
|
|
||||||
signal eth_led_orange : std_logic;
|
|
||||||
|
|
||||||
-- System Timer
|
|
||||||
signal irq_timer : std_logic;
|
|
||||||
|
|
||||||
-- # Instruction Bus
|
|
||||||
-- Wishbone interconnect (master)
|
|
||||||
signal wbi_masters_o : wishbone_slave_in_vector(0 downto 0);
|
|
||||||
signal wbi_masters_i : wishbone_slave_out_vector(wbi_masters_o'range);
|
|
||||||
alias wbi_o is wbi_masters_o(0);
|
|
||||||
alias wbi_i is wbi_masters_i(0);
|
|
||||||
|
|
||||||
-- Wishbone interconnect (slave)
|
|
||||||
signal wbi_slaves_o : wishbone_master_in_vector(1 downto 0);
|
|
||||||
signal wbi_slaves_i : wishbone_master_out_vector(wbi_slaves_o'range);
|
|
||||||
alias wbi_rom_o is wbi_slaves_o(0);
|
|
||||||
alias wbi_rom_i is wbi_slaves_i(0);
|
|
||||||
alias wbi_ram_o is wbi_slaves_o(1);
|
|
||||||
alias wbi_ram_i is wbi_slaves_i(1);
|
|
||||||
|
|
||||||
-- Slave address map
|
|
||||||
constant wishbone_instruction_addresses : wishbone_address_vector := (
|
|
||||||
0 => x"00000000", -- Boot ROM
|
|
||||||
1 => x"40000000" -- RAM
|
|
||||||
);
|
|
||||||
constant wishbone_instruction_masks : wishbone_address_vector := (
|
|
||||||
0 => x"C0000000", -- Boot ROM
|
|
||||||
1 => x"C0000000" -- RAM
|
|
||||||
);
|
|
||||||
|
|
||||||
-- # Data Bus
|
|
||||||
-- Wishbone interconnect (master)
|
|
||||||
signal wbd_masters_o : wishbone_slave_in_vector(0 downto 0);
|
|
||||||
signal wbd_masters_i : wishbone_slave_out_vector(wbd_masters_o'range);
|
|
||||||
alias wbd_o is wbd_masters_o(0);
|
|
||||||
alias wbd_i is wbd_masters_i(0);
|
|
||||||
|
|
||||||
-- Wishbone interconnect (slave)
|
|
||||||
signal wbd_slaves_o : wishbone_master_in_vector(3 downto 0);
|
|
||||||
signal wbd_slaves_i : wishbone_master_out_vector(wbd_slaves_o'range);
|
|
||||||
alias wb_ram_o is wbd_slaves_o(0);
|
|
||||||
alias wb_ram_i is wbd_slaves_i(0);
|
|
||||||
alias wb_timer_o is wbd_slaves_o(1);
|
|
||||||
alias wb_timer_i is wbd_slaves_i(1);
|
|
||||||
alias wb_uart_o is wbd_slaves_o(2);
|
|
||||||
alias wb_uart_i is wbd_slaves_i(2);
|
|
||||||
alias wb_eth_o is wbd_slaves_o(3);
|
|
||||||
alias wb_eth_i is wbd_slaves_i(3);
|
|
||||||
|
|
||||||
-- Slave address map
|
|
||||||
constant wishbone_data_addresses : wishbone_address_vector := (
|
|
||||||
0 => x"40000000", -- RAM
|
|
||||||
1 => x"80000000", -- Timer
|
|
||||||
2 => x"81000000", -- UART
|
|
||||||
3 => x"82000000" -- Eth
|
|
||||||
);
|
|
||||||
constant wishbone_data_masks : wishbone_address_vector := (
|
|
||||||
0 => x"FF000000", -- RAM: Max 16M
|
|
||||||
1 => x"FF000000", -- Timer
|
|
||||||
2 => x"FF000000", -- UART
|
|
||||||
3 => x"FF000000" -- Eth
|
|
||||||
);
|
|
||||||
|
|
||||||
constant IN_SIMULATION : boolean := false --
|
|
||||||
-- pragma translate_off
|
|
||||||
or true --
|
|
||||||
-- pragma translate_on
|
|
||||||
;
|
|
||||||
begin
|
|
||||||
|
|
||||||
SB_IO_inst : component SB_IO
|
|
||||||
generic map(
|
|
||||||
PIN_TYPE => "000000",
|
|
||||||
IO_STANDARD => "SB_LVDS_INPUT"
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
PACKAGE_PIN => eth_rx_p,
|
|
||||||
LATCH_INPUT_VALUE => '1',
|
|
||||||
CLOCK_ENABLE => '1',
|
|
||||||
INPUT_CLK => clk_phy,
|
|
||||||
OUTPUT_CLK => clk_phy,
|
|
||||||
OUTPUT_ENABLE => '0',
|
|
||||||
D_OUT_0 => '0',
|
|
||||||
D_OUT_1 => '0',
|
|
||||||
D_IN_0 => eth_rx_p_i,
|
|
||||||
D_IN_1 => open
|
|
||||||
);
|
|
||||||
|
|
||||||
clockgen : if IN_SIMULATION generate
|
|
||||||
clock_driver : process
|
|
||||||
constant period : time := 1 sec / real(F_CLK);
|
|
||||||
begin
|
|
||||||
clk <= '0';
|
|
||||||
wait for period / 2;
|
|
||||||
clk <= '1';
|
|
||||||
wait for period / 2;
|
|
||||||
end process clock_driver;
|
|
||||||
|
|
||||||
pll_locked <= '1';
|
|
||||||
|
|
||||||
else generate
|
|
||||||
pll_inst : entity work.pll0
|
|
||||||
generic map(
|
|
||||||
F_IN => F_IN,
|
|
||||||
F_CLK => F_CLK,
|
|
||||||
F_CLK_PHY => F_CLK_PHY
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk_in => clk_in,
|
|
||||||
clk_out => clk,
|
|
||||||
clk_out_phy => clk_phy,
|
|
||||||
locked => pll_locked
|
|
||||||
);
|
|
||||||
end generate clockgen;
|
|
||||||
|
|
||||||
por : process(clk) is
|
|
||||||
variable reset_cnt : integer range 0 to 255 := 0;
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset_cnt = 255 then
|
|
||||||
rst <= '0';
|
|
||||||
clr <= '0';
|
|
||||||
else
|
|
||||||
reset_cnt := reset_cnt + 1;
|
|
||||||
rst <= '1';
|
|
||||||
clr <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process por;
|
|
||||||
|
|
||||||
serv_top_vhdl_inst : entity work.serv_top_vhdl
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
clr => clr,
|
|
||||||
wbi_o => wbi_o,
|
|
||||||
wbi_i => wbi_i,
|
|
||||||
wbd_o => wbd_o,
|
|
||||||
wbd_i => wbd_i,
|
|
||||||
irq_timer => irq_timer
|
|
||||||
);
|
|
||||||
|
|
||||||
servant_rom_vhdl_inst : entity work.servant_ram_vhdl
|
|
||||||
generic map(
|
|
||||||
memfile => "../sw/bootrom/bootrom.vhex",
|
|
||||||
read_only => true,
|
|
||||||
adr_width => 9
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
clr => clr,
|
|
||||||
wb_o => wbi_rom_o,
|
|
||||||
wb_i => wbi_rom_i
|
|
||||||
);
|
|
||||||
|
|
||||||
aps6404l_wb_inst : entity work.aps6404l_wb
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
wbi_o => wbi_ram_o,
|
|
||||||
wbi_i => wbi_ram_i,
|
|
||||||
wb_o => wb_ram_o,
|
|
||||||
wb_i => wb_ram_i,
|
|
||||||
psram_ce_n => psram_ce_n,
|
|
||||||
psram_sclk => psram_sclk,
|
|
||||||
psram_sio => psram_sio
|
|
||||||
);
|
|
||||||
|
|
||||||
servant_timer_vhdl_inst : entity work.servant_timer_vhdl
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
clr => clr,
|
|
||||||
wb_o => wb_timer_o,
|
|
||||||
wb_i => wb_timer_i,
|
|
||||||
irq => irq_timer
|
|
||||||
);
|
|
||||||
|
|
||||||
uart_wb_inst : entity work.uart_wb
|
|
||||||
generic map(
|
|
||||||
F_CLK => F_CLK,
|
|
||||||
BAUD_RATE => UART_BAUD
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
wb_o => wb_uart_o,
|
|
||||||
wb_i => wb_uart_i,
|
|
||||||
serial_out => uart_tx,
|
|
||||||
serial_in => uart_rx
|
|
||||||
);
|
|
||||||
|
|
||||||
trashernet_phy_wb_inst : entity work.trashernet_phy_wb
|
|
||||||
generic map(
|
|
||||||
F_CLK => F_CLK,
|
|
||||||
F_CLK_PHY => F_CLK_PHY
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
phy_clk => clk_phy,
|
|
||||||
rst => rst,
|
|
||||||
wb_o => wb_eth_o,
|
|
||||||
wb_i => wb_eth_i,
|
|
||||||
rx_p => eth_rx_p_i,
|
|
||||||
tx_p => eth_tx_p_i,
|
|
||||||
tx_n => eth_tx_n_i,
|
|
||||||
led_rx => eth_led_green,
|
|
||||||
led_tx => eth_led_orange
|
|
||||||
);
|
|
||||||
eth_tx_p <= (others => eth_tx_p_i);
|
|
||||||
eth_tx_n <= (others => eth_tx_n_i);
|
|
||||||
|
|
||||||
wishbone_crossbar_data_inst : entity generics.wishbone_arbiter
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
masters_o => wbd_masters_o,
|
|
||||||
masters_i => wbd_masters_i,
|
|
||||||
slaves_o => wbd_slaves_o,
|
|
||||||
slaves_i => wbd_slaves_i,
|
|
||||||
address => wishbone_data_addresses,
|
|
||||||
mask => wishbone_data_masks
|
|
||||||
);
|
|
||||||
|
|
||||||
wishbone_crossbar_instruction_inst : entity generics.wishbone_arbiter
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
masters_o => wbi_masters_o,
|
|
||||||
masters_i => wbi_masters_i,
|
|
||||||
slaves_o => wbi_slaves_o,
|
|
||||||
slaves_i => wbi_slaves_i,
|
|
||||||
address => wishbone_instruction_addresses,
|
|
||||||
mask => wishbone_instruction_masks
|
|
||||||
);
|
|
||||||
|
|
||||||
eth_led_green_n <= not eth_led_green;
|
|
||||||
eth_led_orange_n <= not eth_led_orange;
|
|
||||||
led_user <= not uart_tx or not uart_rx;
|
|
||||||
|
|
||||||
flash_ce_n <= 'Z';
|
|
||||||
flash_sclk <= 'Z';
|
|
||||||
flash_sio <= (others => 'Z');
|
|
||||||
|
|
||||||
pmod <= (others => 'Z');
|
|
||||||
end architecture rtl;
|
|
|
@ -1,262 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library trashernet;
|
|
||||||
use trashernet.trashernet_pkg.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.all;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
|
|
||||||
entity trashernet_phy_wb is
|
|
||||||
generic(
|
|
||||||
F_CLK : in integer; -- Clock frequency in Hz
|
|
||||||
F_CLK_PHY : in integer
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
-- Global
|
|
||||||
clk : in std_logic; -- Global clock
|
|
||||||
phy_clk : in std_logic; -- PHY clock
|
|
||||||
rst : in std_logic; -- Asynchronous reset
|
|
||||||
|
|
||||||
-- Wishbone IF
|
|
||||||
wb_o : out wishbone_slave_out; -- Wishbone bus (out)
|
|
||||||
wb_i : in wishbone_slave_in; -- Wishbone bus (in)
|
|
||||||
|
|
||||||
-- Ethernet physical signals
|
|
||||||
rx_p : in std_logic;
|
|
||||||
tx_p : out std_logic;
|
|
||||||
tx_n : out std_logic;
|
|
||||||
-- LEDs
|
|
||||||
led_tx : out std_logic;
|
|
||||||
led_rx : out std_logic
|
|
||||||
);
|
|
||||||
end entity trashernet_phy_wb;
|
|
||||||
|
|
||||||
architecture RTL of trashernet_phy_wb is
|
|
||||||
-- PHY application interface
|
|
||||||
signal phy_out : phy_out_t; -- PHY application IF (out)
|
|
||||||
signal phy_in : phy_in_t; -- PHY application IF (in)
|
|
||||||
|
|
||||||
signal mac_out : raw_mac_out_t; -- MAC application IF (out)
|
|
||||||
signal mac_in : raw_mac_in_t; -- MAC application IF (in)
|
|
||||||
|
|
||||||
signal wb_adr : unsigned(2 downto 2);
|
|
||||||
|
|
||||||
signal status_register : std_logic_vector(31 downto 0);
|
|
||||||
|
|
||||||
signal rx_fifo_read : std_logic;
|
|
||||||
signal rx_fifo_data : std_logic_vector(7 downto 0);
|
|
||||||
|
|
||||||
signal tx_fifo_write : std_logic;
|
|
||||||
signal tx_fifo_commit : std_logic;
|
|
||||||
signal tx_fifo_empty : std_logic;
|
|
||||||
signal tx_fifo_data : std_logic_vector(7 downto 0);
|
|
||||||
|
|
||||||
signal rx_fifo_empty : std_logic;
|
|
||||||
signal rx_bitcount : std_logic_vector(10 downto 0);
|
|
||||||
signal rx_fifo_block_count : std_logic_vector(rx_bitcount'range);
|
|
||||||
signal rx_block_next : std_logic;
|
|
||||||
begin
|
|
||||||
trashernet_phy_inst : entity trashernet.trashernet_phy_cdc
|
|
||||||
generic map(
|
|
||||||
F_CLK => F_CLK,
|
|
||||||
F_CLK_PHY => F_CLK_PHY
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
phy_clk => phy_clk,
|
|
||||||
rst => rst,
|
|
||||||
phy_out => phy_out,
|
|
||||||
phy_in => phy_in,
|
|
||||||
rx_p => rx_p,
|
|
||||||
tx_p => tx_p,
|
|
||||||
tx_n => tx_n
|
|
||||||
);
|
|
||||||
|
|
||||||
trashernet_raw_mac_inst : entity trashernet.trashernet_raw_mac
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
phy_out => phy_out,
|
|
||||||
phy_in => phy_in,
|
|
||||||
mac_out => mac_out,
|
|
||||||
mac_in => mac_in
|
|
||||||
);
|
|
||||||
|
|
||||||
rx_fifo_inst : entity generics.fifo_block
|
|
||||||
generic map(
|
|
||||||
SIZE => 2047
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst_a => '0',
|
|
||||||
clr => rst,
|
|
||||||
data_in => mac_out.rx_mac_data,
|
|
||||||
write => mac_out.rx_mac_valid,
|
|
||||||
commit => mac_out.rx_mac_crc_ok,
|
|
||||||
abort => mac_out.rx_mac_crc_error,
|
|
||||||
full => open,
|
|
||||||
data_out => rx_fifo_data,
|
|
||||||
data_first => open,
|
|
||||||
empty => rx_fifo_empty,
|
|
||||||
read => rx_fifo_read,
|
|
||||||
usage => open
|
|
||||||
);
|
|
||||||
|
|
||||||
fifo_inst : entity generics.fifo
|
|
||||||
generic map(
|
|
||||||
SIZE => 31
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst_a => '0',
|
|
||||||
clr => rst,
|
|
||||||
data_in => rx_bitcount,
|
|
||||||
write => mac_out.rx_mac_crc_ok,
|
|
||||||
full => open,
|
|
||||||
data_out => rx_fifo_block_count,
|
|
||||||
empty => open,
|
|
||||||
read => rx_block_next,
|
|
||||||
usage => open
|
|
||||||
);
|
|
||||||
|
|
||||||
rxcount : process(rst, clk) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
rx_bitcount <= (others => '0');
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if mac_out.rx_mac_crc_error or mac_out.rx_mac_crc_ok then
|
|
||||||
rx_bitcount <= (others => '0');
|
|
||||||
elsif mac_out.rx_mac_valid then
|
|
||||||
rx_bitcount <= std_logic_vector(unsigned(rx_bitcount) + 1);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process rxcount;
|
|
||||||
tx_fifo_inst : entity generics.fifo_block
|
|
||||||
generic map(
|
|
||||||
SIZE => 2047
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst_a => '0',
|
|
||||||
clr => rst,
|
|
||||||
data_in => wb_i.dat(7 downto 0),
|
|
||||||
write => tx_fifo_write,
|
|
||||||
commit => tx_fifo_commit,
|
|
||||||
abort => '0',
|
|
||||||
full => open,
|
|
||||||
data_out => tx_fifo_data,
|
|
||||||
data_first => open,
|
|
||||||
empty => tx_fifo_empty,
|
|
||||||
read => mac_out.tx_mac_data_ack,
|
|
||||||
usage => open
|
|
||||||
);
|
|
||||||
|
|
||||||
wb_adr <= unsigned(wb_i.adr(wb_adr'range));
|
|
||||||
wbif : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
wb_o.ack <= '0';
|
|
||||||
rx_fifo_read <= '0';
|
|
||||||
tx_fifo_write <= '0';
|
|
||||||
tx_fifo_commit <= '0';
|
|
||||||
rx_block_next <= '0';
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
wb_o.ack <= '0';
|
|
||||||
rx_fifo_read <= '0';
|
|
||||||
tx_fifo_write <= '0';
|
|
||||||
tx_fifo_commit <= '0';
|
|
||||||
rx_block_next <= '0';
|
|
||||||
|
|
||||||
if (wb_i.cyc and wb_i.stb) then
|
|
||||||
wb_o.ack <= '1';
|
|
||||||
|
|
||||||
if wb_adr = 0 then
|
|
||||||
wb_o.dat <= status_register;
|
|
||||||
if wb_o.ack = '0' then
|
|
||||||
if wb_i.we = '1' then
|
|
||||||
tx_fifo_commit <= wb_i.dat(2);
|
|
||||||
rx_block_next <= wb_i.dat(1);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
wb_o.dat <= (others => '0');
|
|
||||||
|
|
||||||
if wb_o.ack = '0' then
|
|
||||||
if wb_i.we = '1' then
|
|
||||||
tx_fifo_write <= '1';
|
|
||||||
else
|
|
||||||
rx_fifo_read <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
wb_o.dat(7 downto 0) <= rx_fifo_data;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process wbif;
|
|
||||||
|
|
||||||
wb_o.err <= '0';
|
|
||||||
wb_o.rty <= '1';
|
|
||||||
wb_o.stall <= '0';
|
|
||||||
|
|
||||||
mac_in.tx_mac_data_en <= not tx_fifo_empty; -- FIXME: this does not care about inter-packet gaps indicated by `data_first`
|
|
||||||
mac_in.tx_mac_data <= tx_fifo_data;
|
|
||||||
|
|
||||||
status_register <= ("0" & x"0" & rx_fifo_block_count & -- 31..16
|
|
||||||
x"000" & "0" & (not tx_fifo_empty) & (not rx_fifo_empty) & phy_out.carrier_detect);
|
|
||||||
|
|
||||||
ledstretch : process(clk) is
|
|
||||||
constant CMAX : integer := integer(0.1 / (1.0 / real(F_CLK)));
|
|
||||||
constant CMIN : integer := -integer(0.1 / (1.0 / real(F_CLK)));
|
|
||||||
variable cnt : integer range CMIN to CMAX;
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if cnt = CMIN then
|
|
||||||
led_rx <= phy_out.carrier_detect;
|
|
||||||
if phy_out.rx_active then
|
|
||||||
cnt := CMAX;
|
|
||||||
led_rx <= not phy_out.carrier_detect;
|
|
||||||
end if;
|
|
||||||
elsif cnt = 0 then
|
|
||||||
led_rx <= phy_out.carrier_detect;
|
|
||||||
cnt := cnt - 1;
|
|
||||||
else
|
|
||||||
cnt := cnt - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process ledstretch;
|
|
||||||
|
|
||||||
ledstretch2 : process(clk) is
|
|
||||||
constant CMAX : integer := integer(0.1 / (1.0 / real(F_CLK)));
|
|
||||||
constant CMIN : integer := -integer(0.1 / (1.0 / real(F_CLK)));
|
|
||||||
variable cnt : integer range CMIN to CMAX;
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if cnt = CMIN then
|
|
||||||
if phy_out.tx_active then
|
|
||||||
cnt := CMAX;
|
|
||||||
led_tx <= '1';
|
|
||||||
end if;
|
|
||||||
elsif cnt = 0 then
|
|
||||||
led_tx <= '0';
|
|
||||||
cnt := cnt - 1;
|
|
||||||
else
|
|
||||||
cnt := cnt - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process ledstretch2;
|
|
||||||
end architecture RTL;
|
|
|
@ -1,125 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
-- ADDR0: RD: [...] TX_BUSY TX_DATA_FULL RX_DATA_EMPTY
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
library generics;
|
|
||||||
use generics.all;
|
|
||||||
use generics.wishbone_pkg.all;
|
|
||||||
|
|
||||||
entity uart_wb is
|
|
||||||
generic(
|
|
||||||
F_CLK : integer;
|
|
||||||
BAUD_RATE : integer := 115200
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk : in std_logic;
|
|
||||||
rst : in std_logic;
|
|
||||||
-- Wishbone IF
|
|
||||||
wb_o : out wishbone_slave_out; -- Wishbone bus (out)
|
|
||||||
wb_i : in wishbone_slave_in; -- Wishbone bus (in)
|
|
||||||
|
|
||||||
serial_out : out std_logic;
|
|
||||||
serial_in : in std_logic
|
|
||||||
);
|
|
||||||
end entity uart_wb;
|
|
||||||
|
|
||||||
architecture rtl of uart_wb is
|
|
||||||
signal wb_adr : unsigned(2 downto 0);
|
|
||||||
|
|
||||||
signal status_register : std_logic_vector(31 downto 0);
|
|
||||||
|
|
||||||
signal in_data : std_logic_vector(7 downto 0);
|
|
||||||
signal in_data_latched : std_logic_vector(in_data'range);
|
|
||||||
signal in_data_valid : std_logic;
|
|
||||||
signal in_data_available : std_logic;
|
|
||||||
|
|
||||||
signal out_data : std_logic_vector(in_data'range);
|
|
||||||
signal out_data_valid : std_logic;
|
|
||||||
signal out_data_latched : std_logic;
|
|
||||||
signal out_busy : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
uart_tx_inst : entity generics.uart_tx
|
|
||||||
generic map(
|
|
||||||
F_CLK => F_CLK,
|
|
||||||
BAUD_RATE => BAUD_RATE
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst_a => rst,
|
|
||||||
data => out_data,
|
|
||||||
data_valid => out_data_valid,
|
|
||||||
data_latched => out_data_latched,
|
|
||||||
busy => out_busy,
|
|
||||||
serial_out => serial_out
|
|
||||||
);
|
|
||||||
|
|
||||||
uart_rx_inst : entity generics.uart_rx
|
|
||||||
generic map(
|
|
||||||
F_CLK => F_CLK,
|
|
||||||
BAUD_RATE => BAUD_RATE
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst_a => rst,
|
|
||||||
data => in_data,
|
|
||||||
data_valid => in_data_valid,
|
|
||||||
serial_in_a => serial_in
|
|
||||||
);
|
|
||||||
|
|
||||||
wb_adr <= unsigned(wb_i.adr(wb_adr'range));
|
|
||||||
status_register <= x"000000" & "00000" & out_busy & out_data_valid & (not in_data_available);
|
|
||||||
|
|
||||||
wb_if : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
in_data_available <= '0';
|
|
||||||
out_data_valid <= '0';
|
|
||||||
wb_o.ack <= '0';
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
wb_o.ack <= '0';
|
|
||||||
|
|
||||||
if out_data_latched then
|
|
||||||
out_data_valid <= '0';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if (wb_i.CYC and wb_i.STB) then
|
|
||||||
wb_o.ack <= '1';
|
|
||||||
if wb_adr = 0 then -- status reg
|
|
||||||
wb_o.dat <= status_register;
|
|
||||||
else -- data reg (write to transmit, read to retrieve)
|
|
||||||
if wb_i.we then
|
|
||||||
out_data <= wb_i.dat(out_data'range);
|
|
||||||
out_data_valid <= '1';
|
|
||||||
else
|
|
||||||
wb_o.dat <= x"000000" & in_data_latched;
|
|
||||||
in_data_available <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if in_data_valid then
|
|
||||||
in_data_available <= '1';
|
|
||||||
in_data_latched <= in_data;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process wb_if;
|
|
||||||
|
|
||||||
wb_o.err <= '0';
|
|
||||||
wb_o.stall <= '0';
|
|
||||||
wb_o.rty <= '0';
|
|
||||||
|
|
||||||
end architecture rtl;
|
|
|
@ -1,176 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
use std.textio.all;
|
|
||||||
|
|
||||||
entity aps6404l is
|
|
||||||
generic(
|
|
||||||
LOG_EN : boolean := true
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
ce_n : in std_logic;
|
|
||||||
sclk : in std_logic;
|
|
||||||
sio : inout std_logic_vector(3 downto 0)
|
|
||||||
);
|
|
||||||
end entity aps6404l;
|
|
||||||
|
|
||||||
architecture bench of aps6404l is
|
|
||||||
procedure print(text : string) is
|
|
||||||
variable buf : line;
|
|
||||||
begin
|
|
||||||
if not LOG_EN then
|
|
||||||
return;
|
|
||||||
end if;
|
|
||||||
write(buf, string'("aps6404l: "));
|
|
||||||
write(buf, text);
|
|
||||||
WriteLine(OUTPUT, buf);
|
|
||||||
end procedure print;
|
|
||||||
|
|
||||||
begin
|
|
||||||
test : process is
|
|
||||||
type rx_state_t is (COMMAND, READ, WRITE, COMPLETE);
|
|
||||||
type byte_vector is array (natural range <>) of std_logic_vector(7 downto 0);
|
|
||||||
variable mem : byte_vector(0 to 1023);
|
|
||||||
variable bytes : byte_vector(0 to 32);
|
|
||||||
variable cnt, bytecnt : integer;
|
|
||||||
variable state : rx_state_t;
|
|
||||||
|
|
||||||
variable mode : integer := 0;
|
|
||||||
variable wrap_boundary : boolean := false;
|
|
||||||
|
|
||||||
variable dout : std_logic_vector(7 downto 0);
|
|
||||||
variable addr : integer;
|
|
||||||
|
|
||||||
variable sio_temp : std_logic_vector(sio'range);
|
|
||||||
|
|
||||||
procedure handle(command_edge : boolean) is
|
|
||||||
begin
|
|
||||||
if command_edge then
|
|
||||||
case state is
|
|
||||||
when COMMAND =>
|
|
||||||
case bytes(0) is
|
|
||||||
when x"66" =>
|
|
||||||
print(" SPI reset enter");
|
|
||||||
state := COMPLETE;
|
|
||||||
|
|
||||||
when x"99" =>
|
|
||||||
print(" SPI reset execute");
|
|
||||||
mode := 0;
|
|
||||||
wrap_boundary := false;
|
|
||||||
state := COMPLETE;
|
|
||||||
|
|
||||||
when x"35" =>
|
|
||||||
print(" QPI enter");
|
|
||||||
mode := 1;
|
|
||||||
state := COMPLETE;
|
|
||||||
|
|
||||||
when x"F5" =>
|
|
||||||
print(" QPI exit");
|
|
||||||
mode := 0;
|
|
||||||
state := COMPLETE;
|
|
||||||
|
|
||||||
when x"C0" =>
|
|
||||||
print(" Wrap Boundary Toggle");
|
|
||||||
wrap_boundary := not wrap_boundary;
|
|
||||||
state := COMPLETE;
|
|
||||||
|
|
||||||
when x"0B" =>
|
|
||||||
print(" QPI Read Slow");
|
|
||||||
state := READ;
|
|
||||||
|
|
||||||
when x"EB" =>
|
|
||||||
print(" QPI Read Fast");
|
|
||||||
state := READ;
|
|
||||||
|
|
||||||
when x"02" =>
|
|
||||||
print(" QPI Write (1)");
|
|
||||||
state := WRITE;
|
|
||||||
|
|
||||||
when x"38" =>
|
|
||||||
print(" QPI Write (2)");
|
|
||||||
state := WRITE;
|
|
||||||
|
|
||||||
when others =>
|
|
||||||
print(" Unknown command: 0x" & to_hstring(bytes(0)));
|
|
||||||
state := COMPLETE;
|
|
||||||
end case;
|
|
||||||
|
|
||||||
when READ =>
|
|
||||||
if bytecnt = 3 then
|
|
||||||
print(" Addr: " & to_hstring(bytes(1)) & to_hstring(bytes(2)) & to_hstring(bytes(3)));
|
|
||||||
addr := to_integer(unsigned(std_logic_vector'(bytes(1), bytes(2), bytes(3))));
|
|
||||||
elsif bytecnt > 4 then
|
|
||||||
dout := mem(addr);
|
|
||||||
print(" Read " & integer'image(addr) & ": " & to_hstring(mem(addr)));
|
|
||||||
addr := addr + 1;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when WRITE =>
|
|
||||||
if bytecnt = 3 then
|
|
||||||
print(" Addr: " & to_hstring(bytes(1)) & to_hstring(bytes(2)) & to_hstring(bytes(3)));
|
|
||||||
addr := to_integer(unsigned(std_logic_vector'(bytes(1), bytes(2), bytes(3))));
|
|
||||||
elsif bytecnt > 3 then
|
|
||||||
print(" Write " & integer'image(addr) & ": " & to_hstring(bytes(bytecnt)));
|
|
||||||
mem(addr) := bytes(bytecnt);
|
|
||||||
addr := addr + 1;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when COMPLETE =>
|
|
||||||
null;
|
|
||||||
end case;
|
|
||||||
|
|
||||||
bytecnt := bytecnt + 1;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if state = READ and bytecnt > 4 then
|
|
||||||
sio_temp := dout(7 downto 4) when command_edge else dout(3 downto 0);
|
|
||||||
sio <= sio_temp after 5 ns;
|
|
||||||
end if;
|
|
||||||
end procedure handle;
|
|
||||||
|
|
||||||
begin
|
|
||||||
sio <= (others => 'Z');
|
|
||||||
wait until ce_n = '0';
|
|
||||||
print("Selected.");
|
|
||||||
bytes := (others => (others => 'U'));
|
|
||||||
cnt := 0;
|
|
||||||
bytecnt := 0;
|
|
||||||
state := COMMAND;
|
|
||||||
loop
|
|
||||||
wait on sclk, ce_n;
|
|
||||||
|
|
||||||
if mode = 0 then -- SPI
|
|
||||||
if falling_edge(sclk) then
|
|
||||||
bytes(cnt / 8)(7 - (cnt mod 8)) := sio(0);
|
|
||||||
cnt := cnt + 1;
|
|
||||||
if cnt mod 4 = 0 then
|
|
||||||
handle(cnt mod 8 = 0);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
else -- QPI
|
|
||||||
if falling_edge(sclk) then
|
|
||||||
bytes(cnt / 2)((1 - (cnt mod 2) + 1) * 4 - 1 downto (1 - (cnt mod 2)) * 4) := sio;
|
|
||||||
cnt := cnt + 1;
|
|
||||||
end if;
|
|
||||||
if falling_edge(sclk) then
|
|
||||||
handle(cnt mod 2 = 0);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
exit when ce_n = '1';
|
|
||||||
end loop;
|
|
||||||
print("Deselected.");
|
|
||||||
end process test;
|
|
||||||
|
|
||||||
end architecture bench;
|
|
|
@ -1,106 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
use ieee.math_real.all;
|
|
||||||
|
|
||||||
entity fifo is
|
|
||||||
generic(
|
|
||||||
SIZE : integer := 15 -- Entries in the FIFO (of size data), SIZE=(n^2)-1 recommended
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
-- generic ports
|
|
||||||
clk : in std_logic; -- System clock
|
|
||||||
rst_a : in std_logic; -- Asynchronous reset
|
|
||||||
clr : in std_logic; -- Remove all entries
|
|
||||||
|
|
||||||
-- FIFO in
|
|
||||||
data_in : in std_logic_vector; -- Data input into FIFO
|
|
||||||
write : in std_logic; -- Data is latched when `data_in_valid and not full`
|
|
||||||
full : out std_logic; -- FIFO is full
|
|
||||||
|
|
||||||
-- FIFO out
|
|
||||||
data_out : out std_logic_vector; -- Data output from FIFO
|
|
||||||
empty : out std_logic; -- FIFO is empty. '0' means "data is available".
|
|
||||||
read : in std_logic; -- Acknowledge that `data_out` was read. The word is removed and next one shifted from FIFO when `read and not empty`.
|
|
||||||
|
|
||||||
-- FIFO meta
|
|
||||||
usage : out integer range 0 to SIZE -- Usage counter
|
|
||||||
);
|
|
||||||
end fifo;
|
|
||||||
|
|
||||||
architecture rtl of fifo is
|
|
||||||
constant MEMORY_WIDTH : integer := data_in'length;
|
|
||||||
subtype pointer_t is integer range 0 to SIZE - 1;
|
|
||||||
type memory_t is array (pointer_t) of std_logic_vector(MEMORY_WIDTH - 1 downto 0);
|
|
||||||
|
|
||||||
signal memory : memory_t;
|
|
||||||
signal read_pointer : pointer_t;
|
|
||||||
signal write_pointer : pointer_t;
|
|
||||||
signal read_pointer_last : pointer_t;
|
|
||||||
|
|
||||||
begin
|
|
||||||
fifo_p : process(rst_a, clk) is
|
|
||||||
variable succesful_read : std_logic;
|
|
||||||
variable succesful_write : std_logic;
|
|
||||||
variable write_pointer_next : pointer_t;
|
|
||||||
variable read_pointer_next : pointer_t;
|
|
||||||
begin
|
|
||||||
if rst_a then
|
|
||||||
read_pointer <= 0;
|
|
||||||
write_pointer <= 0;
|
|
||||||
read_pointer_last <= SIZE - 1;
|
|
||||||
usage <= 0;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
succesful_read := read and not empty;
|
|
||||||
succesful_write := write and (not full or succesful_read);
|
|
||||||
|
|
||||||
write_pointer_next := write_pointer;
|
|
||||||
read_pointer_next := read_pointer;
|
|
||||||
|
|
||||||
if succesful_read then
|
|
||||||
read_pointer_next := (read_pointer_next + 1) mod SIZE;
|
|
||||||
read_pointer_last <= read_pointer;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if succesful_write then
|
|
||||||
memory(write_pointer) <= data_in;
|
|
||||||
write_pointer_next := (write_pointer_next + 1) mod SIZE;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if succesful_write xor succesful_read then
|
|
||||||
if succesful_write then
|
|
||||||
usage <= usage + 1;
|
|
||||||
else
|
|
||||||
usage <= usage - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
read_pointer <= read_pointer_next;
|
|
||||||
write_pointer <= write_pointer_next;
|
|
||||||
|
|
||||||
if clr then
|
|
||||||
read_pointer <= 0;
|
|
||||||
write_pointer <= 0;
|
|
||||||
read_pointer_last <= SIZE - 1;
|
|
||||||
usage <= 0;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process fifo_p;
|
|
||||||
|
|
||||||
full <= '1' when read_pointer_last = write_pointer else '0';
|
|
||||||
empty <= '1' when (read_pointer = write_pointer) else '0';
|
|
||||||
|
|
||||||
data_out <= memory(read_pointer);
|
|
||||||
|
|
||||||
end rtl;
|
|
|
@ -1,127 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
-- Tech hint: Width of FIFO will be width of `data_in` + 1.
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
use ieee.math_real.all;
|
|
||||||
|
|
||||||
entity fifo_block is
|
|
||||||
generic(
|
|
||||||
SIZE : integer := 15 -- Entries in the FIFO (of size data), SIZE=(n^2)-1 recommended
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
-- generic ports
|
|
||||||
clk : in std_logic; -- System clock
|
|
||||||
rst_a : in std_logic; -- Asynchronous reset
|
|
||||||
clr : in std_logic; -- Remove all entries
|
|
||||||
|
|
||||||
-- FIFO in
|
|
||||||
data_in : in std_logic_vector; -- Data input into FIFO
|
|
||||||
write : in std_logic; -- Data is latched when `data_in_valid and not full`
|
|
||||||
commit : in std_logic; -- Finalize block
|
|
||||||
abort : in std_logic; -- Abort current block
|
|
||||||
full : out std_logic; -- FIFO is full
|
|
||||||
|
|
||||||
-- FIFO out
|
|
||||||
data_out : out std_logic_vector; -- Data output from FIFO
|
|
||||||
data_first : out std_logic; -- Currently visible word is first in packet
|
|
||||||
empty : out std_logic; -- FIFO is empty. '0' means "data is available".
|
|
||||||
read : in std_logic; -- Acknowledge that `data_out` was read. The word is removed and next one shifted from FIFO when `read and not empty`.
|
|
||||||
|
|
||||||
-- FIFO meta
|
|
||||||
usage : out integer range 0 to SIZE -- Usage counter
|
|
||||||
);
|
|
||||||
end fifo_block;
|
|
||||||
|
|
||||||
architecture rtl of fifo_block is
|
|
||||||
constant MEMORY_WIDTH : integer := data_in'length + 1;
|
|
||||||
subtype pointer_t is integer range 0 to SIZE - 1;
|
|
||||||
type memory_t is array (pointer_t) of std_logic_vector(MEMORY_WIDTH - 1 downto 0);
|
|
||||||
|
|
||||||
signal memory : memory_t;
|
|
||||||
signal read_pointer : pointer_t;
|
|
||||||
signal write_pointer : pointer_t;
|
|
||||||
signal read_pointer_last : pointer_t;
|
|
||||||
signal write_pointer_committed : pointer_t;
|
|
||||||
signal current_is_first : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
fifo : process(rst_a, clk) is
|
|
||||||
variable succesful_read : std_logic;
|
|
||||||
variable succesful_write : std_logic;
|
|
||||||
variable write_pointer_next : pointer_t;
|
|
||||||
variable read_pointer_next : pointer_t;
|
|
||||||
begin
|
|
||||||
if rst_a then
|
|
||||||
read_pointer <= 0;
|
|
||||||
write_pointer <= 0;
|
|
||||||
read_pointer_last <= SIZE - 1;
|
|
||||||
write_pointer_committed <= 0;
|
|
||||||
current_is_first <= '1';
|
|
||||||
usage <= 0;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
succesful_read := read and not empty;
|
|
||||||
succesful_write := write and (not full or succesful_read);
|
|
||||||
|
|
||||||
write_pointer_next := write_pointer;
|
|
||||||
read_pointer_next := read_pointer;
|
|
||||||
|
|
||||||
if succesful_read then
|
|
||||||
read_pointer_next := (read_pointer_next + 1) mod SIZE;
|
|
||||||
read_pointer_last <= read_pointer;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if succesful_write then
|
|
||||||
memory(write_pointer) <= current_is_first & data_in;
|
|
||||||
write_pointer_next := (write_pointer_next + 1) mod SIZE;
|
|
||||||
current_is_first <= '0';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if succesful_write xor succesful_read then
|
|
||||||
if succesful_write then
|
|
||||||
usage <= usage + 1;
|
|
||||||
else
|
|
||||||
usage <= usage - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if commit then
|
|
||||||
write_pointer_committed <= write_pointer;
|
|
||||||
current_is_first <= '1';
|
|
||||||
elsif abort then
|
|
||||||
write_pointer_next := write_pointer_committed;
|
|
||||||
current_is_first <= '1';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
read_pointer <= read_pointer_next;
|
|
||||||
write_pointer <= write_pointer_next;
|
|
||||||
|
|
||||||
if clr then
|
|
||||||
read_pointer <= 0;
|
|
||||||
write_pointer <= 0;
|
|
||||||
read_pointer_last <= SIZE - 1;
|
|
||||||
write_pointer_committed <= 0;
|
|
||||||
current_is_first <= '1';
|
|
||||||
usage <= 0;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process fifo;
|
|
||||||
|
|
||||||
full <= '1' when read_pointer_last = write_pointer else '0';
|
|
||||||
empty <= '1' when (read_pointer = write_pointer_committed) else '0';
|
|
||||||
|
|
||||||
data_out <= memory(read_pointer)(data_out'range);
|
|
||||||
data_first <= memory(read_pointer)(MEMORY_WIDTH - 1);
|
|
||||||
|
|
||||||
end rtl;
|
|
|
@ -1,125 +0,0 @@
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
|
|
||||||
package ice40_components is
|
|
||||||
component SB_PLL40_PAD
|
|
||||||
generic(
|
|
||||||
FEEDBACK_PATH : string;
|
|
||||||
DIVR : std_logic_vector(3 downto 0);
|
|
||||||
DIVF : std_logic_vector(6 downto 0);
|
|
||||||
DIVQ : std_logic_vector(2 downto 0);
|
|
||||||
FILTER_RANGE : std_logic_vector(2 downto 0)
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
RESETB : in std_logic;
|
|
||||||
BYPASS : in std_logic;
|
|
||||||
PACKAGEPIN : in std_logic;
|
|
||||||
PLLOUTCORE : out std_logic;
|
|
||||||
PLLOUTGLOBAL : out std_logic
|
|
||||||
);
|
|
||||||
end component SB_PLL40_PAD;
|
|
||||||
|
|
||||||
component SB_PLL40_2_PAD
|
|
||||||
generic(
|
|
||||||
FEEDBACK_PATH : string;
|
|
||||||
DIVR : std_logic_vector(3 downto 0);
|
|
||||||
DIVF : std_logic_vector(6 downto 0);
|
|
||||||
DIVQ : std_logic_vector(2 downto 0);
|
|
||||||
FILTER_RANGE : std_logic_vector(2 downto 0)
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
RESETB : in std_logic;
|
|
||||||
BYPASS : in std_logic;
|
|
||||||
PACKAGEPIN : in std_logic;
|
|
||||||
PLLOUTCOREA : out std_logic;
|
|
||||||
PLLOUTCOREB : out std_logic;
|
|
||||||
PLLOUTGLOBALA : out std_logic;
|
|
||||||
PLLOUTGLOBALB : out std_logic
|
|
||||||
);
|
|
||||||
end component SB_PLL40_2_PAD;
|
|
||||||
|
|
||||||
component SB_PLL40_2_CORE
|
|
||||||
generic(
|
|
||||||
FEEDBACK_PATH : string;
|
|
||||||
DIVR : std_logic_vector(3 downto 0);
|
|
||||||
DIVF : std_logic_vector(6 downto 0);
|
|
||||||
DIVQ : std_logic_vector(2 downto 0);
|
|
||||||
FILTER_RANGE : std_logic_vector(2 downto 0)
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
RESETB : in std_logic;
|
|
||||||
BYPASS : in std_logic;
|
|
||||||
REFERENCECLK : in std_logic;
|
|
||||||
PLLOUTCOREA : out std_logic;
|
|
||||||
PLLOUTCOREB : out std_logic
|
|
||||||
);
|
|
||||||
end component SB_PLL40_2_CORE;
|
|
||||||
|
|
||||||
component SB_PLL40_CORE
|
|
||||||
generic(
|
|
||||||
FEEDBACK_PATH : string := "SIMPLE";
|
|
||||||
-- DELAY_ADJUSTMENT_MODE_FEEDBACK : string := "FIXED";
|
|
||||||
-- DELAY_ADJUSTMENT_MODE_RELATIVE : string := "FIXED";
|
|
||||||
-- PLLOUT_SELECT : string := "GENCLK";
|
|
||||||
-- SHIFTREG_DIV_MODE : std_logic;
|
|
||||||
-- FDA_FEEDBACK : std_logic_vector(3 downto 0) := "1111";
|
|
||||||
-- FDA_RELATIVE : std_logic_vector(3 downto 0) := "1111";
|
|
||||||
DIVR : std_logic_vector(3 downto 0);
|
|
||||||
DIVF : std_logic_vector(6 downto 0);
|
|
||||||
DIVQ : std_logic_vector(2 downto 0);
|
|
||||||
FILTER_RANGE : std_logic_vector(2 downto 0)
|
|
||||||
-- ENABLE_ICEGATE : std_logic := '0';
|
|
||||||
-- TEST_MODE : std_logic := '0'
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
REFERENCECLK : in std_logic;
|
|
||||||
PLLOUTCORE : out std_logic;
|
|
||||||
PLLOUTGLOBAL : out std_logic;
|
|
||||||
-- EXTFEEDBACK : in std_logic;
|
|
||||||
-- DYNAMICDELAY : in std_logic_vector(7 downto 0);
|
|
||||||
LOCK : out std_logic;
|
|
||||||
BYPASS : in std_logic;
|
|
||||||
RESETB : in std_logic
|
|
||||||
-- LATCHINPUTVALUE : in std_logic;
|
|
||||||
-- SDO : out std_logic;
|
|
||||||
-- SDI : in std_logic;
|
|
||||||
-- SCLK : in std_logic
|
|
||||||
);
|
|
||||||
end component SB_PLL40_CORE;
|
|
||||||
|
|
||||||
component SB_HFOSC
|
|
||||||
generic(
|
|
||||||
CLKHF_DIV : string
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
CLKHFPU : in std_logic;
|
|
||||||
CLKHFEN : in std_logic;
|
|
||||||
CLKHF : out std_logic
|
|
||||||
);
|
|
||||||
end component SB_HFOSC;
|
|
||||||
|
|
||||||
COMPONENT SB_IO IS
|
|
||||||
GENERIC(
|
|
||||||
PIN_TYPE : std_logic_vector(5 downto 0) := "000000";
|
|
||||||
IO_STANDARD : string := "SB_LVDS_INPUT"
|
|
||||||
);
|
|
||||||
PORT(
|
|
||||||
PACKAGE_PIN : in std_logic;
|
|
||||||
LATCH_INPUT_VALUE : in std_logic;
|
|
||||||
CLOCK_ENABLE : in std_logic;
|
|
||||||
INPUT_CLK : in std_logic;
|
|
||||||
OUTPUT_CLK : in std_logic;
|
|
||||||
OUTPUT_ENABLE : in std_logic;
|
|
||||||
D_OUT_0 : in std_logic;
|
|
||||||
D_OUT_1 : in std_logic;
|
|
||||||
D_IN_0 : out std_logic;
|
|
||||||
D_IN_1 : out std_logic
|
|
||||||
);
|
|
||||||
END COMPONENT SB_IO;
|
|
||||||
|
|
||||||
component SB_GB
|
|
||||||
port(
|
|
||||||
USER_SIGNAL_TO_GLOBAL_BUFFER : in std_logic;
|
|
||||||
GLOBAL_BUFFER_OUTPUT : out std_logic);
|
|
||||||
end component;
|
|
||||||
end package ice40_components;
|
|
|
@ -1,55 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
entity synchronizer is
|
|
||||||
generic(
|
|
||||||
init_value : std_logic := '0'; -- Default value of all synchronized signals after reset (ignored when `init_value_v` is set)
|
|
||||||
init_value_v : std_logic_vector := ""; -- Set this reset the bits of the vector individually, leave "" to use `init_value` for all.
|
|
||||||
stages : natural := 2 -- Number of synchronizer flip flops per channel
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- Synchronizer clock
|
|
||||||
rst : in std_logic; -- Asynchronous reset
|
|
||||||
|
|
||||||
data_in_a : in std_logic_vector; -- Asynchronous signal input
|
|
||||||
data_out : out std_logic_vector -- Synchronized signal output
|
|
||||||
);
|
|
||||||
end entity synchronizer;
|
|
||||||
|
|
||||||
architecture rtl of synchronizer is
|
|
||||||
type synchronizer_chain_t is array (stages - 1 downto 0) of std_logic_vector(data_in_a'range);
|
|
||||||
signal synchronizer_chain : synchronizer_chain_t;
|
|
||||||
|
|
||||||
begin
|
|
||||||
assert ((init_value_v'length = 0) or (init_value_v'length = data_in_a'length)) report "init_value_v must have the same width as data_in_a when used" severity error;
|
|
||||||
|
|
||||||
sync_p : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if (rst = '1') then
|
|
||||||
if (init_value_v'length = 0) then
|
|
||||||
synchronizer_chain <= (others => (others => init_value));
|
|
||||||
else
|
|
||||||
synchronizer_chain <= (others => init_value_v);
|
|
||||||
end if;
|
|
||||||
|
|
||||||
elsif (rising_edge(clk)) then
|
|
||||||
for i in synchronizer_chain'high - 1 downto synchronizer_chain'low loop
|
|
||||||
synchronizer_chain(i + 1) <= synchronizer_chain(i);
|
|
||||||
end loop;
|
|
||||||
synchronizer_chain(0) <= data_in_a;
|
|
||||||
end if;
|
|
||||||
end process sync_p;
|
|
||||||
|
|
||||||
data_out <= synchronizer_chain(synchronizer_chain'high);
|
|
||||||
end architecture rtl;
|
|
|
@ -1,99 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
use ieee.math_real.all;
|
|
||||||
|
|
||||||
entity uart_rx is
|
|
||||||
generic(
|
|
||||||
F_CLK : natural := 50_000_000; -- System clock speed
|
|
||||||
BAUD_RATE : natural := 115_200 -- Desired baudrate
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- System clock @ F_CLK
|
|
||||||
rst_a : in std_logic; -- Asynchronous reset
|
|
||||||
|
|
||||||
data : out std_logic_vector; -- Receive payload word (width determines width of UART payload)
|
|
||||||
data_valid : out std_logic; -- Data is valid
|
|
||||||
|
|
||||||
serial_in_a : in std_logic -- UART RX line (asynchronous) @ BAUDRATE
|
|
||||||
);
|
|
||||||
end entity uart_rx;
|
|
||||||
|
|
||||||
architecture rtl of uart_rx is
|
|
||||||
signal serial_in : std_logic;
|
|
||||||
|
|
||||||
constant BITCLK_MAX : integer := integer(real(F_CLK) / real(BAUD_RATE));
|
|
||||||
constant BITCLK_START : integer := BITCLK_MAX / 2;
|
|
||||||
signal bitclk_cnt : integer range 0 to BITCLK_MAX;
|
|
||||||
signal bit_stb : std_logic;
|
|
||||||
|
|
||||||
constant BITCNT_MAX : integer := 10;
|
|
||||||
signal cnt : integer range 0 to BITCNT_MAX;
|
|
||||||
signal busy : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
synchronizer_rx_inst : entity work.synchronizer
|
|
||||||
generic map(
|
|
||||||
init_value => '1'
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst_a,
|
|
||||||
data_in_a(0) => serial_in_a,
|
|
||||||
data_out(0) => serial_in
|
|
||||||
);
|
|
||||||
|
|
||||||
rx : process(clk, rst_a) is
|
|
||||||
begin
|
|
||||||
if rst_a then
|
|
||||||
cnt <= 0;
|
|
||||||
data_valid <= '0';
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
data_valid <= '0';
|
|
||||||
|
|
||||||
if (cnt = 0 and serial_in = '0') or bit_stb = '1' then
|
|
||||||
if cnt = BITCNT_MAX then
|
|
||||||
cnt <= 0;
|
|
||||||
data_valid <= '1';
|
|
||||||
else
|
|
||||||
data <= serial_in & data(7 downto 1);
|
|
||||||
cnt <= cnt + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process rx;
|
|
||||||
busy <= '1' when cnt /= 0 else '0';
|
|
||||||
|
|
||||||
bitclk : process(clk, rst_a) is
|
|
||||||
begin
|
|
||||||
if rst_a then
|
|
||||||
bit_stb <= '0';
|
|
||||||
bitclk_cnt <= 0;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
bit_stb <= '0';
|
|
||||||
|
|
||||||
if not busy then
|
|
||||||
bitclk_cnt <= BITCLK_START;
|
|
||||||
else
|
|
||||||
if bitclk_cnt = 0 then
|
|
||||||
bitclk_cnt <= BITCLK_MAX;
|
|
||||||
bit_stb <= '1';
|
|
||||||
else
|
|
||||||
bitclk_cnt <= bitclk_cnt - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process bitclk;
|
|
||||||
end architecture rtl;
|
|
|
@ -1,96 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
use ieee.math_real.round;
|
|
||||||
|
|
||||||
entity uart_tx is
|
|
||||||
generic(
|
|
||||||
F_CLK : integer := 50_000_000; -- System clock speed
|
|
||||||
BAUD_RATE : integer := 115_200 -- Desired baudrate
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- System clock @ F_CLK
|
|
||||||
rst_a : in std_logic; -- Asynchronous reset
|
|
||||||
|
|
||||||
data : in std_logic_vector; -- Data to send (width determines width of UART payload)
|
|
||||||
data_valid : in std_logic; -- Data is valid, TX at next opportunity
|
|
||||||
|
|
||||||
data_latched : out std_logic; -- The data word has been latched, go ahead and apply the next one, or negate data_valid to end the transaction after the current word
|
|
||||||
busy : out std_logic; -- The core is busy transmitting a data word
|
|
||||||
serial_out : out std_logic -- UART TX line
|
|
||||||
);
|
|
||||||
end entity uart_tx;
|
|
||||||
|
|
||||||
architecture rtl of uart_tx is
|
|
||||||
constant COUNTER_MAX : natural := 10;
|
|
||||||
|
|
||||||
signal sr : std_logic_vector((data'length + 1) - 1 downto 0);
|
|
||||||
|
|
||||||
signal bit_cnt : integer range 0 to COUNTER_MAX;
|
|
||||||
|
|
||||||
constant BITCLK_MAX : integer := integer(real(F_CLK) / real(BAUD_RATE));
|
|
||||||
signal bitclk_cnt : integer range 0 to BITCLK_MAX;
|
|
||||||
signal bit_stb : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
tx_fsm : process(clk, rst_a) is
|
|
||||||
begin
|
|
||||||
if (rst_a = '1') then
|
|
||||||
sr <= (others => '1');
|
|
||||||
bit_cnt <= 0;
|
|
||||||
data_latched <= '0';
|
|
||||||
|
|
||||||
elsif (rising_edge(clk)) then
|
|
||||||
data_latched <= '0';
|
|
||||||
|
|
||||||
if ((bit_stb = '1') or (bit_cnt = 0)) then
|
|
||||||
sr <= '1' & sr(sr'high downto 1);
|
|
||||||
if (bit_cnt = 0) then
|
|
||||||
if (data_valid = '1') then
|
|
||||||
data_latched <= '1';
|
|
||||||
sr <= data & '0';
|
|
||||||
bit_cnt <= COUNTER_MAX;
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
bit_cnt <= bit_cnt - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process tx_fsm;
|
|
||||||
serial_out <= sr(0); -- @suppress PID1: Not a readback signal
|
|
||||||
|
|
||||||
busy <= '1' when (bit_cnt /= 0) or (data_valid = '1') else '0';
|
|
||||||
|
|
||||||
bitclk : process(clk, rst_a) is
|
|
||||||
begin
|
|
||||||
if rst_a then
|
|
||||||
bit_stb <= '0';
|
|
||||||
bitclk_cnt <= BITCLK_MAX;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
bit_stb <= '0';
|
|
||||||
|
|
||||||
if not busy then
|
|
||||||
bitclk_cnt <= BITCLK_MAX;
|
|
||||||
else
|
|
||||||
if bitclk_cnt = 0 then
|
|
||||||
bitclk_cnt <= BITCLK_MAX;
|
|
||||||
bit_stb <= '1';
|
|
||||||
else
|
|
||||||
bitclk_cnt <= bitclk_cnt - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process bitclk;
|
|
||||||
|
|
||||||
end architecture rtl;
|
|
|
@ -1,136 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
use work.wishbone_pkg.all;
|
|
||||||
|
|
||||||
entity wishbone_arbiter is
|
|
||||||
generic(
|
|
||||||
ASYNC : boolean := true; -- Generate the switch as a fully asynchronous circuit when false, register outputs when true.
|
|
||||||
NO_DEAD_SLAVE : boolean := true -- Connect to slave 0,0 on no address match (saves resources)
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk : in std_logic; -- System clock, must be shared with all slaves and masters.
|
|
||||||
rst : in std_logic; -- Asynchronous reset
|
|
||||||
|
|
||||||
-- Master connections (crossbar is a slave)
|
|
||||||
masters_o : in wishbone_slave_in_vector; -- Connections to masters (crossbar is slave), inputs to crossbar
|
|
||||||
masters_i : out wishbone_slave_out_vector; -- Connections to masters (crossbar is slave), outputs from crossbar
|
|
||||||
|
|
||||||
-- Slave connections (crossbar is a master)
|
|
||||||
slaves_o : in wishbone_master_in_vector; -- Connections to slaves (crossbar is master), inputs to crossbar
|
|
||||||
slaves_i : out wishbone_master_out_vector; -- Connections to slaves (crossbar is master), outputs from crossbar
|
|
||||||
|
|
||||||
-- Address configuration of the slaves connected
|
|
||||||
address : in wishbone_address_vector; -- Base address for each slave connection. Must be the same size as `master_i` and `master_o`
|
|
||||||
mask : in wishbone_address_vector -- Bit mask for slave base addresses. Must be the same size as `master_i` and `master_o`
|
|
||||||
);
|
|
||||||
end wishbone_arbiter;
|
|
||||||
|
|
||||||
architecture rtl of wishbone_arbiter is
|
|
||||||
subtype slave_index is integer range 0 to slaves_i'length - 1;
|
|
||||||
subtype master_index is integer range 0 to masters_i'length - 1;
|
|
||||||
|
|
||||||
signal slave_sel : slave_index;
|
|
||||||
signal master_sel : master_index;
|
|
||||||
signal matched : std_logic;
|
|
||||||
|
|
||||||
constant SLEEPY_MASTER : wishbone_master_out := (cyc => '0', stb => '0', adr => (others => '-'), sel => (others => '-'), we => '-', dat => (others => '-'));
|
|
||||||
constant SLEEPY_SLAVE : wishbone_slave_out := (ack => '0', err => '0', rty => '0', stall => '1', dat => (others => '-'));
|
|
||||||
|
|
||||||
procedure generate_logic(
|
|
||||||
signal mo : in wishbone_slave_in_vector;
|
|
||||||
signal so : in wishbone_master_in_vector;
|
|
||||||
signal ssel : out slave_index;
|
|
||||||
signal msel : out master_index;
|
|
||||||
signal mtch : out std_logic
|
|
||||||
) is
|
|
||||||
begin
|
|
||||||
ssel <= 0;
|
|
||||||
msel <= 0;
|
|
||||||
mtch <= '0';
|
|
||||||
master_loop : for master_id in mo'range loop
|
|
||||||
if (mo(master_id).cyc and mo(master_id).stb) then
|
|
||||||
slave_loop : for slave_id in so'range loop
|
|
||||||
if (mo(master_id).adr and mask(slave_id)) = address(slave_id) then
|
|
||||||
ssel <= slave_id;
|
|
||||||
msel <= master_id;
|
|
||||||
mtch <= '1';
|
|
||||||
exit master_loop;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
end procedure generate_logic;
|
|
||||||
|
|
||||||
procedure connect_slaves(
|
|
||||||
signal mo : in wishbone_slave_in_vector;
|
|
||||||
signal mi : out wishbone_slave_out_vector;
|
|
||||||
signal so : in wishbone_master_in_vector;
|
|
||||||
signal si : out wishbone_master_out_vector;
|
|
||||||
constant ssel : in slave_index;
|
|
||||||
constant msel : in master_index;
|
|
||||||
signal mtch : in std_logic
|
|
||||||
) is
|
|
||||||
begin
|
|
||||||
for slave_id in si'range loop
|
|
||||||
si(slave_id) <= SLEEPY_MASTER;
|
|
||||||
-- Always connect data path from selected master to *all* slave inputs
|
|
||||||
si(slave_id).dat <= mo(msel).dat;
|
|
||||||
si(slave_id).we <= mo(msel).we;
|
|
||||||
si(slave_id).sel <= mo(msel).sel;
|
|
||||||
si(slave_id).adr <= mo(msel).adr and (not mask(ssel));
|
|
||||||
if (mtch = '1' or NO_DEAD_SLAVE) and (slave_id = ssel) then -- If we are the currently active slave, then also connect these (else SLEEPY default)
|
|
||||||
si(slave_id).cyc <= mo(msel).cyc;
|
|
||||||
si(slave_id).stb <= mo(msel).stb;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
for master_id in mi'range loop
|
|
||||||
mi(master_id) <= SLEEPY_SLAVE;
|
|
||||||
-- Always connect data path from selected slave to *all* master inputs
|
|
||||||
mi(master_id).dat <= so(ssel).dat;
|
|
||||||
if (mtch = '1' or NO_DEAD_SLAVE) and (master_id = msel) then -- If we are the currently active master, also connect these (else SLEEPY default)
|
|
||||||
mi(master_id).ack <= so(ssel).ack;
|
|
||||||
mi(master_id).err <= so(ssel).err;
|
|
||||||
mi(master_id).rty <= so(ssel).rty;
|
|
||||||
mi(master_id).stall <= so(ssel).stall;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
end procedure connect_slaves;
|
|
||||||
|
|
||||||
begin
|
|
||||||
assert ASYNC = true report "Arbiter does not support ASYNC mode" severity failure;
|
|
||||||
|
|
||||||
sync : if ASYNC generate
|
|
||||||
name : process(masters_o, slaves_o, address, mask) is
|
|
||||||
begin
|
|
||||||
generate_logic(masters_o, slaves_o, slave_sel, master_sel, matched);
|
|
||||||
end process name;
|
|
||||||
|
|
||||||
else generate
|
|
||||||
sync_proc : process(rst, clk) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
slave_sel <= 0;
|
|
||||||
master_sel <= 0;
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
generate_logic(masters_o, slaves_o, slave_sel, master_sel, matched);
|
|
||||||
end if;
|
|
||||||
end process sync_proc;
|
|
||||||
end generate sync;
|
|
||||||
|
|
||||||
name : process(masters_o, slaves_o, slave_sel, master_sel, matched, mask) is
|
|
||||||
begin
|
|
||||||
connect_slaves(masters_o, masters_i, slaves_o, slaves_i, slave_sel, master_sel, matched);
|
|
||||||
end process name;
|
|
||||||
|
|
||||||
end rtl;
|
|
|
@ -1,51 +0,0 @@
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TODO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
package wishbone_pkg is
|
|
||||||
constant WISHBONE_ADDRESS_WIDTH : integer := 32;
|
|
||||||
constant WISHBONE_DATA_WIDTH : integer := 32;
|
|
||||||
|
|
||||||
subtype wishbone_address is std_logic_vector(WISHBONE_ADDRESS_WIDTH - 1 downto 0);
|
|
||||||
subtype wishbone_data is std_logic_vector(WISHBONE_DATA_WIDTH - 1 downto 0);
|
|
||||||
subtype wishbone_byte_select is std_logic_vector((WISHBONE_ADDRESS_WIDTH / 8) - 1 downto 0);
|
|
||||||
subtype wishbone_cycle_type is std_logic_vector(2 downto 0);
|
|
||||||
subtype wishbone_burst_type is std_logic_vector(1 downto 0);
|
|
||||||
|
|
||||||
type wishbone_master_out is record
|
|
||||||
cyc : std_logic;
|
|
||||||
stb : std_logic;
|
|
||||||
adr : wishbone_address;
|
|
||||||
sel : wishbone_byte_select;
|
|
||||||
we : std_logic;
|
|
||||||
dat : wishbone_data;
|
|
||||||
end record wishbone_master_out;
|
|
||||||
subtype wishbone_slave_in is wishbone_master_out;
|
|
||||||
|
|
||||||
type wishbone_slave_out is record
|
|
||||||
ack : std_logic;
|
|
||||||
err : std_logic;
|
|
||||||
rty : std_logic;
|
|
||||||
stall : std_logic;
|
|
||||||
dat : wishbone_data;
|
|
||||||
end record wishbone_slave_out;
|
|
||||||
subtype wishbone_master_in is wishbone_slave_out;
|
|
||||||
|
|
||||||
type wishbone_master_out_vector is array (natural range <>) of wishbone_master_out;
|
|
||||||
type wishbone_slave_out_vector is array (natural range <>) of wishbone_slave_out;
|
|
||||||
subtype wishbone_slave_in_vector is wishbone_master_out_vector;
|
|
||||||
subtype wishbone_master_in_vector is wishbone_slave_out_vector;
|
|
||||||
|
|
||||||
type wishbone_address_vector is array (natural range <>) of wishbone_address;
|
|
||||||
type wishbone_data_vector is array (natural range <>) of wishbone_data;
|
|
||||||
end wishbone_pkg;
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
files=`find bench/ design/ device_models/ generics/ -name *.vhd`
|
|
||||||
|
|
||||||
for file in $files; do
|
|
||||||
cp $file /tmp/t
|
|
||||||
cat /tmp/h /tmp/t > $file
|
|
||||||
done
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 086090046c98d31787af5e657ce0d4adbd5815f2
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 206332f3d1c1f5b704bad09b1380a8aed8b736aa
|
|
58
fpga/run.py
58
fpga/run.py
|
@ -1,58 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from vunit import VUnit
|
|
||||||
import os
|
|
||||||
import pathlib
|
|
||||||
import subprocess
|
|
||||||
import pathlib
|
|
||||||
|
|
||||||
libraries = {
|
|
||||||
# Design files
|
|
||||||
os.path.realpath(os.path.join(__file__, "..")) : {
|
|
||||||
"bench",
|
|
||||||
"design",
|
|
||||||
"device_models",
|
|
||||||
"generics",
|
|
||||||
"serv",
|
|
||||||
"trashernet"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
project_dir=pathlib.Path(__file__).parent.resolve()
|
|
||||||
|
|
||||||
libs = {}
|
|
||||||
|
|
||||||
vu = VUnit.from_argv(compile_builtins=False)
|
|
||||||
vu.add_vhdl_builtins()
|
|
||||||
|
|
||||||
for base_path in libraries:
|
|
||||||
for library_name in libraries[base_path]:
|
|
||||||
libs[library_name] = vu.add_library(library_name)
|
|
||||||
|
|
||||||
if type(libraries[base_path]) is dict: # Manually specified files
|
|
||||||
print("direct")
|
|
||||||
for filename in libraries[base_path][library_name]:
|
|
||||||
libs[library_name].add_source_files(os.path.join(base_path, filename))
|
|
||||||
else: # Auto-detect files
|
|
||||||
print(f"Importing: {library_name}")
|
|
||||||
if library_name == "trashernet": # Special case: Trashernet submodule
|
|
||||||
path = os.path.join(base_path, "hdl", library_name, library_name, "*.vhd")
|
|
||||||
libs[library_name].add_source_files(path)
|
|
||||||
elif library_name == "serv": # Special case: SERV submodule
|
|
||||||
print("Skipping SERV. It's Verilog.")
|
|
||||||
else: # Normal lib
|
|
||||||
path = os.path.join(base_path, "hdl", library_name)
|
|
||||||
if os.path.exists(path):
|
|
||||||
path=os.path.join(path, "*.vhd")
|
|
||||||
libs[library_name].add_source_files(path)
|
|
||||||
|
|
||||||
# If we don't already use our own OSVVM implementation, add the default one.
|
|
||||||
if not "osvvm" in libs:
|
|
||||||
vu.add_osvvm()
|
|
||||||
|
|
||||||
vu.add_compile_option("ghdl.a_flags", ["-frelaxed", "-fsynopsys"])
|
|
||||||
vu.add_compile_option("nvc.a_flags", ["--relaxed"])
|
|
||||||
#vu.set_sim_option("nvc.elab_flags", ["-O3"])
|
|
||||||
vu.set_sim_option("nvc.sim_flags", ["--format=fst", "--wave=wave.fst"])
|
|
||||||
|
|
||||||
vu.main()
|
|
|
@ -1,56 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from vunit import VUnit
|
|
||||||
import os
|
|
||||||
import pathlib
|
|
||||||
import subprocess
|
|
||||||
import pathlib
|
|
||||||
|
|
||||||
libraries = {
|
|
||||||
# Design files
|
|
||||||
os.path.realpath(os.path.join(__file__, "..")) : {
|
|
||||||
"design",
|
|
||||||
"device_models",
|
|
||||||
"generics",
|
|
||||||
"serv",
|
|
||||||
"trashernet"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
project_dir=pathlib.Path(__file__).parent.resolve()
|
|
||||||
|
|
||||||
libs = {}
|
|
||||||
|
|
||||||
vu = VUnit.from_argv(compile_builtins=False)
|
|
||||||
#vu.add_vhdl_builtins()
|
|
||||||
|
|
||||||
for base_path in libraries:
|
|
||||||
for library_name in libraries[base_path]:
|
|
||||||
libs[library_name] = vu.add_library(library_name)
|
|
||||||
|
|
||||||
if type(libraries[base_path]) is dict: # Manually specified files
|
|
||||||
print("direct")
|
|
||||||
for filename in libraries[base_path][library_name]:
|
|
||||||
libs[library_name].add_source_files(os.path.join(base_path, filename))
|
|
||||||
else: # Auto-detect files
|
|
||||||
print(f"Importing: {library_name}")
|
|
||||||
if library_name == "trashernet": # Special case: Trashernet submodule
|
|
||||||
path = os.path.join(base_path, "hdl", library_name, library_name, "*.vhd")
|
|
||||||
libs[library_name].add_source_files(path)
|
|
||||||
elif library_name == "serv": # Special case: SERV submodule
|
|
||||||
print("Skipping SERV. It's Verilog.")
|
|
||||||
else: # Normal lib
|
|
||||||
path = os.path.join(base_path, "hdl", library_name)
|
|
||||||
if os.path.exists(path):
|
|
||||||
path=os.path.join(path, "*.vhd")
|
|
||||||
libs[library_name].add_source_files(path)
|
|
||||||
|
|
||||||
# If we don't already use our own OSVVM implementation, add the default one.
|
|
||||||
#if not "osvvm" in libs:
|
|
||||||
# vu.add_osvvm()
|
|
||||||
|
|
||||||
vu.add_compile_option("ghdl.a_flags", ["-frelaxed", "-fsynopsys"])
|
|
||||||
vu.add_compile_option("nvc.a_flags", ["--relaxed"])
|
|
||||||
#vu.set_sim_option("nvc.elab_flags", ["-O3"])
|
|
||||||
|
|
||||||
vu.main()
|
|
|
@ -4,6 +4,13 @@
|
||||||
(generator_version "8.0")
|
(generator_version "8.0")
|
||||||
(uuid "50245fe9-16a2-46fe-8648-51ebfd485de2")
|
(uuid "50245fe9-16a2-46fe-8648-51ebfd485de2")
|
||||||
(paper "A4")
|
(paper "A4")
|
||||||
|
(title_block
|
||||||
|
(title "Trashernet SoC")
|
||||||
|
(date "2024-07-07")
|
||||||
|
(rev "2")
|
||||||
|
(company "notsyncing.net")
|
||||||
|
(comment 1 "https://l.notsyncing.net/tnet")
|
||||||
|
)
|
||||||
(lib_symbols
|
(lib_symbols
|
||||||
(symbol "Device:C"
|
(symbol "Device:C"
|
||||||
(pin_numbers hide)
|
(pin_numbers hide)
|
||||||
|
@ -2464,6 +2471,17 @@
|
||||||
)
|
)
|
||||||
(uuid "fcfe9b21-6439-4517-bc6a-f6b7dde83736")
|
(uuid "fcfe9b21-6439-4517-bc6a-f6b7dde83736")
|
||||||
)
|
)
|
||||||
|
(text "TODO: Power supply ramping is too fast for iCE40 devices.\nThis will (randomly) cause 100 mA of \"leakage current\".\nAlso, this violates the required power supply sequencing."
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(at 72.644 66.548 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
(color 255 0 0 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(uuid "60bf2dd2-aa9a-460c-aecf-3ce8f474812e")
|
||||||
|
)
|
||||||
(symbol
|
(symbol
|
||||||
(lib_id "power:+5V")
|
(lib_id "power:+5V")
|
||||||
(at 80.01 38.1 0)
|
(at 80.01 38.1 0)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,13 @@
|
||||||
(generator_version "8.0")
|
(generator_version "8.0")
|
||||||
(uuid "6f17954a-662c-4681-9d8a-117fc0975850")
|
(uuid "6f17954a-662c-4681-9d8a-117fc0975850")
|
||||||
(paper "A4")
|
(paper "A4")
|
||||||
|
(title_block
|
||||||
|
(title "Trashernet SoC")
|
||||||
|
(date "2024-07-07")
|
||||||
|
(rev "2")
|
||||||
|
(company "notsyncing.net")
|
||||||
|
(comment 1 "https://l.notsyncing.net/tnet")
|
||||||
|
)
|
||||||
(lib_symbols
|
(lib_symbols
|
||||||
(symbol "Connector:RJ45_Amphenol_RJMG1BD3B8K1ANR"
|
(symbol "Connector:RJ45_Amphenol_RJMG1BD3B8K1ANR"
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
|
@ -4602,6 +4609,12 @@
|
||||||
(color 0 0 0 0)
|
(color 0 0 0 0)
|
||||||
(uuid "261ce2bc-286e-4eec-83c1-db0778273d59")
|
(uuid "261ce2bc-286e-4eec-83c1-db0778273d59")
|
||||||
)
|
)
|
||||||
|
(junction
|
||||||
|
(at 194.31 130.81)
|
||||||
|
(diameter 0)
|
||||||
|
(color 0 0 0 0)
|
||||||
|
(uuid "28945ddd-ab60-4b42-be94-5eab2c7d3d74")
|
||||||
|
)
|
||||||
(junction
|
(junction
|
||||||
(at 33.02 151.13)
|
(at 33.02 151.13)
|
||||||
(diameter 0)
|
(diameter 0)
|
||||||
|
@ -4674,12 +4687,6 @@
|
||||||
(color 0 0 0 0)
|
(color 0 0 0 0)
|
||||||
(uuid "fa6bfac9-47bb-453a-bdc4-b901db28eab8")
|
(uuid "fa6bfac9-47bb-453a-bdc4-b901db28eab8")
|
||||||
)
|
)
|
||||||
(junction
|
|
||||||
(at 194.31 102.87)
|
|
||||||
(diameter 0)
|
|
||||||
(color 0 0 0 0)
|
|
||||||
(uuid "fc96b561-289f-459e-9965-d5ceec93cb24")
|
|
||||||
)
|
|
||||||
(junction
|
(junction
|
||||||
(at 106.68 69.85)
|
(at 106.68 69.85)
|
||||||
(diameter 0)
|
(diameter 0)
|
||||||
|
@ -4926,7 +4933,7 @@
|
||||||
)
|
)
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 194.31 129.54) (xy 194.31 132.08)
|
(xy 189.23 97.79) (xy 189.23 100.33)
|
||||||
)
|
)
|
||||||
(stroke
|
(stroke
|
||||||
(width 0)
|
(width 0)
|
||||||
|
@ -4964,6 +4971,16 @@
|
||||||
)
|
)
|
||||||
(uuid "1ddf6e54-a484-48cb-b03d-d61f25ed9504")
|
(uuid "1ddf6e54-a484-48cb-b03d-d61f25ed9504")
|
||||||
)
|
)
|
||||||
|
(wire
|
||||||
|
(pts
|
||||||
|
(xy 194.31 133.35) (xy 200.66 133.35)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(uuid "1e0e5f00-3b05-4db3-9f85-96466ce1082e")
|
||||||
|
)
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 106.68 77.47) (xy 121.92 77.47)
|
(xy 106.68 77.47) (xy 121.92 77.47)
|
||||||
|
@ -5064,6 +5081,16 @@
|
||||||
)
|
)
|
||||||
(uuid "2b07da13-08e9-4826-a6f6-c3ee65fa4214")
|
(uuid "2b07da13-08e9-4826-a6f6-c3ee65fa4214")
|
||||||
)
|
)
|
||||||
|
(wire
|
||||||
|
(pts
|
||||||
|
(xy 189.23 97.79) (xy 194.31 97.79)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(uuid "2cdb962f-f874-46d9-bbdc-69b9e6de0b0e")
|
||||||
|
)
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 67.31 113.03) (xy 69.85 113.03)
|
(xy 67.31 113.03) (xy 69.85 113.03)
|
||||||
|
@ -5076,7 +5103,7 @@
|
||||||
)
|
)
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 185.42 102.87) (xy 182.88 102.87)
|
(xy 185.42 130.81) (xy 182.88 130.81)
|
||||||
)
|
)
|
||||||
(stroke
|
(stroke
|
||||||
(width 0)
|
(width 0)
|
||||||
|
@ -5174,16 +5201,6 @@
|
||||||
)
|
)
|
||||||
(uuid "3799491b-d693-44a3-9270-8ede3eadeead")
|
(uuid "3799491b-d693-44a3-9270-8ede3eadeead")
|
||||||
)
|
)
|
||||||
(wire
|
|
||||||
(pts
|
|
||||||
(xy 193.04 102.87) (xy 194.31 102.87)
|
|
||||||
)
|
|
||||||
(stroke
|
|
||||||
(width 0)
|
|
||||||
(type default)
|
|
||||||
)
|
|
||||||
(uuid "389dce51-7411-4289-bb71-2733ca90d344")
|
|
||||||
)
|
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 58.42 113.03) (xy 58.42 124.46)
|
(xy 58.42 113.03) (xy 58.42 124.46)
|
||||||
|
@ -5484,6 +5501,16 @@
|
||||||
)
|
)
|
||||||
(uuid "68aeeca0-dbf0-4ac5-a6a7-33953eac8e73")
|
(uuid "68aeeca0-dbf0-4ac5-a6a7-33953eac8e73")
|
||||||
)
|
)
|
||||||
|
(wire
|
||||||
|
(pts
|
||||||
|
(xy 194.31 129.54) (xy 194.31 130.81)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(uuid "6b7b4e9f-2f7c-4fe5-80d0-5c8fb93ccc2d")
|
||||||
|
)
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 223.52 99.06) (xy 233.68 99.06)
|
(xy 223.52 99.06) (xy 233.68 99.06)
|
||||||
|
@ -5494,6 +5521,16 @@
|
||||||
)
|
)
|
||||||
(uuid "6ba4c6ac-2bc9-4a50-aed9-b95f9c568999")
|
(uuid "6ba4c6ac-2bc9-4a50-aed9-b95f9c568999")
|
||||||
)
|
)
|
||||||
|
(wire
|
||||||
|
(pts
|
||||||
|
(xy 193.04 130.81) (xy 194.31 130.81)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(uuid "6c39451f-f9a6-45fb-af50-8ccccab0d0b4")
|
||||||
|
)
|
||||||
(polyline
|
(polyline
|
||||||
(pts
|
(pts
|
||||||
(xy 219.71 93.98) (xy 223.52 93.98)
|
(xy 219.71 93.98) (xy 223.52 93.98)
|
||||||
|
@ -5744,16 +5781,6 @@
|
||||||
)
|
)
|
||||||
(uuid "87028265-d61c-4256-afde-06187db5f018")
|
(uuid "87028265-d61c-4256-afde-06187db5f018")
|
||||||
)
|
)
|
||||||
(wire
|
|
||||||
(pts
|
|
||||||
(xy 194.31 101.6) (xy 194.31 102.87)
|
|
||||||
)
|
|
||||||
(stroke
|
|
||||||
(width 0)
|
|
||||||
(type default)
|
|
||||||
)
|
|
||||||
(uuid "8c7ae453-2af4-4d62-8539-7992572d7c7a")
|
|
||||||
)
|
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 69.85 124.46) (xy 69.85 127)
|
(xy 69.85 124.46) (xy 69.85 127)
|
||||||
|
@ -5894,6 +5921,26 @@
|
||||||
)
|
)
|
||||||
(uuid "9d1495ee-29e1-4ca3-94c1-a62fc85a7d15")
|
(uuid "9d1495ee-29e1-4ca3-94c1-a62fc85a7d15")
|
||||||
)
|
)
|
||||||
|
(wire
|
||||||
|
(pts
|
||||||
|
(xy 194.31 130.81) (xy 194.31 133.35)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(uuid "a05a28a0-d79b-4b56-84d4-7a1de793f622")
|
||||||
|
)
|
||||||
|
(wire
|
||||||
|
(pts
|
||||||
|
(xy 200.66 133.35) (xy 200.66 130.81)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(uuid "a4f8b6be-651d-4e43-8be5-133fb9f8df72")
|
||||||
|
)
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 139.7 80.01) (xy 139.7 81.28)
|
(xy 139.7 80.01) (xy 139.7 81.28)
|
||||||
|
@ -6016,7 +6063,7 @@
|
||||||
)
|
)
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 194.31 102.87) (xy 194.31 104.14)
|
(xy 194.31 97.79) (xy 194.31 104.14)
|
||||||
)
|
)
|
||||||
(stroke
|
(stroke
|
||||||
(width 0)
|
(width 0)
|
||||||
|
@ -6266,7 +6313,7 @@
|
||||||
)
|
)
|
||||||
(wire
|
(wire
|
||||||
(pts
|
(pts
|
||||||
(xy 182.88 102.87) (xy 182.88 105.41)
|
(xy 182.88 130.81) (xy 182.88 133.35)
|
||||||
)
|
)
|
||||||
(stroke
|
(stroke
|
||||||
(width 0)
|
(width 0)
|
||||||
|
@ -6526,7 +6573,7 @@
|
||||||
)
|
)
|
||||||
(uuid "1da93ede-0ae8-4a68-8941-d61f3d871d57")
|
(uuid "1da93ede-0ae8-4a68-8941-d61f3d871d57")
|
||||||
)
|
)
|
||||||
(label "CLK_12M"
|
(label "CLK_50M"
|
||||||
(at 129.54 175.26 0)
|
(at 129.54 175.26 0)
|
||||||
(fields_autoplaced yes)
|
(fields_autoplaced yes)
|
||||||
(effects
|
(effects
|
||||||
|
@ -6944,7 +6991,7 @@
|
||||||
)
|
)
|
||||||
(uuid "b29a2984-e3e7-4487-a331-bb8e576b641e")
|
(uuid "b29a2984-e3e7-4487-a331-bb8e576b641e")
|
||||||
)
|
)
|
||||||
(label "CLK_12M"
|
(label "CLK_50M"
|
||||||
(at 88.9 185.42 180)
|
(at 88.9 185.42 180)
|
||||||
(fields_autoplaced yes)
|
(fields_autoplaced yes)
|
||||||
(effects
|
(effects
|
||||||
|
@ -7264,7 +7311,7 @@
|
||||||
)
|
)
|
||||||
(symbol
|
(symbol
|
||||||
(lib_id "power:GND")
|
(lib_id "power:GND")
|
||||||
(at 182.88 105.41 0)
|
(at 182.88 133.35 0)
|
||||||
(unit 1)
|
(unit 1)
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(in_bom yes)
|
(in_bom yes)
|
||||||
|
@ -7273,7 +7320,7 @@
|
||||||
(fields_autoplaced yes)
|
(fields_autoplaced yes)
|
||||||
(uuid "094f2d05-80f5-414e-b1f1-87530da413db")
|
(uuid "094f2d05-80f5-414e-b1f1-87530da413db")
|
||||||
(property "Reference" "#PWR026"
|
(property "Reference" "#PWR026"
|
||||||
(at 182.88 111.76 0)
|
(at 182.88 139.7 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7282,7 +7329,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "GND"
|
(property "Value" "GND"
|
||||||
(at 182.88 110.49 0)
|
(at 182.88 138.43 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7290,7 +7337,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Footprint" ""
|
(property "Footprint" ""
|
||||||
(at 182.88 105.41 0)
|
(at 182.88 133.35 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7299,7 +7346,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Datasheet" ""
|
(property "Datasheet" ""
|
||||||
(at 182.88 105.41 0)
|
(at 182.88 133.35 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7308,7 +7355,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Description" "Power symbol creates a global label with name \"GND\" , ground"
|
(property "Description" "Power symbol creates a global label with name \"GND\" , ground"
|
||||||
(at 182.88 105.41 0)
|
(at 182.88 133.35 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7865,7 +7912,7 @@
|
||||||
)
|
)
|
||||||
(symbol
|
(symbol
|
||||||
(lib_id "power:GND")
|
(lib_id "power:GND")
|
||||||
(at 194.31 132.08 0)
|
(at 189.23 100.33 0)
|
||||||
(unit 1)
|
(unit 1)
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(in_bom yes)
|
(in_bom yes)
|
||||||
|
@ -7874,7 +7921,7 @@
|
||||||
(fields_autoplaced yes)
|
(fields_autoplaced yes)
|
||||||
(uuid "2378d86e-41ed-42d0-9a10-9701062fdbcf")
|
(uuid "2378d86e-41ed-42d0-9a10-9701062fdbcf")
|
||||||
(property "Reference" "#PWR021"
|
(property "Reference" "#PWR021"
|
||||||
(at 194.31 138.43 0)
|
(at 189.23 106.68 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7883,7 +7930,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "GND"
|
(property "Value" "GND"
|
||||||
(at 194.31 137.16 0)
|
(at 189.23 105.41 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7891,7 +7938,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Footprint" ""
|
(property "Footprint" ""
|
||||||
(at 194.31 132.08 0)
|
(at 189.23 100.33 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7900,7 +7947,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Datasheet" ""
|
(property "Datasheet" ""
|
||||||
(at 194.31 132.08 0)
|
(at 189.23 100.33 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -7909,7 +7956,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Description" "Power symbol creates a global label with name \"GND\" , ground"
|
(property "Description" "Power symbol creates a global label with name \"GND\" , ground"
|
||||||
(at 194.31 132.08 0)
|
(at 189.23 100.33 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -8808,16 +8855,15 @@
|
||||||
)
|
)
|
||||||
(symbol
|
(symbol
|
||||||
(lib_id "power:+3V3")
|
(lib_id "power:+3V3")
|
||||||
(at 194.31 101.6 0)
|
(at 200.66 130.81 0)
|
||||||
(unit 1)
|
(unit 1)
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(in_bom yes)
|
(in_bom yes)
|
||||||
(on_board yes)
|
(on_board yes)
|
||||||
(dnp no)
|
(dnp no)
|
||||||
(fields_autoplaced yes)
|
|
||||||
(uuid "666c8d73-fbc3-46d1-9981-ad87f3930f90")
|
(uuid "666c8d73-fbc3-46d1-9981-ad87f3930f90")
|
||||||
(property "Reference" "#PWR023"
|
(property "Reference" "#PWR023"
|
||||||
(at 194.31 105.41 0)
|
(at 200.66 134.62 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -8826,15 +8872,16 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "+3V3"
|
(property "Value" "+3V3"
|
||||||
(at 194.31 96.52 0)
|
(at 194.31 129.54 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
)
|
)
|
||||||
|
(justify left)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Footprint" ""
|
(property "Footprint" ""
|
||||||
(at 194.31 101.6 0)
|
(at 200.66 130.81 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -8843,7 +8890,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Datasheet" ""
|
(property "Datasheet" ""
|
||||||
(at 194.31 101.6 0)
|
(at 200.66 130.81 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -8852,7 +8899,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Description" "Power symbol creates a global label with name \"+3V3\""
|
(property "Description" "Power symbol creates a global label with name \"+3V3\""
|
||||||
(at 194.31 101.6 0)
|
(at 200.66 130.81 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -9306,7 +9353,7 @@
|
||||||
)
|
)
|
||||||
(symbol
|
(symbol
|
||||||
(lib_id "Device:C")
|
(lib_id "Device:C")
|
||||||
(at 189.23 102.87 90)
|
(at 189.23 130.81 90)
|
||||||
(unit 1)
|
(unit 1)
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(in_bom yes)
|
(in_bom yes)
|
||||||
|
@ -9314,7 +9361,7 @@
|
||||||
(dnp no)
|
(dnp no)
|
||||||
(uuid "78d4edae-aade-4399-996c-c47ea7795f31")
|
(uuid "78d4edae-aade-4399-996c-c47ea7795f31")
|
||||||
(property "Reference" "C12"
|
(property "Reference" "C12"
|
||||||
(at 189.23 97.028 90)
|
(at 189.23 136.398 90)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -9322,7 +9369,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "100n"
|
(property "Value" "100n"
|
||||||
(at 189.23 99.314 90)
|
(at 189.23 134.366 90)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -9330,7 +9377,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Footprint" "Capacitor_SMD:C_0603_1608Metric"
|
(property "Footprint" "Capacitor_SMD:C_0603_1608Metric"
|
||||||
(at 193.04 101.9048 0)
|
(at 193.04 129.8448 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -9339,7 +9386,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Datasheet" "~"
|
(property "Datasheet" "~"
|
||||||
(at 189.23 102.87 0)
|
(at 189.23 130.81 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -9348,7 +9395,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Description" "Unpolarized capacitor"
|
(property "Description" "Unpolarized capacitor"
|
||||||
(at 189.23 102.87 0)
|
(at 189.23 130.81 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
|
@ -11605,7 +11652,7 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "12MHz"
|
(property "Value" "50MHz"
|
||||||
(at 72.898 179.07 0)
|
(at 72.898 179.07 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
|
|
|
@ -4,6 +4,13 @@
|
||||||
(generator_version "8.0")
|
(generator_version "8.0")
|
||||||
(uuid "d7368bdd-94df-4bcb-8823-60f77936df1c")
|
(uuid "d7368bdd-94df-4bcb-8823-60f77936df1c")
|
||||||
(paper "A4")
|
(paper "A4")
|
||||||
|
(title_block
|
||||||
|
(title "Trashernet SoC")
|
||||||
|
(date "2024-07-07")
|
||||||
|
(rev "2")
|
||||||
|
(company "notsyncing.net")
|
||||||
|
(comment 1 "https://l.notsyncing.net/tnet")
|
||||||
|
)
|
||||||
(lib_symbols
|
(lib_symbols
|
||||||
(symbol "Connector:USB_B_Micro"
|
(symbol "Connector:USB_B_Micro"
|
||||||
(pin_names
|
(pin_names
|
||||||
|
|
4
sw/bootrom/.gitignore
vendored
4
sw/bootrom/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
||||||
*.bin
|
|
||||||
*.elf
|
|
||||||
*.hex
|
|
||||||
*.vhex
|
|
|
@ -1,45 +0,0 @@
|
||||||
__heap_size = 0x80;
|
|
||||||
__stack_size = 0x80;
|
|
||||||
|
|
||||||
MEMORY
|
|
||||||
{
|
|
||||||
ROM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x100
|
|
||||||
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x400
|
|
||||||
}
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
.text :
|
|
||||||
{
|
|
||||||
*(.boot)
|
|
||||||
*(.text)
|
|
||||||
*(.text)
|
|
||||||
*(.rodata*)
|
|
||||||
} > ROM
|
|
||||||
.data :
|
|
||||||
{
|
|
||||||
*(.sbss)
|
|
||||||
*(.data)
|
|
||||||
*(.bss)
|
|
||||||
*(.rela*)
|
|
||||||
*(COMMON)
|
|
||||||
} > RAM
|
|
||||||
|
|
||||||
.heap :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE ( end = . );
|
|
||||||
_sheap = .;
|
|
||||||
. = . + __heap_size;
|
|
||||||
. = ALIGN(4);
|
|
||||||
_eheap = .;
|
|
||||||
} >RAM
|
|
||||||
|
|
||||||
.stack :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
_estack = .;
|
|
||||||
. = . + __stack_size;
|
|
||||||
. = ALIGN(4);
|
|
||||||
_sstack = .;
|
|
||||||
} >RAM
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
riscv64-elf-gcc -mabi=ilp32 -march=rv32i -nostdlib -nostartfiles -ffreestanding -T boot.ld -Os -o bootrom.elf main.c
|
|
||||||
#riscv64-elf-objdump -D bootrom.elf
|
|
||||||
riscv64-elf-objcopy -O binary bootrom.elf bootrom.bin
|
|
||||||
od --endian=little -vtx4 -An -w4 bootrom.bin | tr -d ' ' > bootrom.vhex
|
|
||||||
r2 -A -c 'pdf @ sym._start' -q bootrom.elf
|
|
|
@ -1,73 +0,0 @@
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#define UART0_BASE 0x81000000
|
|
||||||
#define UART0_SR (*((volatile uint32_t *) (UART0_BASE + 0x00)))
|
|
||||||
#define UART0_DR (*((volatile uint32_t *) (UART0_BASE + 0x04)))
|
|
||||||
|
|
||||||
#define UART0_SR_RX_DATA_EMPTY (1 << 0)
|
|
||||||
#define UART0_SR_TX_FULL (1 << 1)
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Set up stack pointer
|
|
||||||
asm("_start:\
|
|
||||||
xor sp, sp, sp;\
|
|
||||||
lui sp, 0x80100;\
|
|
||||||
j main;\
|
|
||||||
");
|
|
||||||
*/
|
|
||||||
|
|
||||||
__attribute__((noreturn)) void _start() {
|
|
||||||
uint8_t state = 0;
|
|
||||||
uint8_t c;
|
|
||||||
uint8_t opcode;
|
|
||||||
uint8_t *ptr;
|
|
||||||
uint32_t length;
|
|
||||||
uint32_t sr;
|
|
||||||
|
|
||||||
/*while (1) {
|
|
||||||
while (UART0_SR & UART0_SR_RX_DATA_EMPTY);
|
|
||||||
c = UART0_DR;
|
|
||||||
while (UART0_SR & UART0_SR_TX_FULL);
|
|
||||||
UART0_DR = c;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
while (UART0_SR & UART0_SR_RX_DATA_EMPTY);
|
|
||||||
c = (uint8_t)UART0_DR;
|
|
||||||
sr = (sr << 8) | c;
|
|
||||||
state++;
|
|
||||||
switch (state) {
|
|
||||||
case 1: // Opcode
|
|
||||||
opcode = c;
|
|
||||||
if (c == 0) // NOP
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 5: // Address
|
|
||||||
ptr = (uint8_t*)sr;
|
|
||||||
if (opcode == 3) { // Jump
|
|
||||||
//((void (*)()) ptr)();
|
|
||||||
asm("jalr %0" : : "r"(ptr)); // Not sure why, but the jump above causes GCC to save variables to the stack at the beginning of this function
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 9: // Data
|
|
||||||
length = sr;
|
|
||||||
if (opcode == 2) { // Read
|
|
||||||
for (; length > 0; length--) {
|
|
||||||
while (UART0_SR & UART0_SR_TX_FULL);
|
|
||||||
UART0_DR = *(ptr++);
|
|
||||||
}
|
|
||||||
} else { // Write
|
|
||||||
for (; length > 0; length--) {
|
|
||||||
while (UART0_SR & UART0_SR_RX_DATA_EMPTY);
|
|
||||||
*(ptr++) = UART0_DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
115
tools/flash.py
115
tools/flash.py
|
@ -1,115 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------- --
|
|
||||||
# TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
|
||||||
# -------------------------------------------------------------------------- --
|
|
||||||
# Interface program for the bootrom. Basically a serial-to-wishbone bridge.
|
|
||||||
# -------------------------------------------------------------------------- --
|
|
||||||
# Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
# Contributors : None
|
|
||||||
# License : Mozilla Public License (MPL) Version 2
|
|
||||||
# -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
import serial
|
|
||||||
import sys
|
|
||||||
from ast import literal_eval
|
|
||||||
|
|
||||||
def eprint(*args, **kwargs):
|
|
||||||
print(*args, file=sys.stderr, **kwargs)
|
|
||||||
|
|
||||||
ser = serial.Serial('/dev/ttyUSB0', 250000, timeout=2)
|
|
||||||
|
|
||||||
def sread(address, length, quiet = False):
|
|
||||||
if not quiet:
|
|
||||||
eprint(f'Reading {length} bytes from 0x{address:08x}...')
|
|
||||||
ser.write(b'\x02' + address.to_bytes(4, byteorder='big') + length.to_bytes(4, byteorder='big'))
|
|
||||||
data = bytes()
|
|
||||||
while length > 0:
|
|
||||||
maxpkg = min(length, 128)
|
|
||||||
rd = ser.read(maxpkg)
|
|
||||||
if len(rd) == 0:
|
|
||||||
eprint("ERROR: Receive timeout")
|
|
||||||
return None
|
|
||||||
data += rd
|
|
||||||
length -= len(rd)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def swrite(address, data, quiet = False):
|
|
||||||
if not quiet:
|
|
||||||
eprint('Writing {} bytes to 0x{:08x}...'.format(len(data), address))
|
|
||||||
ser.write(b'\x01' + address.to_bytes(4, byteorder='big') + len(data).to_bytes(4, byteorder='big') + data)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def sjump(address, quiet = False):
|
|
||||||
if not quiet:
|
|
||||||
eprint(f'Jumping to 0x{address:08x}...')
|
|
||||||
ser.write(b'\x03' + address.to_bytes(4, byteorder='big'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def get_diff(a, b):
|
|
||||||
diff = 0
|
|
||||||
for i in range(0, len(a)):
|
|
||||||
if a[i] != b[i]:
|
|
||||||
print('[0x{:08x}] 0x{:02x} => 0x{:02x}'.format(i, a[i], b[i]))
|
|
||||||
diff += 1
|
|
||||||
return diff
|
|
||||||
|
|
||||||
def probe():
|
|
||||||
r = sread(0, 4, quiet = True);
|
|
||||||
if r is None:
|
|
||||||
eprint("ERROR: Probe failed! Check that the device is in bootloader mode.")
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def program(filename, addr=0, check=True):
|
|
||||||
f = open(filename, "rb")
|
|
||||||
d = bytes(f.read())
|
|
||||||
swrite(addr, d)
|
|
||||||
if check:
|
|
||||||
r = sread(addr, len(d))
|
|
||||||
if r is None:
|
|
||||||
eprint("Programming failed")
|
|
||||||
return 1
|
|
||||||
diff_cnt = get_diff(d, r)
|
|
||||||
if diff_cnt == 0:
|
|
||||||
eprint("Programming OK.")
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
print(f"Programming failed, {diff_cnt} bytes differ.")
|
|
||||||
return 2
|
|
||||||
else:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def monitor():
|
|
||||||
print("Monitoring serial, press Ctrl+C to stop.")
|
|
||||||
while 1:
|
|
||||||
rd = ser.read(1)
|
|
||||||
if len(rd) > 0:
|
|
||||||
sys.stdout.buffer.write(bytes(rd))
|
|
||||||
sys.stdout.buffer.flush()
|
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
|
||||||
eprint("usage: " + sys.argv[0] + " [write|dump|jump] [address] [file]")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
command = sys.argv[1]
|
|
||||||
addr = literal_eval(sys.argv[2])
|
|
||||||
|
|
||||||
if probe():
|
|
||||||
exit(-1)
|
|
||||||
|
|
||||||
ret = 0
|
|
||||||
if command == "write":
|
|
||||||
file = sys.argv[3]
|
|
||||||
ret = program(file, addr)
|
|
||||||
elif command == "dump":
|
|
||||||
length = literal_eval(sys.argv[3])
|
|
||||||
sys.stdout.buffer.write(sread(addr, length))
|
|
||||||
elif command == "jump":
|
|
||||||
ret = sjump(addr)
|
|
||||||
monitor()
|
|
||||||
else:
|
|
||||||
ret = -2
|
|
||||||
eprint("Unknown command")
|
|
||||||
|
|
||||||
exit(ret)
|
|
Loading…
Reference in New Issue
Block a user