Compare commits

..

5 Commits

Author SHA1 Message Date
7379df7b74 phy: Improve clock accuracy at 0.5 dividers at the cost of some jitter 2024-07-15 13:34:54 +02:00
21a0d0e69a phy_cdc: Allow unlimited clock ratios
Actually, assuming that each clock domain is fast enough for 10 MBit/s,
there is no problem running crazy ratios.
2024-07-06 18:05:00 +02:00
943febcb99 phy_cdc: Fix synchronization behavior
For low ratios of the two clock domains, the slow clock domain would
receive incorrect data as the fast (PHY) clock domain's data output
would have already updated with the first bit of the next byte by
the time the slow (system) clock domain read it.

This fix registers the data in the source clock domain as opposed
to the destination clock domain. This is allowed because the valid
strobe is synchronized in a way to guarantee that data has been
valid for a while when it becomes asserted.

Additionally, `phy_out.rx_data` and `phy_out.rx_data_valid` are no
longer registered in the destination (system) clock domain as this
now introduces unnecessary latency. Also, this was broken the way
it was anyway as `rx_active` and `rx_error` would've also had to be
registered to keep all timings in sync.
2024-07-06 17:58:11 +02:00
da7e329939 des: Fix compatibility with Yosys 2024-06-22 11:19:02 +02:00
4bce111d69 doc: Add synthesized size for PHY-only design 2024-02-04 09:34:36 +01:00
14 changed files with 44 additions and 948 deletions

View File

@ -28,6 +28,14 @@ Notes:
* The RX pull up/downs are probably not the best idea, and fixable in a better way. But for now, this shall work -- and suffice!
* On the TX side, I'm grossly overloading the drivers. A line driver would probably be a good idea. Or you can just parallel multiple outputs ;D
## Stats
Sythesized for a Lattice LFXP2-5E FPGA using LSE / Diamond v3.12:
| Configuration | Slices | LUT4 | Registers |
| ---------------- | ------ | ---- | --------- |
| `trashernet_phy` | 115 | 188 | 91 |
## License
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.

View File

