- कमर्शियल CPU या डेडिकेटेड नेटवर्क चिप के बिना बनाए गए डिस्क्रीट लॉजिक कंप्यूटर में 10BASE-T Ethernet ट्रांसमिट/रिसीव क्षमता जोड़ने की हार्डवेयर निर्माण कहानी
- पहले बनाए गए 10BASE-T↔SPI physical layer adapter के ऊपर MAC layer module जोड़कर उसे homebrew computer से जोड़ा गया, और transmitter व receiver को स्वतंत्र full-duplex संरचना में बनाया गया
- receiver SPI डेटा को bytes में बदलकर 2 kB SRAM में स्टोर करता है, और पहले 6 bytes को हार्डवेयर में जांचकर केवल
FE:FA:F6:F2:EE:EAया broadcast MAC स्वीकार करता है - transmitter ने circuit को सरल रखने के लिए FCS generation और preamble preparation को software पर छोड़ा, और केवल 1024-byte fixed-length frames सपोर्ट करता है
- uIP 1.0 compile कर सकने वाला C compiler तक बनाया गया और network apps चलाए गए; नतीजे ping average 85 ms और HTTP static file download 2.6 kB/s के स्तर के रहे
डिस्क्रीट लॉजिक कंप्यूटर में Ethernet जोड़ना
- एक पूरा computer system discrete logic components से बनाने के काम की अगली कड़ी के रूप में, network applications चला सकने वाला Ethernet adapter लागू किया गया
- पहले 10BASE-T Ethernet signal को SPI में बदलने और वापस बदलने वाला physical layer adapter बनाया गया था, और उस समय operation testing के लिए STM32 microcontroller इस्तेमाल किया गया था
- इस बार काम का मुख्य हिस्सा उस adapter को homebrew computer से जोड़ने के लिए MAC layer module है
- adapter full-duplex संरचना वाला है, जिसमें transmit और receive भाग एक-दूसरे से स्वतंत्र रूप से काम करते हैं
Receiver: SPI डेटा को frame buffer में स्टोर करना
- receiver SPI serial data को byte-level parallel data में बदलता है और byte clock निकालता है
- destination MAC address को पहले 6 bytes में जांचा जाता है, और criteria पर खरे न उतरने वाले frames reject कर दिए जाते हैं
- प्राप्त bytes 6116 2 kB SRAM buffer में लिखे जाते हैं
- frame खत्म होने पर receiver inactive हो जाता है, और फिर से active होने तक अतिरिक्त frames नहीं लेता
- byte counter रुकने के बाद भी value बनाए रखता है ताकि CPU received length पढ़ सके
- FCS को hardware में verify नहीं किया जाता
-
Data collection और buffer access
- SPI serial data shift register
U32में जाता है, औरU30वU31क्रमशः bits और bytes गिनते हैं - D flip-flop
U29BSRAM write signalrecv_buf_weबनाता है, और यह signal input data के हर 8 bits पर थोड़ी देर के लिए low हो जाता है - received bytes
U20वाले 6116 SRAM में लिखे जाते हैं U13,U16,U18address multiplexer बनाते हैं, जो SRAM address input के लिए byte counter या system address bus चुनते हैंU21received bytes को RAM तक पहुंचाने वाले 3-state buffer की भूमिका निभाता है- CPU को received data और length access करने देने के लिए RAM और byte counter system data bus से जुड़े हैं
U25receive RAM को system data bus से जोड़ता है- frame complete होने के बाद byte counter की value
recv_byte_cntbus पर बनी रहती है U26,U27किसी specific address read request आने पर यह value system data bus पर भेजते हैंU27का बाकी आधा हिस्सा receiver और transmitter status query करने वाला 2-bit read-only status register बनाता है
- SPI serial data shift register
Hardware MAC address filtering
- Ethernet traffic analyze करने पर पता चला कि frames आम तौर पर थोड़े delay से अलग किए गए 3–4 units के छोटे batches में आते थे, और एक ही batch के अंदर भी destination MAC address अक्सर अलग होता था
- computer शायद इतना तेज नहीं था कि software में MAC filtering करके receiver को फिर से active कर सके, इसलिए hardware MAC filtering जरूरी थी
- custom MAC address store करके पहले 6 bytes से compare करने वाला तरीका बहुत जटिल होने के कारण छोड़ दिया गया
- single-byte repeated MAC address भी संभव था, लेकिन आखिर में MAC address को byte index के function के रूप में बनाया गया
- bit 0 को 0 पर fixed रखा गया
- bit 1 को 1 पर fixed रखा गया
- bit 2~4 byte index की inverted value हैं
- bit 5~7 को 1 पर fixed रखा गया
- इस rule से बना MAC address
FE:FA:F6:F2:EE:EAहै - ARP operation के लिए broadcast MAC
FF:FF:FF:FF:FF:FFभी स्वीकार किया जाता है U33data bit 0 और bit 2~4 को desired values से match करता है या नहीं, यह compare करता है; औरU34Aoutput तब high होता है जब ये bits match करते हैंU35Abroadcast MAC check लागू करता है, और bit 0 व bit 2~4 सभी 1 हों तो output high हो जाता है- दोनों signals को
D7औरR6का उपयोग करने वाले diode OR से combine किया जाता है, औरU35Bजांचता है कि बाकी bits सभी 1 हैं या नहीं - single byte का validity result
U10Aमें accumulate होता है- frame receive न करते समय incoming SPI slave select signal
sslow होता है औरU10Aको 1 पर set किया जाता है - frame receive के दौरान हर received byte पर value update होती है
- destination MAC address criteria पर खरा उतरे तो
U10Avalue high बनी रहती है - byte address 5 तक पहुंचने पर final value
U36Bमें latch होती है, और destination address match न करे तो frame reception रोक दिया जाता है
- frame receive न करते समय incoming SPI slave select signal
Transmitter: fixed-length frames से circuit सरल बनाना
- transmitter भी receiver की तरह FCS generation को hardware में लागू नहीं करता और software में handle करता है
- circuit कम करने के लिए transmitter केवल fixed-length frames support करता है
- frame length 1024 bytes चुनी गई, जो common MTU 1500 bytes के करीब है
- 10BASE-T के लिए जरूरी preamble कई
0x55और अंत में0xD5से बना होता है, और software को इसे भी इसी 1024-byte में साथ में load करना होता है - fixed frame length higher-level protocols को प्रभावित नहीं करती
- higher-level protocols packet size को header में encode करते हैं
- actual Ethernet frame length पर निर्भर नहीं करते
-
Transmit data flow
- transmit data SRAM में stored होता है
- 20 MHz clock 4-bit counter में input होती है, और overflow output byte clock के रूप में इस्तेमाल होता है
- किसी specific write-only memory location में value लिखने पर counter active होता है और frame transmission शुरू हो जाता है
- parallel byte data shift register के जरिए serialize होता है
- receiver की तरह
U12bits गिनता है औरU14bytes गिनता है - 20 MHz clock integrated oscillator से आती है, और सीधे इस्तेमाल नहीं होती; कम से कम divide-by-2 करके इस्तेमाल होती है
- यह तरीका oscillator के duty cycle को output signal पर असर डालने से रोकता है
-
RAM, shift register, timing
- RAM
U22के address input selection के लिए receiver की तरह तीन 74HC157 multiplexers इस्तेमाल होते हैं U23RAM में data load करने के लिए इस्तेमाल होता हैU24current transmit byte के intermediate storage की भूमिका निभाता है- byte counter 74HC4040 ripple counter है, इसलिए stabilization धीमा है
- जब RAM output अभी valid नहीं होता, तब
U24stable output देता है - data shift register
U28में जाता है और bit-by-bit shift होता है - RAM से shift register में जाने वाले bits का order गलत wire हो गया था, ऐसा hardware bug था; इसलिए software में bits shuffle करके workaround करना पड़ा
MOSIऔरSCKको अच्छे 10BASE-T signal बनाने के लिए ठीक-ठीक synchronize होना चाहिएU11AऔरU8Bयह synchronization संभालते हैंtx_cnt0bit counter का bit 0 है, और 20 MHz को divide-by-2 किया हुआ signal clock के लिए इस्तेमाल होता हैU11Aइस signal के अनुसार output बदलता हैU8B,U11Aद्वारा बनाए गए delay से match करने के लिए clock delay करता है- D latch साधारण AND gate से ज्यादा complex होता है और लगभग 5 ns ज्यादा delay रखता है, इसलिए तेज 74LV74A इस्तेमाल किया गया
- 74LV74A इस board पर fast family का इकलौता chip है
- RAM
CPU interface और memory mapping
- programmer के नजरिए से Ethernet adapter memory-mapped interface जैसा दिखता है
- दोनों frame buffers
0xF000पर mapped हैं - read-only registers दो हैं
0xFB00का 8-bit status registerRX_FULLऔरTX_BUSYflags रखता हैRX_FULLframe reception complete state दिखाता हैTX_BUSYframe transmission in progress state दिखाता है0xFB02का 16-bit register received data length रखता है
- write operations control commands के रूप में इस्तेमाल होते हैं
0xFB00पर कोई भी value लिखने से receiver फिर से active होता है0xFB01पर कोई भी value लिखने से transmission शुरू होता है
- CPU interrupts support नहीं करता, इसलिए interrupts नहीं हैं
- संबंधित addresses सभी upper 4 bits 1 वाले
Fसे शुरू होते हैं, और इस condition कोU2Acheck करता है - buffer address में bit 11 को 0 होना चाहिए, और
U1D,D2,R2,U1Eइसे check करते हैं - register address में दूसरा hexadecimal digit
Bयानी1011होना चाहिए, औरU1BवU2Bइसकी पुष्टि करते हैं U4A,U4Bdecoders individual functions select करने में इस्तेमाल होते हैं- दो LEDs buffer या register access दिखाते हैं
Programming और performance
- network support चाहिए था, लेकिन TCP/IP stack खुद implement नहीं करना था और assembly programming भी असुविधाजनक थी, इसलिए C compiler बनाया गया
- यह compiler छोटे TCP/IP library uIP 1.0 को compile कर सकने जितना mature है
- CPU की code density बहुत कम है, लेकिन uIP RAM में fit हो जाता है और real applications के लिए भी जगह बचती है
- network performance कम है, लेकिन यह commercial CPU या special chip के बिना लागू किया गया नतीजा है
- ping round-trip average: 85 ms
- HTTP server download speed: 2.6 kB/s
- HTTP server SD card की static files serve करता है
- model, schematic files और PCB drawings GitHub repository में हैं
1 टिप्पणियां
Hacker News की राय
शेयर करने के लिए शानदार काम। तर्क-प्रक्रिया का stack trace खास तौर पर अच्छा लगा, और बहुत-सी चीज़ों को first principles से समझाना या beginner के नज़रिए से समझाने की कोशिश करना शैक्षिक रूप से बेहतरीन है
वास्तविक networking के लिए भले ही यह व्यावहारिक न हो, लेकिन मुझे नहीं लगता कि यह सिर्फ़ कोई खिलवाड़ है। ऐसे दौर में जब बेहद जटिल network chips में backdoor मिल रहे हैं, आगे चलकर इसके लिए अधिक गंभीर पाठक-वर्ग या project motivation बन सकती है
यह तो पूरी तरह custom computer के लिए है, इसलिए अपने-आप में कहीं ज़्यादा प्रभावशाली है, और “तो मैंने C compiler बना लिया” वाली बात तो अलग ही है। फिर भी यह सोचने पर मजबूर करता है कि “सामान्य” PC के लिए Ethernet card का minimum implementation कितना होगा
काफ़ी हिस्सा मिलता-जुलता होगा, और checksum को PC CPU से handle कराया जा सकता है। Connection या तो raw serial होगा, या अधिक व्यावहारिक रूप से USB चाहिए होगा, और अंत में शायद “real” driver इस्तेमाल करना पड़ेगा या user space में भेजकर process करना होगा
मिलती-जुलती चीज़ें देखते हुए लगा कि अगर device https://en.wikipedia.org/wiki/USB_communications_device_clas... implement करे, तो क्या यह अपने driver के बिना “बस चल” सकता है, लेकिन यह सभी checksums को host side पर handle करने के साथ शायद ठीक से मेल नहीं खाएगा
खोजते हुए https://en.wikipedia.org/wiki/Ethernet_over_USB भी मिला, शायद इसका मतलब है कि ऐसा adapter बनाया जा सकता है जो सिर्फ़ physical connection को USB में बदल दे और बाकी computer खुद handle करे
शायद किसी FTDI-style USB device को 10base2 Ethernet bit-banging करने के लिए मनाया जा सके। तरीका यह होगा कि line traffic को साफ़ bitstream में बदलने और frame start align करने वाला “PHY” हिस्सा ही implement किया जाए, फिर PC बाकी सब software में process करे
USB side पर CDC-NCM खुद किसी भी MCU पर implement करना मुश्किल नहीं है, लेकिन USB HS PHY implementation के लिए व्यवहार में ASIC hardware चाहिए
0.30 डॉलर वाले USB HS ULPI PHY का इस्तेमाल करें तो FPGA में USB CDC-NCM काफ़ी आसानी से implement किया जा सकता है
अंत में इस project के लिए बनाए गए C compiler का link है: https://github.com/imihajlow/ccpu-cc
लगता है linker और libc भी हैं। Hardware design कितना जटिल है, यह ठीक से नहीं जानता, लेकिन C compiler को हल्के-फुल्के अंदाज़ में बनाकर जोड़ देना कमाल है
सच में प्रभावशाली। ऐसा project खुद करके देखना चाहता हूँ, और system को समझने से लेकर उसे बनाने तक लगी लगन और अनगिनत घंटों के लिए सम्मान महसूस होता है
retirement की कोई ख़ास इच्छा नहीं है, लेकिन शायद तब इस तरह के hardware-software projects में समय लगाऊँ
तो क्या यह Etherlink 3c501 से बेहतर है, या उससे भी खराब? :-D
https://mirror.math.princeton.edu/pub/oldlinux/Linux.old/net...
अगर याद सही है, तो network से आया नया packet उसी buffer को overwrite कर देता था जिसे CPU पढ़ने वाला था। मैंने इसे कुछ समय Linux में इस्तेमाल किया था, और performance सच में बहुत खराब थी
Driver और firmware updates हमारी नज़र से कितना कुछ छिपा देते हैं, यह हैरान करने वाला है
मेरे वाले में दो buffers हैं, इसलिए यह बेहतर है :) फिर भी received frame सिर्फ़ एक ही रखा जाता है
“Frame length fixed कर देने से higher-level protocols पर असर नहीं पड़ता। क्योंकि higher-level protocols header में packet size encode करते हैं और actual Ethernet frame length पर निर्भर नहीं करते” वाला हिस्सा दिलचस्प है
हाल में मैंने packet decoder बनाया था, और हर layer पर explicitly verify किया कि lower-layer length सही है या नहीं। IP के मामले में मेरे decoder में IP datagram length को Ethernet frame length और link-layer header length से बिल्कुल match करना होता है
यह ज़रूरत से ज़्यादा सावधानी के लिए नहीं था, बल्कि short frames detect करने के लिए था, और बाद में long frames को भी error मानने का फैसला किया। लेखक uIP इस्तेमाल कर रहे हैं, लेकिन Linux या दूसरे modern OS इसे कैसे handle करते हैं, यह जानना चाहूँगा। यह भी जानना चाहूँगा कि interoperability testing की गई थी या नहीं
अगर application L2 data नहीं देखती, तो Linux IP stack इसे बस ignore कर देता है
DEC के पहले SSI Ethernet card set की तुलना में यह physically काफी छोटा है: https://i.ebayimg.com/images/g/NEYAAOSw-mZlg0lZ/s-l1600.jpg
DEC DEUNA boards की लंबाई 1 foot से ज़्यादा है, लेकिन उनमें features भी बहुत ज़्यादा हैं। DEUNA एक “real” NIC है, जिसमें send/receive queues हैं, वह उन्हें autonomously handle करता है और DMA भी करता है। बेशक, card पर अपना PDP-11 भी है, जो उसे चलाता है
सच में शानदार। जानना चाहूँगा इसमें कितना समय लगा
यह दिखाता है कि network port से जुड़े chip के अंदर backdoor लगाना कितना आसान है
Communication Systems Engineering course में Ethernet signal processing implement किया था, और फिर ARP और switching सहित TCP/IP stack को Motorola 68k QUIC assembly में implement किया
वह मेरी ज़िंदगी के सबसे लंबे 18 महीने थे