@ -1 +0,0 @@
target/**

View File

@ -1,491 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cactus"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf034765b7d19a011c6d619e880582bf95e8186b580e6fab56589872dd87dcf5"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfgrammar"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41879646bd1fbd55efdb9e2c1ac85e63856ad951e4e14b2e3086374802a13e9b"
dependencies = [
"indexmap",
"lazy_static",
"num-traits",
"regex",
"serde",
"vob",
]
[[package]]
name = "deranged"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "filetime"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"unicode-width",
]
[[package]]
name = "hashbrown"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
[[package]]
name = "indexmap"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]]
name = "lrlex"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d3c956ecfc913cb0e89575c5dd74d2558ec6e12c18f23baabc2985dc48ead28"
dependencies = [
"cfgrammar",
"getopts",
"lazy_static",
"lrpar",
"num-traits",
"quote",
"regex",
"regex-syntax",
"serde",
"vergen",
]
[[package]]
name = "lrpar"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f2acdd7023dc9f0eb51b13a615477c245519f593537667116874d2c699972d"
dependencies = [
"bincode",
"cactus",
"cfgrammar",
"filetime",
"indexmap",
"lazy_static",
"lrtable",
"num-traits",
"packedvec",
"regex",
"serde",
"static_assertions",
"vergen",
"vob",
]
[[package]]
name = "lrtable"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "310933a066b41ed437844d548c5972b02b407e63a8254d08204082a05f7a1b34"
dependencies = [
"cfgrammar",
"fnv",
"num-traits",
"serde",
"sparsevec",
"vob",
]
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "num-traits"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [
"autocfg",
]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "packedvec"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bde3c690ec20e4a2b4fb46f0289a451181eb50011a1e2acc8d85e2fde9062a45"
dependencies = [
"num-traits",
"serde",
]
[[package]]
name = "proc-macro2"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b1106fec09662ec6dd98ccac0f81cef56984d0b49f75c92d8cbad76e20c005c"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "rustversion"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "semver"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0"
[[package]]
name = "serde"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sparsevec"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35df5d2e580b29f3f7ec5b4ed49b0ab3acf7f3624122b3e823cafb9630f293b8"
dependencies = [
"num-traits",
"packedvec",
"serde",
"vob",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "time"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe"
dependencies = [
"deranged",
"itoa",
"libc",
"num_threads",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
dependencies = [
"time-core",
]
[[package]]
name = "trashernet-as"
version = "0.1.0"
dependencies = [
"cfgrammar",
"lrlex",
"lrpar",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-width"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "vergen"
version = "8.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85e7dc29b3c54a2ea67ef4f953d5ec0c4085035c0ae2d325be1c0d2144bd9f16"
dependencies = [
"anyhow",
"rustversion",
"time",
]
[[package]]
name = "vob"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c058f4c41e71a043c67744cb76dcc1ae63ece328c1732a72489ccccc2dec23e6"
dependencies = [
"num-traits",
"rustc_version",
"serde",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"

View File

@ -1,16 +0,0 @@
[package]
name = "trashernet-as"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
cfgrammar = "0.13"
lrlex = "0.13"
lrpar = "0.13"
[dependencies]
cfgrammar = "0.13"
lrlex = "0.13"
lrpar = "0.13"

View File

@ -1,15 +0,0 @@
use cfgrammar::yacc::YaccKind;
use lrlex::CTLexerBuilder;
fn main() {
CTLexerBuilder::new()
.lrpar_config(|ctp| {
ctp.yacckind(YaccKind::Grmtools)
.grammar_in_src_dir("calc.y")
.unwrap()
})
.lexer_in_src_dir("calc.l")
.unwrap()
.build()
.unwrap();
}

View File

@ -1,186 +0,0 @@
# Trashernet Command Processor
Commands:
* MATCH (length, matches, jump), followed by match-jump-addresses if <jump>, followed by match bytes interleaved: Match incoming data against. Set <length> to zero for unconditional jump. If no match, abort reception.
* FORWARD (length): Output <length> bytes of data on the output port
* IGNORE (length): Ignore <length> bytes
* OUTPUT: Output following byte on the special port
Command format:
2b 4b 3b 1b
[Opcode] [length] [matches] [jump]
Example program:
# MAC frame
MATCH (6, 2, false) AA.BB.CC.DD.EE.FF FF.FF.FF.FF.FF.FF
IGNORE (6)
# Protocol MUX
MATCH (
# IPv4
MATCH (4, 1, false) 192.168.178.1
# IDEA 2
Okay, I need a new idea. The problem with the first is that I almost always need access to parameters from the past. E.g. ARP requires the sender MAC address for the response. In the current design, I would've already discarded that because what do I care about it for a data packet.
So, new approach: A packet is received into a RAM ring buffer, and then the script is started with the CRC OK.
New scripting language:
* SET_CURSOR (position): Set cursor to position in received telegram
* MATCH[!] <address> <pattern>: Jump to address if pattern matches; else continue after pattern and reset cursor to before match (without !), or stop receiving (with !)
* FORWARD <length>
* OUTPUT <byte>
* DIE
COMMAND formatting:
general : [3 bit opcode]
MATCH : [1b deathflag] [4 bit length]
Example program:
MAC_DST: MATCH AA.BB.CC.DD.EE.FF -> ETHERTYPE
MAC_BCAST: MATCH! FF.FF.FF.FF.FF.FF -> ETHERTYPE
ETHERTYPE_ARP: MATCH 08.06 -> ARP
ETHERTYPE_IP: MATCH! 08.00 -> IP
ARP: MATCH! 00.01.08.00.06.04 -> ARP_HDR_OK
ARP_HDR_OK: MATCH 01 -> ARP_REQUEST
MATCH! 02 -> ARP_REPLY
ARP_REQUEST: SET_CURSOR +10
MATCH! AA.BB.CC.DD.EE.FF -> ARP_REQUEST_OK
ARP_REQUEST_OK: OUTPUT 01
SET_CURSOR -16
FORWARD 10
DONE
This program generates an interrupt for
* ARP (01) with 10 user bytes SHA+SPA
## Now, on the sender side.
* TX processor runs on shared memory with receiver, possibly even shared with the receive buffer
So that receiver can write "program memory" of transmitter, this is relevant for example for IP TX, which checks that some memory address is the target TX address.
Idea for an IP TX with ARP.
* Destination IP is written to address in memory
* Start IP TX program
* ARP_CHECK: SET_CURSOR(ARP RX address buffer)
* MATCH <destination address) -> FOUND_IP
* WRITE_MEM <ARP TX address buffer> <destination IP>
* SET_CURSOR(ARP TX address buffer)
* MATCH <destination address> -> ARP_CHECK
* !!! TBD: Assemble and send out ARP request
* JUMP ARP_CHECK
* !!! TBD: Loop until MATCH
* FOUND_IP: Assemble and send out IP frame
ideas for improvement:
* have two cursors for the TX engine
-> basically to select between static data and dynamic
# Final (TM) Idea
* We build one processor. It handles both TX and RX
* It runs code from a shared memory space with the RX buffer
* It has multiple pointer registers (at least two)
Commands:
* Match <len, abort_flag,poll_flag> -> <dest>: Compare len characters from ptr1 and ptr2, jump to dest if all match, go to next instruction if not; if len=zero, it's an unconditional jump. `poll_flag` keeps looping here until the condition is met. `abort_flag` will abort command execution on mismatch.
* SetPtr <ptr>, <relative/absolute>
* Write <len>: Write <len> data from ptr2 to ptr1
* Output <ptr, len>: Push <len> data from <ptr> to output FIFO
* Input <ptr, len>: Read <len> bytes from input FIFO into <ptr>
* Return: TBD: Single-level return to caller (last match?)
* Jump <ptr1> <ptr2>: Pseudo-command, will translate to other instructions. Set location of ptr1 and ptr2 (opt.), then jump (empty match) to that address.
## Example to send an IP frame
* Write destination IP to <dest-ip>
* Start TX IP program
SendUDP:
CheckARP:
SetPtr ptr1, <arp-rx-ip-buffer>
SetPtr ptr2, <dest-ip>
Match 4 -> FOUND_ARP
NeedARPRequest:
Jump SendMAC, ptr1="FF:FF:FF:FF:FF:FF", ptr2="08:06"
Jump SendARP, ptr1=<dest-ip>
Match 4, poll -> FOUND_ARP
FOUND_ARP:
// ## SendMAC: Send MAC frame. ptr1: Destination MAC, ptr2: Ethertype
SendMAC:
Output ptr1, 6
SetPtr ptr1, <my-mac>
Output ptr1, 6
Output ptr2, 2
Return
SendARPRequest:
Output <ARP-header> // TODO
Output <my-mac> // SHA
Output <my-ip> // SPA
Output FF:FF:FF:FF:FF:FF // THA
Output <dest-ip> // TPA
Return
## Maybe change concept
Idea is: We pretty much have a template for each frame in memory. The program will assemble the data in place, and then TX the entire block
// Variables will be defined in order!
// Ethernet frame
Def ETH-DEST-MAC:6
Def ETH-SOURCE-MAC:6=00:DE:AD:BE:EF:00
Def ETH-ETHERTYPE:2
// ARP frame
Def ARP-HEADER:?=0001:0800:0604:0001
Def ARP-SHA:0=&ETH-SOURCE-MAC
Def ARP-SPA:4
Def ARP-THA:6
Def ARP-TPA:4
CheckARP:
SetPtr ptr1, <arp-rx-ip-buffer>
SetPtr ptr2, <dest-ip>
Match 4 -> FOUND_ARP
NeedARPRequest:
// Build Ethernet header
Write &ETH-DEST-MAC, "FF:FF:FF:FF:FF:FF"
Write &ETH-ETHERTYPE, "0806"
Output &ETH-DEST-MAC, 18
// Build ARP header
Write &ARP_TPA, <dest-ip>, 4
Output &ARP-HEADER, 8
Output &ARP_SHA, 6
Output &ARP_SPA, 4
Output &ARP-THA, 10 // +ARP-TPA
// todo: set up match
Match 4, poll -> FOUND_ARP
FOUND_ARP:

View File

@ -1,9 +0,0 @@
%%
SetPtr "SetPtr"
[0-9]+ "NUM-DEC"
0x[0-9a-fA-F]+ "NUM-HEX"
0b[0-1]+ "NUM-BIN"
[\n] "NEWLINE"
[\t ]+ ;
&[0-9a-zA-Z_]+ "Reference"
[0-9a-zA-Z ] "text"

View File

@ -1,95 +0,0 @@
%start CommandSequence
%%
CommandSequence -> Result <LinkedList<Result<LineOfCode, CompilerError>>, CompilerError>:
CommandLine CommandSequence
{
let mut list = $2?;
list.push_front($1);
Ok(list)
}
| CommandLine
{
let mut list : LinkedList<Result<LineOfCode, CompilerError>> = LinkedList::new();
list.push_front($1);
Ok(list)
}
;
CommandLine -> Result<LineOfCode, CompilerError>:
Command 'NEWLINE'
{
Ok(LineOfCode{line : 42, code: $1})
}
| 'NEWLINE'
{
Err(CompilerError {pos: $1.unwrap().span(), description: CompilerErrorType::MiscError})
}
;
/*Comment -> Result<(), ()>:
';' 'text':
{
Ok(())
}
;*/
Command -> Result <Code, CompilerError>:
'SetPtr' PointerId Symbol
{
Ok(Code::Instruction(InstructionType::SetPtr{which: $2?, address: $3?}))
}
;
PointerId -> Result<u16, CompilerError>:
Literal
{
let num = $1?;
if num > 0 && num <= 1 {
Ok(num)
} else {
//Err(CompilerError {pos: $lexer.line_col($1.unwrap().span()), description: CompilerErrorType::MiscError})
Ok(42) // TODO: This should raise an error, but I don't know the span anymore -.-
}
}
;
Symbol -> Result<Symbol, CompilerError>:
Literal
{
Ok(Symbol::ResolvedSymbol{address: $1?})
}
| Reference
{
Ok(Symbol::UnresolvedSymbol{symbol: $1?})
}
;
Reference -> Result<String, CompilerError>:
'Reference'
{
Ok($lexer.span_str($1.unwrap().span())[1..].to_string())
}
;
Literal -> Result<u16, CompilerError>:
'NUM-HEX'
{
parse_number(16, $1.unwrap().span(), &$lexer.span_str($1.unwrap().span())[2..]) // TODO: Change error to include line/col etc.
}
| 'NUM-DEC'
{
parse_number(10, $1.unwrap().span(), &$lexer.span_str($1.unwrap().span()))
}
;
%%
use crate::compiler_types::*;
use std::collections::LinkedList;
fn parse_number(radix: u32, span: lrpar::Span, s: &str) -> Result<u16, CompilerError> {
//Ok(u16::from_str_radix(s, radix)?)
//u16::from_str_radix(s, radix).map_err(CompilerError{description: CompilerErrorType::MiscError})
u16::from_str_radix(s, radix).map_err(|e| CompilerError{pos: span, description: e.into()})
}

View File

@ -1,73 +0,0 @@
use std::num;
#[derive(Debug)]
pub enum Symbol {
UnresolvedSymbol{symbol: String},
ResolvedSymbol{address: u16}
}
#[derive(Debug)]
pub enum JumpCondition {
Always,
OnMatch,
OnTimer
}
#[derive(Debug)]
pub enum InstructionType {
SetPtr{which: u16, address: Symbol},
Output{length: Symbol},
Match{length: Symbol},
Write{length: Symbol},
Timer{time: Symbol},
Page{page: Symbol},
Return,
Input{length: Symbol},
Jump{address: Symbol, condition: JumpCondition}
}
#[derive(Debug)]
pub enum Code {
Instruction(InstructionType),
Comment(String)
}
#[derive(Debug)]
pub struct LineOfCode {
pub line: usize,
pub code: Result<Code, CompilerError>
}
#[derive(Debug)]
pub struct CompilerError {
pub pos: lrpar::Span,
pub description: CompilerErrorType
}
#[derive(Debug)]
pub enum CompilerErrorType {
LiteralError(num::ParseIntError),
LexerError(lrlex::DefaultLexeme),
MiscError
}
impl From<num::ParseIntError> for CompilerErrorType {
fn from(e: num::ParseIntError) -> Self {
CompilerErrorType::LiteralError(e)
}
}
impl From<lrlex::DefaultLexeme> for CompilerErrorType {
fn from(e: lrlex::DefaultLexeme) -> Self {
CompilerErrorType::LexerError(e)
}
}
/*
impl fmt::Debug for LineOfCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Line = {}", self.line)
}
}
*/

View File

@ -1,25 +0,0 @@
mod compiler_types;
use std::env;
use std::fs;
use lrlex::lrlex_mod;
use lrpar::lrpar_mod;
lrlex_mod!("calc.l");
lrpar_mod!("calc.y");
fn main() {
let lexerdef = calc_l::lexerdef();
let args: Vec<String> = env::args().collect();
let code = fs::read_to_string(&args[1]).unwrap();
let lexer = lexerdef.lexer(&code);
let (res, errs) = calc_y::parse(&lexer);
for e in errs {
println!("{}", e.pp(&lexer, &calc_y::token_epp));
}
match res {
Some(r) => println!("Result: {:#?}", r),
_ => eprintln!("Unable to evaluate expression.")
}
}

View File

@ -1,4 +0,0 @@
SetPtr 1 22
SetPtr 2 0x42
SetPtr 3 &Ref
SetPtr 4 99999

View File

@ -55,12 +55,13 @@ architecture rtl of trashernet_arp is
signal arp_tx_reply_ack : std_logic; -- ARP reply has been latched and is being sent
signal arp_tx_request_rq : std_logic; -- Request to transmit an ARP request
signal arp_tx_request_tpa : ip_addr_t; -- IP address that we want to know the MAC address of, either real target or gateway
signal arp_tx_request_tpa : ip_addr_t; -- IP address that we want to know the MAC address of
signal arp_tx_request_ack : std_logic; -- ARP request has been latched and is being sent
signal arp_rx_reply_stb : std_logic; -- An ARP reply was received (strobe)
signal arp_rx_sha : mac_addr_t; -- The MAC address of the reply sender, valid with arp_rx_reply
signal arp_rx_spa : ip_addr_t; -- The IP address of the reply sender, valid with arp_rx_reply
begin
resolver : block
type resolver_state_t is (IDLE, QUERY_MAC);
@ -71,10 +72,8 @@ begin
signal replied_ip : ip_addr_t;
signal replied_mac : mac_addr_t;
signal arp_query_stb : std_logic; -- Pipelined version of arp_in.arp_query_stb
signal target_is_in_subnet : std_logic; -- Indicates whether the target IP is the subnet or whether to send this to the gateway
begin
arp_resolver_main : process(rst, clk) is
begin
if rst then
@ -97,7 +96,7 @@ begin
case state is
when IDLE =>
if arp_query_stb then
if arp_in.arp_query_stb then
if query_mac_found then
arp_out.arp_ok_stb <= '1';
else
@ -119,21 +118,9 @@ begin
end if;
end process arp_resolver_main;
query_mac_found <= '1' when (arp_tx_request_tpa = replied_ip) else '0';
target_is_in_subnet <= or((arp_in.arp_ip xor ip_config.gateway) and ip_config.subnet_mask);
arp_out.arp_mac <= replied_mac;
-- Pipelines the start of query so that we get some additional time to evaluate the target+netmask.
pipeline : process (clk, rst) is
begin
if rst then
arp_tx_request_tpa <= (others => x"00");
arp_query_stb <= '0';
elsif rising_edge(clk) then
arp_tx_request_tpa <= arp_in.arp_ip when target_is_in_subnet else ip_config.gateway;
arp_query_stb <= arp_in.arp_query_stb;
end if;
end process pipeline;
arp_tx_request_tpa <= arp_in.arp_ip;
timeout_timer_inst : entity work.timer
generic map(

View File

@ -253,6 +253,7 @@ begin
begin
if rst then
phy_out.rx_data_valid <= '0';
phy_out.rx_data <= (others => '0'); -- Needed for yosys to compile
elsif rising_edge(clk) then
phy_out.rx_data_valid <= '0';
@ -296,7 +297,10 @@ begin
-- -------------------------------------------------------------------------
transmitter : block
constant TX_STB_CNT_MAX : integer := integer(round(real(F_CLK) / real((F_ETH * 2)))) - 1;
constant TX_STB_CNT_IDEAL : real := real(F_CLK) / real((F_ETH * 2));
constant TX_STB_SKIP_ERROR : real := abs (round(TX_STB_CNT_IDEAL) - TX_STB_CNT_IDEAL);
constant TX_STB_CNT_MAX : integer := integer(round(TX_STB_CNT_IDEAL + 0.25)) - 1; -- Round up starting for error > 0.25
constant TX_STB_SKIP_SECOND : boolean := TX_STB_SKIP_ERROR >= 0.25; -- Skip one clock cycle every other symbol to hit clock rate in between when the divider is close to x.5
signal tx_stb_cnt : integer range 0 to TX_STB_CNT_MAX;
type tx_state_t is (IDLE, NLP, TX, IPG);
@ -367,6 +371,9 @@ begin
if tx_stb_cnt = 0 then
tx_stb_cnt <= TX_STB_CNT_MAX;
if TX_STB_SKIP_SECOND and bit_stage = '1' then
tx_stb_cnt <= TX_STB_CNT_MAX - 1;
end if;
else
tx_stb_cnt <= tx_stb_cnt - 1;
end if;

View File

@ -44,14 +44,14 @@ architecture rtl of trashernet_phy_cdc is
signal phy_phy_in : phy_in_t;
-- Helper signals
signal rx_data_valid_i : std_logic;
signal rx_data_i : byte;
begin
assert F_CLK_PHY > 2 * F_CLK report "F_CLK_PHY must be at least 2x F_CLK" severity failure;
-- -------------------------------------------------------------------------
-- Drives: PHY clock domain
-- -------------------------------------------------------------------------
-- Reset synchronizer for PHY
rstsync : process(phy_clk, rst) is
begin
if rst then
@ -61,6 +61,7 @@ begin
end if;
end process rstsync;
-- Operate Trashernet in PHY clock domain
trashernet_phy_inst : entity work.trashernet_phy
generic map(
F_CLK => F_CLK_PHY
@ -75,6 +76,22 @@ begin
tx_n => tx_n
);
-- Latch data in PHY clock domain when valid is strobed
-- If the other clock domain is slower than the time it takes for the strobe to synchronize,
-- `phy_phy_out.rx_data` will already have shifted in the next bit and no longer be valid.
-- Therefore, we need to latch it here.
rxdff : process(phy_clk, rst) is
begin
if rst then
rx_data_i <= (others => '0');
elsif rising_edge(phy_clk) then
if phy_phy_out.rx_data_valid then
rx_data_i <= phy_phy_out.rx_data;
end if;
end if;
end process rxdff;
synchronizer_txen_inst : entity work.synchronizer
generic map(
SIZE => 5
@ -98,18 +115,10 @@ begin
a_in => phy_phy_out.rx_data_valid,
b_clk => clk,
b_rst => rst,
b_out => rx_data_valid_i
b_out => phy_out.rx_data_valid
);
rxdvff : process(clk, rst) is
begin
if rst then
phy_out.rx_data_valid <= '0';
elsif rising_edge(clk) then
phy_out.rx_data_valid <= rx_data_valid_i;
phy_out.rx_data <= phy_phy_out.rx_data; -- Data should be stable after the time it takes the _valid signal to go through the synchronizer
end if;
end process rxdvff;
phy_out.rx_data <= rx_data_i; -- No need to synchronize in new clock domain as latched data has been stable for a while thanks to the delay in the _valid synchronizer
cdc_strobe_rxer_inst : entity work.cdc_strobe
port map(