Compare commits
17 Commits
feature/ar
...
master
Author | SHA1 | Date | |
---|---|---|---|
7379df7b74 | |||
21a0d0e69a | |||
943febcb99 | |||
da7e329939 | |||
4bce111d69 | |||
2190f146a0 | |||
91cdb13bb3 | |||
0db98483dc | |||
6de8d24537 | |||
87bc9ce3d7 | |||
fdcb1cb719 | |||
a0c9df28f1 | |||
0d7981f801 | |||
172a11070b | |||
9d9b3b1cce | |||
e421ba0dff | |||
277d01737d |
@ -6,6 +6,7 @@ Trashernet is a very trashy Ethernet stack for FPGAs written in VHDL aiming to c
|
|||||||
|
|
||||||
* Layer 1, Physical: `trashernet_phy`
|
* Layer 1, Physical: `trashernet_phy`
|
||||||
* Layer 2, Data link: `trashernet_mac`, `trashernet_eth`, `trashernet_arp`
|
* Layer 2, Data link: `trashernet_mac`, `trashernet_eth`, `trashernet_arp`
|
||||||
|
* Layer 3, Network: `trashernet_ipv4`, `trashernet_ipv4prot`, `trashernet_icmp`
|
||||||
|
|
||||||
When writing it, the following were the main design philosophies:
|
When writing it, the following were the main design philosophies:
|
||||||
|
|
||||||
@ -27,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!
|
* 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
|
* 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
|
## License
|
||||||
|
|
||||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||||
|
68
demo/lattice_brevia2/pingable/pingable.ldf
Normal file
68
demo/lattice_brevia2/pingable/pingable.ldf
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<BaliProject version="3.2" title="pingable" device="LFXP2-5E-6TN144C" default_implementation="impl1">
|
||||||
|
<Options/>
|
||||||
|
<Implementation title="impl1" dir="impl1" description="impl1" synthesis="lse" default_strategy="Strategy1">
|
||||||
|
<Options def_top="trashernet.fifo" lib="work" top="top_pingable"/>
|
||||||
|
<Source name="../ip/pll0.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../design/ledcon.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/cdc_strobe.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/crc.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/synchronizer.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_eth.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_mac.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_phy.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_phy_cdc.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_pkg.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_arp.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../design/top_hwitl.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/timer.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../design/top_pingable.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options top_module="top_pingable"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/fifo.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_icmp.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_ipv4.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../../trashernet/trashernet_ipv4prot.vhd" type="VHDL" type_short="VHDL">
|
||||||
|
<Options lib="trashernet"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="impl1/impl1.xcf" type="Programming Project File" type_short="Programming">
|
||||||
|
<Options/>
|
||||||
|
</Source>
|
||||||
|
<Source name="pingable.lpf" type="Logic Preference" type_short="LPF">
|
||||||
|
<Options/>
|
||||||
|
</Source>
|
||||||
|
</Implementation>
|
||||||
|
<Strategy name="Strategy1" file="pingable1.sty"/>
|
||||||
|
</BaliProject>
|
47
demo/lattice_brevia2/pingable/pingable.lpf
Normal file
47
demo/lattice_brevia2/pingable/pingable.lpf
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
BLOCK RESETPATHS ;
|
||||||
|
BLOCK ASYNCPATHS ;
|
||||||
|
LOCATE COMP "clk" SITE "21" ;
|
||||||
|
LOCATE COMP "rst_n" SITE "19" ;
|
||||||
|
LOCATE COMP "rx_p" SITE "94" ;
|
||||||
|
LOCATE COMP "led_n[0]" SITE "37" ;
|
||||||
|
LOCATE COMP "led_n[1]" SITE "38" ;
|
||||||
|
LOCATE COMP "led_n[2]" SITE "39" ;
|
||||||
|
LOCATE COMP "led_n[3]" SITE "40" ;
|
||||||
|
LOCATE COMP "led_n[4]" SITE "43" ;
|
||||||
|
LOCATE COMP "led_n[5]" SITE "44" ;
|
||||||
|
LOCATE COMP "led_n[6]" SITE "45" ;
|
||||||
|
LOCATE COMP "led_n[7]" SITE "46" ;
|
||||||
|
IOBUF PORT "rx_p" IO_TYPE=LVPECL33 ;
|
||||||
|
IOBUF PORT "clk" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "rst_n" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "debug_data[0]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "debug_data[1]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "debug_data[2]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "debug_data[3]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "debug_data[4]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "debug_data[5]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "debug_data[6]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "debug_data[7]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "led_n[0]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "led_n[1]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "led_n[2]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "led_n[3]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "led_n[4]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "led_n[5]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "led_n[6]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "led_n[7]" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "tx_n" IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "tx_p" IO_TYPE=LVCMOS33 ;
|
||||||
|
LOCATE COMP "tx_n" SITE "114" ;
|
||||||
|
LOCATE COMP "tx_p" SITE "116" ;
|
||||||
|
LOCATE COMP "button_n[0]" SITE "54" ;
|
||||||
|
LOCATE COMP "debug_data[0]" SITE "73" ;
|
||||||
|
LOCATE COMP "debug_data[1]" SITE "74" ;
|
||||||
|
LOCATE COMP "debug_data[2]" SITE "77" ;
|
||||||
|
LOCATE COMP "debug_data[3]" SITE "87" ;
|
||||||
|
LOCATE COMP "debug_data[4]" SITE "88" ;
|
||||||
|
LOCATE COMP "debug_data[5]" SITE "89" ;
|
||||||
|
LOCATE COMP "debug_data[6]" SITE "90" ;
|
||||||
|
LOCATE COMP "debug_data[7]" SITE "91" ;
|
||||||
|
BLOCK PATH FROM CLKNET "clk_c" TO CLKNET "clk_phy" ;
|
||||||
|
BLOCK PATH FROM CLKNET "clk_phy" TO CLKNET "clk_c" ;
|
206
demo/lattice_brevia2/pingable/pingable1.sty
Normal file
206
demo/lattice_brevia2/pingable/pingable1.sty
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE strategy>
|
||||||
|
<Strategy version="1.0" predefined="0" description="" label="Strategy1">
|
||||||
|
<Property name="PROP_BD_CmdLineArgs" value="" time="0"/>
|
||||||
|
<Property name="PROP_BD_EdfHardtimer" value="Enable" time="0"/>
|
||||||
|
<Property name="PROP_BD_EdfInBusNameConv" value="None" time="0"/>
|
||||||
|
<Property name="PROP_BD_EdfInLibPath" value="" time="0"/>
|
||||||
|
<Property name="PROP_BD_EdfInRemLoc" value="Off" time="0"/>
|
||||||
|
<Property name="PROP_BD_EdfMemPath" value="" time="0"/>
|
||||||
|
<Property name="PROP_BD_ParSearchPath" value="" time="0"/>
|
||||||
|
<Property name="PROP_BIT_AddressBitGen" value="Increment" time="0"/>
|
||||||
|
<Property name="PROP_BIT_AllowReadBitGen" value="Disable" time="0"/>
|
||||||
|
<Property name="PROP_BIT_ByteWideBitMirror" value="Disable" time="0"/>
|
||||||
|
<Property name="PROP_BIT_CapReadBitGen" value="Disable" time="0"/>
|
||||||
|
<Property name="PROP_BIT_ConModBitGen" value="Disable" time="0"/>
|
||||||
|
<Property name="PROP_BIT_CreateBitFile" value="True" time="0"/>
|
||||||
|
<Property name="PROP_BIT_DisRAMResBitGen" value="True" time="0"/>
|
||||||
|
<Property name="PROP_BIT_DisableUESBitgen" value="False" time="0"/>
|
||||||
|
<Property name="PROP_BIT_DonePinBitGen" value="Pullup" time="0"/>
|
||||||
|
<Property name="PROP_BIT_DoneSigBitGen" value="4" time="0"/>
|
||||||
|
<Property name="PROP_BIT_EnIOBitGen" value="TriStateDuringReConfig" time="0"/>
|
||||||
|
<Property name="PROP_BIT_EnIntOscBitGen" value="Disable" time="0"/>
|
||||||
|
<Property name="PROP_BIT_ExtClockBitGen" value="False" time="0"/>
|
||||||
|
<Property name="PROP_BIT_GSREnableBitGen" value="True" time="0"/>
|
||||||
|
<Property name="PROP_BIT_GSRRelOnBitGen" value="DoneIn" time="0"/>
|
||||||
|
<Property name="PROP_BIT_GranTimBitGen" value="0" time="0"/>
|
||||||
|
<Property name="PROP_BIT_IOTriRelBitGen" value="Cycle 2" time="0"/>
|
||||||
|
<Property name="PROP_BIT_JTAGEnableBitGen" value="False" time="0"/>
|
||||||
|
<Property name="PROP_BIT_LenBitsBitGen" value="24" time="0"/>
|
||||||
|
<Property name="PROP_BIT_MIFFileBitGen" value="" time="0"/>
|
||||||
|
<Property name="PROP_BIT_NoHeader" value="False" time="0"/>
|
||||||
|
<Property name="PROP_BIT_OutFormatBitGen" value="Bit File (Binary)" time="0"/>
|
||||||
|
<Property name="PROP_BIT_OutFormatBitGen_REF" value="Bit File (Binary)" time="0"/>
|
||||||
|
<Property name="PROP_BIT_OutFormatPromGen" value="Intel Hex 32-bit" time="0"/>
|
||||||
|
<Property name="PROP_BIT_ParityCheckBitGen" value="True" time="0"/>
|
||||||
|
<Property name="PROP_BIT_ReadBackBitGen" value="Flash" time="0"/>
|
||||||
|
<Property name="PROP_BIT_ReadCaptureBitGen" value="Disable" time="0"/>
|
||||||
|
<Property name="PROP_BIT_RemZeroFramesBitGen" value="False" time="0"/>
|
||||||
|
<Property name="PROP_BIT_RunDRCBitGen" value="True" time="0"/>
|
||||||
|
<Property name="PROP_BIT_SearchPthBitGen" value="" time="0"/>
|
||||||
|
<Property name="PROP_BIT_StartUpClkBitGen" value="Cclk" time="0"/>
|
||||||
|
<Property name="PROP_BIT_SynchIOBitGen" value="True" time="0"/>
|
||||||
|
<Property name="PROP_BIT_SysClockConBitGen" value="Reset" time="0"/>
|
||||||
|
<Property name="PROP_BIT_SysConBitGen" value="Reset" time="0"/>
|
||||||
|
<Property name="PROP_BIT_UFMOrder" value="Normal" time="0"/>
|
||||||
|
<Property name="PROP_BIT_WaitStTimBitGen" value="5" time="0"/>
|
||||||
|
<Property name="PROP_IOTIMING_AllSpeed" value="False" time="0"/>
|
||||||
|
<Property name="PROP_LST_AllowDUPMod" value="False" time="0"/>
|
||||||
|
<Property name="PROP_LST_CarryChain" value="True" time="0"/>
|
||||||
|
<Property name="PROP_LST_CarryChainLength" value="0" time="0"/>
|
||||||
|
<Property name="PROP_LST_CmdLineArgs" value="" time="0"/>
|
||||||
|
<Property name="PROP_LST_DSPStyle" value="DSP" time="0"/>
|
||||||
|
<Property name="PROP_LST_DSPUtil" value="100" time="0"/>
|
||||||
|
<Property name="PROP_LST_DecodeUnreachableStates" value="False" time="0"/>
|
||||||
|
<Property name="PROP_LST_DisableDistRam" value="False" time="0"/>
|
||||||
|
<Property name="PROP_LST_EBRUtil" value="100" time="0"/>
|
||||||
|
<Property name="PROP_LST_EdfFrequency" value="200" time="0"/>
|
||||||
|
<Property name="PROP_LST_EdfHardtimer" value="Enable" time="0"/>
|
||||||
|
<Property name="PROP_LST_EdfInLibPath" value="" time="0"/>
|
||||||
|
<Property name="PROP_LST_EdfInRemLoc" value="Off" time="0"/>
|
||||||
|
<Property name="PROP_LST_EdfMemPath" value="" time="0"/>
|
||||||
|
<Property name="PROP_LST_FIXGATEDCLKS" value="True" time="0"/>
|
||||||
|
<Property name="PROP_LST_FSMEncodeStyle" value="Auto" time="0"/>
|
||||||
|
<Property name="PROP_LST_ForceGSRInfer" value="No" time="0"/>
|
||||||
|
<Property name="PROP_LST_IOInsertion" value="True" time="0"/>
|
||||||
|
<Property name="PROP_LST_InterFileDump" value="False" time="0"/>
|
||||||
|
<Property name="PROP_LST_LoopLimit" value="1950" time="0"/>
|
||||||
|
<Property name="PROP_LST_MaxFanout" value="1000" time="0"/>
|
||||||
|
<Property name="PROP_LST_MuxStyle" value="Auto" time="0"/>
|
||||||
|
<Property name="PROP_LST_NumCriticalPaths" value="" time="0"/>
|
||||||
|
<Property name="PROP_LST_OptimizeGoal" value="Timing" time="0"/>
|
||||||
|
<Property name="PROP_LST_PropagatConst" value="True" time="0"/>
|
||||||
|
<Property name="PROP_LST_RAMStyle" value="Auto" time="0"/>
|
||||||
|
<Property name="PROP_LST_ROMStyle" value="Auto" time="0"/>
|
||||||
|
<Property name="PROP_LST_RemoveDupRegs" value="True" time="0"/>
|
||||||
|
<Property name="PROP_LST_ResolvedMixedDrivers" value="False" time="0"/>
|
||||||
|
<Property name="PROP_LST_ResourceShare" value="True" time="0"/>
|
||||||
|
<Property name="PROP_LST_UseIOReg" value="Auto" time="0"/>
|
||||||
|
<Property name="PROP_LST_UseLPF" value="True" time="0"/>
|
||||||
|
<Property name="PROP_LST_VHDL2008" value="True" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_AutoTiming" value="True" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_CheckUnconstrainedConns" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_CheckUnconstrainedPaths" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_FullName" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_NumUnconstrainedPaths" value="0" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_ReportStyle" value="Verbose Timing Report" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_RouteEstAlogtithm" value="0" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_RptAsynTimLoop" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAPSTA_WordCasePaths" value="1" time="0"/>
|
||||||
|
<Property name="PROP_MAP_IgnorePreErr" value="True" time="0"/>
|
||||||
|
<Property name="PROP_MAP_MAPIORegister" value="Auto" time="0"/>
|
||||||
|
<Property name="PROP_MAP_MAPInferGSR" value="True" time="0"/>
|
||||||
|
<Property name="PROP_MAP_MapModArgs" value="" time="0"/>
|
||||||
|
<Property name="PROP_MAP_OvermapDevice" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAP_PackLogMapDes" value="" time="0"/>
|
||||||
|
<Property name="PROP_MAP_RegRetiming" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAP_SigCrossRef" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAP_SymCrossRef" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAP_TimingDriven" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAP_TimingDrivenNodeRep" value="False" time="0"/>
|
||||||
|
<Property name="PROP_MAP_TimingDrivenPack" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_AutoTiming" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_CheckUnconstrainedConns" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_CheckUnconstrainedPaths" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_FullName" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_NumUnconstrainedPaths" value="0" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_ReportStyle" value="Verbose Timing Report" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_RptAsynTimLoop" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_SpeedForHoldAnalysis" value="m" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_SpeedForSetupAnalysis" value="default" time="0"/>
|
||||||
|
<Property name="PROP_PARSTA_WordCasePaths" value="10" time="0"/>
|
||||||
|
<Property name="PROP_PAR_CrDlyStFileParDes" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PAR_DisableTDParDes" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PAR_EffortParDes" value="5" time="0"/>
|
||||||
|
<Property name="PROP_PAR_MultiSeedSortMode" value="Worst Slack" time="0"/>
|
||||||
|
<Property name="PROP_PAR_NewRouteParDes" value="NBR" time="0"/>
|
||||||
|
<Property name="PROP_PAR_PARClockSkew" value="Off" time="0"/>
|
||||||
|
<Property name="PROP_PAR_PARModArgs" value="" time="0"/>
|
||||||
|
<Property name="PROP_PAR_ParMultiNodeList" value="" time="0"/>
|
||||||
|
<Property name="PROP_PAR_ParRunPlaceOnly" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PAR_PlcIterParDes" value="1" time="0"/>
|
||||||
|
<Property name="PROP_PAR_PlcStCostTblParDes" value="1" time="0"/>
|
||||||
|
<Property name="PROP_PAR_PrefErrorOut" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PAR_RemoveDir" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PAR_RouteDlyRedParDes" value="0" time="0"/>
|
||||||
|
<Property name="PROP_PAR_RoutePassParDes" value="6" time="0"/>
|
||||||
|
<Property name="PROP_PAR_RouteResOptParDes" value="0" time="0"/>
|
||||||
|
<Property name="PROP_PAR_RoutingCDP" value="Auto" time="0"/>
|
||||||
|
<Property name="PROP_PAR_RoutingCDR" value="1" time="0"/>
|
||||||
|
<Property name="PROP_PAR_RunParWithTrce" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PAR_RunTimeReduction" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PAR_SaveBestRsltParDes" value="1" time="0"/>
|
||||||
|
<Property name="PROP_PAR_StopZero" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PAR_parHold" value="On" time="0"/>
|
||||||
|
<Property name="PROP_PAR_parPathBased" value="Off" time="0"/>
|
||||||
|
<Property name="PROP_PRE_CmdLineArgs" value="" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfArrayBoundsCase" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfAutoResOfRam" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfClockDomainCross" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfDSPAcrossHie" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfFullCase" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfIgnoreRamRWCol" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfMissConstraint" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfNetFanout" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfParaCase" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfReencodeFSM" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfResSharing" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfTimingViolation" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfUseSafeFSM" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_EdfVlog2001" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynComArea" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynCritcal" value="3" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynFSM" value="Auto" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynFreq" value="200" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynGSR" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynGatedClk" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynIOPad" value="False" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynOutNetForm" value="None" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynOutPref" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynRepClkFreq" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynRetime" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynTimSum" value="10" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynTransform" value="True" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSyninpd" value="0" time="0"/>
|
||||||
|
<Property name="PROP_PRE_VSynoutd" value="0" time="0"/>
|
||||||
|
<Property name="PROP_SYN_ClockConversion" value="True" time="0"/>
|
||||||
|
<Property name="PROP_SYN_CmdLineArgs" value="" time="0"/>
|
||||||
|
<Property name="PROP_SYN_DisableRegisterRep" value="False" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfAllowDUPMod" value="False" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfArea" value="False" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfArrangeVHDLFiles" value="True" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfDefEnumEncode" value="Default" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfFanout" value="1000" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfFrequency" value="200" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfGSR" value="False" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfInsertIO" value="False" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfNumCritPath" value="" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfNumStartEnd" value="" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfOutNetForm" value="None" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfPushTirstates" value="True" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfResSharing" value="True" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfRunRetiming" value="Pipelining Only" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfSymFSM" value="True" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfUnconsClk" value="False" time="0"/>
|
||||||
|
<Property name="PROP_SYN_EdfVerilogInput" value="Verilog 2001" time="0"/>
|
||||||
|
<Property name="PROP_SYN_ExportSetting" value="No" time="0"/>
|
||||||
|
<Property name="PROP_SYN_LibPath" value="" time="0"/>
|
||||||
|
<Property name="PROP_SYN_ResolvedMixedDrivers" value="False" time="0"/>
|
||||||
|
<Property name="PROP_SYN_UpdateCompilePtTimData" value="False" time="0"/>
|
||||||
|
<Property name="PROP_SYN_UseLPF" value="True" time="0"/>
|
||||||
|
<Property name="PROP_SYN_VHDL2008" value="True" time="0"/>
|
||||||
|
<Property name="PROP_THERMAL_DefaultFreq" value="0" time="0"/>
|
||||||
|
<Property name="PROP_TIM_MaxDelSimDes" value="" time="0"/>
|
||||||
|
<Property name="PROP_TIM_MinSpeedGrade" value="False" time="0"/>
|
||||||
|
<Property name="PROP_TIM_ModPreSimDes" value="" time="0"/>
|
||||||
|
<Property name="PROP_TIM_NegStupHldTim" value="True" time="0"/>
|
||||||
|
<Property name="PROP_TIM_TimSimGenPUR" value="True" time="0"/>
|
||||||
|
<Property name="PROP_TIM_TimSimGenX" value="False" time="0"/>
|
||||||
|
<Property name="PROP_TIM_TimSimHierSep" value="" time="0"/>
|
||||||
|
<Property name="PROP_TIM_TransportModeOfPathDelay" value="False" time="0"/>
|
||||||
|
<Property name="PROP_TIM_TrgtSpeedGrade" value="" time="0"/>
|
||||||
|
<Property name="PROP_TIM_WriteVerboseNetlist" value="False" time="0"/>
|
||||||
|
<Property name="PROP_TMCHK_EnableCheck" value="True" time="0"/>
|
||||||
|
</Strategy>
|
@ -182,11 +182,13 @@ architecture eth of top_hwitl is
|
|||||||
constant F_CLK : integer := 50000000;
|
constant F_CLK : integer := 50000000;
|
||||||
constant F_CLK_PHY : integer := 140000000;
|
constant F_CLK_PHY : integer := 140000000;
|
||||||
|
|
||||||
constant ETH_CONFIG : configuration_t := (
|
constant ETH_CONFIG : configuration_t := (
|
||||||
mac_address => (x"00", x"ff", x"ff", x"11", x"22", x"33")
|
mac_address => (x"00", x"FF", x"FF", x"11", x"22", x"33")
|
||||||
);
|
);
|
||||||
constant IP_CONFIG : ip_configuration_t := (
|
constant IP_CONFIG : ipv4_configuration_t := (
|
||||||
ip_address => (x"C0", x"A8", x"02", x"02")
|
ip_address => (x"C0", x"A8", x"02", x"02"),
|
||||||
|
subnet_mask => (x"FF", x"FF", x"FF", x"00"),
|
||||||
|
gateway => (x"C0", x"A8", x"02", x"01")
|
||||||
);
|
);
|
||||||
|
|
||||||
signal rst : std_logic;
|
signal rst : std_logic;
|
||||||
@ -199,10 +201,10 @@ architecture eth of top_hwitl is
|
|||||||
signal mac_in : mac_in_t;
|
signal mac_in : mac_in_t;
|
||||||
|
|
||||||
constant PROT_ARP : integer := 0;
|
constant PROT_ARP : integer := 0;
|
||||||
constant PROT_IP : integer := 1;
|
constant PROT_IPV4 : integer := 1;
|
||||||
constant ETHERNET_II_PROTOCOLS : ethernet_ii_protocol_vector := (
|
constant ETHERNET_II_PROTOCOLS : ethernet_ii_protocol_vector := (
|
||||||
PROT_ARP => ETHERNET_II_PROTOCOL_ARP,
|
PROT_ARP => ETHERNET_II_PROTOCOL_ARP,
|
||||||
PROT_IP => ETHERNET_II_PROTOCOL_IP
|
PROT_IPV4 => ETHERNET_II_PROTOCOL_IPV4
|
||||||
);
|
);
|
||||||
signal ethernet_i_out : ethernet_i_out_t;
|
signal ethernet_i_out : ethernet_i_out_t;
|
||||||
signal ethernet_i_in : ethernet_i_in_t;
|
signal ethernet_i_in : ethernet_i_in_t;
|
||||||
@ -211,7 +213,53 @@ architecture eth of top_hwitl is
|
|||||||
|
|
||||||
signal arp_out : arp_out_t;
|
signal arp_out : arp_out_t;
|
||||||
signal arp_in : arp_in_t;
|
signal arp_in : arp_in_t;
|
||||||
|
|
||||||
|
signal ipv4_out : ipv4_out_t;
|
||||||
|
signal ipv4_in : ipv4_in_t;
|
||||||
|
|
||||||
|
constant IPROT_ICMP : integer := 0;
|
||||||
|
constant IPROT_UDP : integer := 1;
|
||||||
|
constant IPV4_PROTOCOLS : ipv4_protocol_vector := (
|
||||||
|
IPROT_ICMP => IPV4_PROTOCOL_ICMP,
|
||||||
|
IPROT_UDP => IPV4_PROTOCOL_UDP
|
||||||
|
);
|
||||||
|
signal ipv4_protocol_out : ipv4_protocol_out_vector(IPV4_PROTOCOLS'range);
|
||||||
|
signal ipv4_protocol_in : ipv4_protocol_in_vector(IPV4_PROTOCOLS'range);
|
||||||
begin
|
begin
|
||||||
|
trashernet_icmp_inst : entity trashernet.trashernet_icmp
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
ipv4_protocol_out => ipv4_protocol_out(IPROT_ICMP),
|
||||||
|
ipv4_protocol_in => ipv4_protocol_in(IPROT_ICMP)
|
||||||
|
);
|
||||||
|
|
||||||
|
trashernet_ipv4prot_inst : entity trashernet.trashernet_ipv4prot
|
||||||
|
generic map(
|
||||||
|
IPV4_PROTOCOLS => IPV4_PROTOCOLS
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
ipv4_out => ipv4_out,
|
||||||
|
ipv4_in => ipv4_in,
|
||||||
|
ipv4_protocol_out => ipv4_protocol_out,
|
||||||
|
ipv4_protocol_in => ipv4_protocol_in
|
||||||
|
);
|
||||||
|
|
||||||
|
trashernet_ipv4_inst : entity trashernet.trashernet_ipv4
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
ipv4_config => IP_CONFIG,
|
||||||
|
arp_out => arp_out,
|
||||||
|
arp_in => arp_in,
|
||||||
|
ethernet_ii_out => ethernet_ii_out(PROT_IPV4),
|
||||||
|
ethernet_ii_in => ethernet_ii_in(PROT_IPV4),
|
||||||
|
ipv4_out => ipv4_out,
|
||||||
|
ipv4_in => ipv4_in
|
||||||
|
);
|
||||||
|
|
||||||
trashernet_arp_inst : entity trashernet.trashernet_arp
|
trashernet_arp_inst : entity trashernet.trashernet_arp
|
||||||
generic map(
|
generic map(
|
||||||
SYSTICK_FREQ => F_CLK
|
SYSTICK_FREQ => F_CLK
|
||||||
@ -304,28 +352,94 @@ begin
|
|||||||
if (ethernet_ii_out(PROT_ARP).rx_header_rcv) then
|
if (ethernet_ii_out(PROT_ARP).rx_header_rcv) then
|
||||||
report "RX ARP";
|
report "RX ARP";
|
||||||
end if;
|
end if;
|
||||||
if (ethernet_ii_out(PROT_IP).rx_header_rcv) then
|
|
||||||
report "RX IP";
|
if ipv4_out.rx_ok_stb then
|
||||||
|
report "RX IP OK";
|
||||||
|
end if;
|
||||||
|
if ipv4_out.rx_error_stb then
|
||||||
|
report "RX IP error";
|
||||||
|
end if;
|
||||||
|
if ipv4_out.rx_header_rcv then
|
||||||
|
report "RX IP start. PROT=" & to_hstring(ipv4_out.rx_protocol) & ", FROM=" & ip_to_string(ipv4_out.rx_ip_address);
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process receiver;
|
end process receiver;
|
||||||
|
|
||||||
arp_request_test : process(clk, rst) is
|
udp : process(clk) is
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rising_edge(clk) then
|
||||||
arp_in.arp_ip <= (x"C0", x"A8", x"02", x"01");
|
if ipv4_protocol_out(IPROT_UDP).rx_header_rcv then
|
||||||
arp_in.arp_query_stb <= '0';
|
report "Receive UDP";
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
arp_in.arp_query_stb <= not button_n(0);
|
|
||||||
|
|
||||||
if arp_out.arp_ok_stb then
|
|
||||||
report "Found MAC: " & mac_to_string(arp_out.arp_mac);
|
|
||||||
end if;
|
|
||||||
if arp_out.arp_fail_stb then
|
|
||||||
report "ARP failed";
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process arp_request_test;
|
end process udp;
|
||||||
|
|
||||||
|
tx_udp_p : block
|
||||||
|
type state_t is (IDLE, TX, DONE);
|
||||||
|
signal state : state_t;
|
||||||
|
|
||||||
|
constant PACKET : byte_vector := (
|
||||||
|
x"10", x"00", -- Source port
|
||||||
|
x"04", x"00", -- Destination port
|
||||||
|
x"00", x"15", -- Length
|
||||||
|
x"00", x"00", -- Checksum (not used)
|
||||||
|
x"48", x"65", x"6C", x"6C", x"6F", x"20", x"57", x"6F", x"72", x"6C", x"64", x"21", x"0a" -- Payload
|
||||||
|
);
|
||||||
|
signal sr : byte_vector(PACKET'range);
|
||||||
|
signal cnt : integer range 0 to sr'length - 1;
|
||||||
|
|
||||||
|
begin
|
||||||
|
tx_udp : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
state <= IDLE;
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
case state is
|
||||||
|
when IDLE =>
|
||||||
|
if button_n(0) = '0' then
|
||||||
|
state <= TX;
|
||||||
|
sr <= PACKET;
|
||||||
|
cnt <= sr'length - 1;
|
||||||
|
report "UDP: Start TX";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when TX =>
|
||||||
|
if ipv4_protocol_out(IPROT_UDP).tx_data_ack then
|
||||||
|
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
||||||
|
if cnt = 0 then
|
||||||
|
state <= DONE;
|
||||||
|
else
|
||||||
|
cnt <= cnt - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
if ipv4_protocol_out(IPROT_UDP).tx_err_stb then
|
||||||
|
report "UDP: TX ERROR";
|
||||||
|
state <= DONE;
|
||||||
|
end if;
|
||||||
|
if ipv4_protocol_out(IPROT_UDP).tx_ok_stb then
|
||||||
|
report "UDP: TX OK stb in TX state -- that shouldn't happen, right?";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when DONE =>
|
||||||
|
null;
|
||||||
|
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process tx_udp;
|
||||||
|
ipv4_protocol_in(IPROT_UDP).tx_en <= '1' when state = TX else '0';
|
||||||
|
ipv4_protocol_in(IPROT_UDP).tx_ip_address <= (x"C0", x"A8", x"02", x"01");
|
||||||
|
ipv4_protocol_in(IPROT_UDP).tx_length <= to_unsigned(sr'length, 16);
|
||||||
|
ipv4_protocol_in(IPROT_UDP).tx_data <= sr(0);
|
||||||
|
end block tx_udp_p;
|
||||||
|
|
||||||
|
icmp : process(clk) is
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if ipv4_protocol_out(IPROT_ICMP).rx_header_rcv then
|
||||||
|
report "Receive ICMP";
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process icmp;
|
||||||
|
|
||||||
end architecture eth;
|
end architecture eth;
|
||||||
|
248
design/top_pingable.vhd
Normal file
248
design/top_pingable.vhd
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- top_mac_test.vhd: Test design to verify the functionality of the MAC core
|
||||||
|
-- Sends a broadcast with 100 decrementing numbers every 250 ms or when a
|
||||||
|
-- button is pushed. It will also directly reply with that content to any
|
||||||
|
-- packet addressed to us.
|
||||||
|
--
|
||||||
|
-- Target: Lattice Brevia 2 (LFXP2-5E)
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
library trashernet;
|
||||||
|
use trashernet.trashernet_pkg.all;
|
||||||
|
|
||||||
|
entity top_pingable is
|
||||||
|
port(
|
||||||
|
clk : in std_logic;
|
||||||
|
rst_n : in std_logic;
|
||||||
|
rx_p : in std_logic;
|
||||||
|
tx_p : out std_logic;
|
||||||
|
tx_n : out std_logic;
|
||||||
|
led_n : out std_logic_vector(7 downto 0);
|
||||||
|
button_n : in std_logic_vector(3 downto 0);
|
||||||
|
debug_data : out std_logic_vector(7 downto 0)
|
||||||
|
);
|
||||||
|
end entity top_pingable;
|
||||||
|
|
||||||
|
architecture rtl of top_pingable is
|
||||||
|
component pll0
|
||||||
|
port(
|
||||||
|
CLK : in std_logic;
|
||||||
|
CLKOP : out std_logic;
|
||||||
|
LOCK : out std_logic
|
||||||
|
);
|
||||||
|
end component pll0;
|
||||||
|
|
||||||
|
constant F_CLK : integer := 50000000;
|
||||||
|
constant F_CLK_PHY : integer := 140000000;
|
||||||
|
|
||||||
|
constant LED_BLINK : boolean_vector(led_n'range) := (
|
||||||
|
6 downto 2 => true,
|
||||||
|
others => false
|
||||||
|
);
|
||||||
|
|
||||||
|
constant ETH_CONFIG : configuration_t := (
|
||||||
|
mac_address => (x"00", x"FF", x"FF", x"11", x"22", x"44")
|
||||||
|
);
|
||||||
|
constant IP_CONFIG : ipv4_configuration_t := (
|
||||||
|
ip_address => (x"C0", x"A8", x"02", x"02"),
|
||||||
|
subnet_mask => (x"FF", x"FF", x"FF", x"00"),
|
||||||
|
gateway => (x"C0", x"A8", x"02", x"01")
|
||||||
|
);
|
||||||
|
|
||||||
|
signal rst : std_logic;
|
||||||
|
signal clk_phy : std_logic;
|
||||||
|
signal phy_pll_lock : std_logic;
|
||||||
|
|
||||||
|
signal led_sig : std_logic_vector(led_n'range);
|
||||||
|
|
||||||
|
signal phy_out : phy_out_t;
|
||||||
|
signal phy_in : phy_in_t;
|
||||||
|
|
||||||
|
signal mac_out : mac_out_t;
|
||||||
|
signal mac_in : mac_in_t;
|
||||||
|
|
||||||
|
constant PROT_ARP : integer := 0;
|
||||||
|
constant PROT_IPV4 : integer := 1;
|
||||||
|
constant ETHERNET_II_PROTOCOLS : ethernet_ii_protocol_vector := (
|
||||||
|
PROT_ARP => ETHERNET_II_PROTOCOL_ARP,
|
||||||
|
PROT_IPV4 => ETHERNET_II_PROTOCOL_IPV4
|
||||||
|
);
|
||||||
|
signal ethernet_i_out : ethernet_i_out_t;
|
||||||
|
signal ethernet_i_in : ethernet_i_in_t;
|
||||||
|
signal ethernet_ii_out : ethernet_ii_out_vector(ETHERNET_II_PROTOCOLS'range);
|
||||||
|
signal ethernet_ii_in : ethernet_ii_in_vector(ETHERNET_II_PROTOCOLS'range);
|
||||||
|
|
||||||
|
signal arp_out : arp_out_t;
|
||||||
|
signal arp_in : arp_in_t;
|
||||||
|
|
||||||
|
signal ipv4_out : ipv4_out_t;
|
||||||
|
signal ipv4_in : ipv4_in_t;
|
||||||
|
|
||||||
|
constant IPROT_ICMP : integer := 0;
|
||||||
|
constant IPV4_PROTOCOLS : ipv4_protocol_vector := (
|
||||||
|
IPROT_ICMP => IPV4_PROTOCOL_ICMP
|
||||||
|
);
|
||||||
|
signal ipv4_protocol_out : ipv4_protocol_out_vector(IPV4_PROTOCOLS'range);
|
||||||
|
signal ipv4_protocol_in : ipv4_protocol_in_vector(IPV4_PROTOCOLS'range);
|
||||||
|
|
||||||
|
signal button_n_sync : std_logic_vector(button_n'range);
|
||||||
|
signal button : std_logic_vector(button_n'range);
|
||||||
|
begin
|
||||||
|
trashernet_icmp_inst : entity trashernet.trashernet_icmp
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
ipv4_protocol_out => ipv4_protocol_out(IPROT_ICMP),
|
||||||
|
ipv4_protocol_in => ipv4_protocol_in(IPROT_ICMP)
|
||||||
|
);
|
||||||
|
|
||||||
|
trashernet_ipv4prot_inst : entity trashernet.trashernet_ipv4prot
|
||||||
|
generic map(
|
||||||
|
IPV4_PROTOCOLS => IPV4_PROTOCOLS
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
ipv4_out => ipv4_out,
|
||||||
|
ipv4_in => ipv4_in,
|
||||||
|
ipv4_protocol_out => ipv4_protocol_out,
|
||||||
|
ipv4_protocol_in => ipv4_protocol_in
|
||||||
|
);
|
||||||
|
|
||||||
|
trashernet_ipv4_inst : entity trashernet.trashernet_ipv4
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
ipv4_config => IP_CONFIG,
|
||||||
|
arp_out => arp_out,
|
||||||
|
arp_in => arp_in,
|
||||||
|
ethernet_ii_out => ethernet_ii_out(PROT_IPV4),
|
||||||
|
ethernet_ii_in => ethernet_ii_in(PROT_IPV4),
|
||||||
|
ipv4_out => ipv4_out,
|
||||||
|
ipv4_in => ipv4_in
|
||||||
|
);
|
||||||
|
|
||||||
|
trashernet_arp_inst : entity trashernet.trashernet_arp
|
||||||
|
generic map(
|
||||||
|
SYSTICK_FREQ => F_CLK
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
systick => '1',
|
||||||
|
mac_config => ETH_CONFIG,
|
||||||
|
ip_config => IP_CONFIG,
|
||||||
|
arp_out => arp_out,
|
||||||
|
arp_in => arp_in,
|
||||||
|
ethernet_ii_out => ethernet_ii_out(PROT_ARP),
|
||||||
|
ethernet_ii_in => ethernet_ii_in(PROT_ARP)
|
||||||
|
);
|
||||||
|
|
||||||
|
ethernet_i_in <= ETHERNET_I_IN_UNUSED;
|
||||||
|
|
||||||
|
trashernet_eth_inst : entity trashernet.trashernet_eth
|
||||||
|
generic map(
|
||||||
|
ETHERNET_II_PROTOCOLS => ETHERNET_II_PROTOCOLS
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
mac_out => mac_out,
|
||||||
|
mac_in => mac_in,
|
||||||
|
config => ETH_CONFIG,
|
||||||
|
ethernet_i_out => ethernet_i_out,
|
||||||
|
ethernet_i_in => ethernet_i_in,
|
||||||
|
ethernet_ii_out => ethernet_ii_out,
|
||||||
|
ethernet_ii_in => ethernet_ii_in
|
||||||
|
);
|
||||||
|
|
||||||
|
trashernet_mac_inst : entity trashernet.trashernet_mac
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
phy_out => phy_out,
|
||||||
|
phy_in => phy_in,
|
||||||
|
mac_out => mac_out,
|
||||||
|
mac_in => mac_in
|
||||||
|
);
|
||||||
|
|
||||||
|
pll0_inst : pll0
|
||||||
|
port map(
|
||||||
|
CLK => clk,
|
||||||
|
CLKOP => clk_phy,
|
||||||
|
LOCK => phy_pll_lock
|
||||||
|
);
|
||||||
|
|
||||||
|
trashernet_phy_cdc_inst : entity trashernet.trashernet_phy_cdc
|
||||||
|
generic map(
|
||||||
|
F_CLK => F_CLK,
|
||||||
|
F_CLK_PHY => F_CLK_PHY
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
phy_clk => clk_phy,
|
||||||
|
rst => rst,
|
||||||
|
phy_out => phy_out,
|
||||||
|
phy_in => phy_in,
|
||||||
|
rx_p => rx_p,
|
||||||
|
tx_p => tx_p,
|
||||||
|
tx_n => tx_n
|
||||||
|
);
|
||||||
|
|
||||||
|
reset_sync : process(clk, rst_n) is
|
||||||
|
begin
|
||||||
|
if (rst_n = '0') then
|
||||||
|
rst <= '1';
|
||||||
|
elsif (rising_edge(clk)) then
|
||||||
|
rst <= '0';
|
||||||
|
end if;
|
||||||
|
end process reset_sync;
|
||||||
|
|
||||||
|
ledcon_inst : entity work.ledcon
|
||||||
|
generic map(
|
||||||
|
F_CLK => F_CLK,
|
||||||
|
BLINK => LED_BLINK
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
sig => led_sig,
|
||||||
|
led_n => led_n
|
||||||
|
);
|
||||||
|
|
||||||
|
led_sig <= (
|
||||||
|
0 => phy_pll_lock,
|
||||||
|
1 => phy_out.carrier_detect,
|
||||||
|
2 => phy_out.rx_active,
|
||||||
|
3 => phy_out.rx_error,
|
||||||
|
4 => mac_out.rx_mac_crc_ok,
|
||||||
|
5 => mac_out.rx_mac_crc_error,
|
||||||
|
6 => mac_out.tx_active,
|
||||||
|
7 => '0'
|
||||||
|
);
|
||||||
|
|
||||||
|
synchronizer_inst : entity trashernet.synchronizer
|
||||||
|
generic map(
|
||||||
|
SIZE => 2
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
data_in => button_n(0),
|
||||||
|
data_out => button_n_sync(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
button <= not button_n_sync;
|
||||||
|
end architecture rtl;
|
98
trashernet/fifo.vhd
Normal file
98
trashernet/fifo.vhd
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- fifo.vhd : Basic single-clock FIFO
|
||||||
|
-- Implements a basic single-clock FIFO
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- 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 fifo is
|
||||||
|
generic(
|
||||||
|
DEPTH : natural -- Number of elements the FIFO can hold
|
||||||
|
);
|
||||||
|
port(
|
||||||
|
-- Global
|
||||||
|
clk : in std_logic; -- Global clock
|
||||||
|
rst : in std_logic; -- Asynchronous reset
|
||||||
|
|
||||||
|
-- FIFO
|
||||||
|
clear : in std_logic; -- Synchronous reset (clear FIFO)
|
||||||
|
data_in : in std_logic_vector; -- Data into the FIFO (automatically constrains width)
|
||||||
|
push : in std_logic; -- Push `data_in` into the FIFO
|
||||||
|
full : out std_logic; -- No further elements can be pushed into the FIFO
|
||||||
|
data_out : out std_logic_vector; -- Data out of the FIFO
|
||||||
|
pop : in std_logic; -- Get an element from the FIFO
|
||||||
|
empty : out std_logic -- FIFO is empty
|
||||||
|
);
|
||||||
|
end entity fifo;
|
||||||
|
|
||||||
|
architecture rtl of fifo is
|
||||||
|
type memory_t is array (natural range <>) of std_logic_vector(data_in'range);
|
||||||
|
signal memory : memory_t(0 to DEPTH - 1);
|
||||||
|
|
||||||
|
subtype memory_pointer_t is integer range 0 to DEPTH - 1;
|
||||||
|
subtype usage_counter_t is integer range 0 to DEPTH;
|
||||||
|
|
||||||
|
signal read_pointer : memory_pointer_t;
|
||||||
|
signal write_pointer : memory_pointer_t;
|
||||||
|
signal usage_counter : usage_counter_t;
|
||||||
|
begin
|
||||||
|
fifo_proc : process(clk, rst) is
|
||||||
|
procedure increment_pointer(signal pointer : inout memory_pointer_t) is
|
||||||
|
begin
|
||||||
|
if pointer = pointer'subtype'high then
|
||||||
|
pointer <= 0;
|
||||||
|
else
|
||||||
|
pointer <= pointer + 1;
|
||||||
|
end if;
|
||||||
|
end procedure increment_pointer;
|
||||||
|
|
||||||
|
variable pushed : boolean;
|
||||||
|
variable popped : boolean;
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
read_pointer <= 0;
|
||||||
|
write_pointer <= 0;
|
||||||
|
usage_counter <= 0;
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
pushed := false;
|
||||||
|
popped := false;
|
||||||
|
|
||||||
|
if push and not full then
|
||||||
|
memory(write_pointer) <= data_in;
|
||||||
|
increment_pointer(write_pointer);
|
||||||
|
usage_counter <= usage_counter + 1;
|
||||||
|
pushed := true;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if pop and not empty then
|
||||||
|
increment_pointer(read_pointer);
|
||||||
|
usage_counter <= usage_counter - 1;
|
||||||
|
popped := true;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if pushed and popped then
|
||||||
|
usage_counter <= usage_counter;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if clear then
|
||||||
|
read_pointer <= 0;
|
||||||
|
write_pointer <= 0;
|
||||||
|
usage_counter <= 0;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process fifo_proc;
|
||||||
|
|
||||||
|
data_out <= memory(read_pointer);
|
||||||
|
empty <= '1' when usage_counter = 0 else '0';
|
||||||
|
full <= '1' when usage_counter = DEPTH else '0';
|
||||||
|
|
||||||
|
end architecture rtl;
|
@ -27,7 +27,7 @@ entity trashernet_arp is
|
|||||||
|
|
||||||
-- Configuration
|
-- Configuration
|
||||||
mac_config : in configuration_t; -- Trashernet MAC configuration
|
mac_config : in configuration_t; -- Trashernet MAC configuration
|
||||||
ip_config : in ip_configuration_t; -- Trashernet IP configuration
|
ip_config : in ipv4_configuration_t; -- Trashernet IP configuration
|
||||||
|
|
||||||
-- ARP application interface
|
-- ARP application interface
|
||||||
arp_out : out arp_out_t; -- ARP IF (out from ARP)
|
arp_out : out arp_out_t; -- ARP IF (out from ARP)
|
||||||
|
@ -120,6 +120,7 @@ begin
|
|||||||
arb : process(clk, rst) is
|
arb : process(clk, rst) is
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
|
sel <= SEL_ETH_I;
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
case state is
|
case state is
|
||||||
@ -140,7 +141,7 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
when TXD =>
|
when TXD =>
|
||||||
state <= IDLE when (mac_in.tx_mac_data_en or not mac_out.tx_active);
|
state <= IDLE when (not mac_in.tx_mac_data_en or not mac_out.tx_active);
|
||||||
end case;
|
end case;
|
||||||
end if;
|
end if;
|
||||||
end process arb;
|
end process arb;
|
||||||
|
172
trashernet/trashernet_icmp.vhd
Normal file
172
trashernet/trashernet_icmp.vhd
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- trashernet_icmp.vhd : Ethernet OSI Layer 3, Network (ICMP)
|
||||||
|
-- Implements ICMP echo replies
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- 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.trashernet_pkg.all;
|
||||||
|
|
||||||
|
entity trashernet_icmp is
|
||||||
|
port(
|
||||||
|
-- Global
|
||||||
|
clk : in std_logic; -- Global clock
|
||||||
|
rst : in std_logic; -- Asynchronous reset
|
||||||
|
|
||||||
|
-- IPv4 application interface
|
||||||
|
ipv4_protocol_out : in ipv4_protocol_out_t; -- IPv4 Protocol IF (out from IP Mux)
|
||||||
|
ipv4_protocol_in : out ipv4_protocol_in_t -- IPv4 Protocol IF (into IP Mux)
|
||||||
|
);
|
||||||
|
end entity trashernet_icmp;
|
||||||
|
|
||||||
|
architecture rtl of trashernet_icmp is
|
||||||
|
signal fifo_clear : std_logic;
|
||||||
|
signal fifo_data_in : std_logic_vector(byte'range);
|
||||||
|
signal fifo_push : std_logic;
|
||||||
|
signal fifo_full : std_logic; -- TODO: FIFO full error handling
|
||||||
|
signal fifo_data_out : std_logic_vector(fifo_data_in'range);
|
||||||
|
signal fifo_pop : std_logic;
|
||||||
|
signal fifo_empty : std_logic;
|
||||||
|
|
||||||
|
signal tx_response : std_logic;
|
||||||
|
signal rx_checksum : std_logic_vector(15 downto 0);
|
||||||
|
begin
|
||||||
|
fifo_inst : entity work.fifo
|
||||||
|
generic map(
|
||||||
|
DEPTH => 64
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
clear => fifo_clear,
|
||||||
|
data_in => fifo_data_in,
|
||||||
|
push => fifo_push,
|
||||||
|
full => fifo_full,
|
||||||
|
data_out => fifo_data_out,
|
||||||
|
pop => fifo_pop,
|
||||||
|
empty => fifo_empty
|
||||||
|
);
|
||||||
|
|
||||||
|
rx : block
|
||||||
|
signal sr : byte_vector(0 to 3);
|
||||||
|
alias sr_type is sr(0);
|
||||||
|
alias sr_code is sr(1);
|
||||||
|
alias sr_checksum is sr(2 to 3);
|
||||||
|
|
||||||
|
type state_t is (HEADER, DATA, IGNORE);
|
||||||
|
signal state : state_t;
|
||||||
|
|
||||||
|
signal byte_count : integer range 0 to sr'length;
|
||||||
|
|
||||||
|
begin
|
||||||
|
rx_fsm : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
state <= HEADER;
|
||||||
|
byte_count <= byte_count'subtype'high;
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
|
||||||
|
if (ipv4_protocol_out.rx_data_valid = '1') and (byte_count /= 0) then
|
||||||
|
byte_count <= byte_count - 1;
|
||||||
|
if state = HEADER then
|
||||||
|
sr <= sr(sr'low + 1 to sr'high) & ipv4_protocol_out.rx_data;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if ipv4_protocol_out.rx_header_rcv then
|
||||||
|
byte_count <= byte_count'subtype'high;
|
||||||
|
state <= HEADER;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
case state is
|
||||||
|
when HEADER =>
|
||||||
|
if byte_count = 0 then
|
||||||
|
if sr_type = x"08" then
|
||||||
|
state <= DATA;
|
||||||
|
else
|
||||||
|
state <= IGNORE;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when DATA =>
|
||||||
|
null; -- We just wait here and collect data
|
||||||
|
|
||||||
|
when IGNORE => -- Just wait until it's over
|
||||||
|
null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process rx_fsm;
|
||||||
|
fifo_clear <= ipv4_protocol_out.rx_header_rcv; -- TODO: This will break things when we get another Ping too soon
|
||||||
|
fifo_push <= ipv4_protocol_out.rx_data_valid when state = DATA else '0';
|
||||||
|
fifo_data_in <= ipv4_protocol_out.rx_data;
|
||||||
|
|
||||||
|
tx_response <= ipv4_protocol_out.rx_ok_stb when state = DATA else '0';
|
||||||
|
rx_checksum <= sr_checksum(2) & sr_checksum(3);
|
||||||
|
end block rx;
|
||||||
|
|
||||||
|
tx : block
|
||||||
|
signal checksum : unsigned(16 downto 0);
|
||||||
|
signal checksum_ones : unsigned(15 downto 0);
|
||||||
|
|
||||||
|
type state_t is (IDLE, HEADER, PAYLOAD);
|
||||||
|
signal state : state_t;
|
||||||
|
|
||||||
|
signal sr : byte_vector(0 to 3);
|
||||||
|
signal byte_count : integer range 0 to sr'subtype'high;
|
||||||
|
begin
|
||||||
|
|
||||||
|
checksum <= ('0' & not (unsigned(rx_checksum))) - unsigned'('0' & x"0800"); -- The only change is Type 8 changes to Type 0
|
||||||
|
checksum_ones <= not (checksum(15 downto 0) - checksum(16));
|
||||||
|
|
||||||
|
tx_fsm : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if (ipv4_protocol_out.tx_data_ack = '1') and (byte_count /= 0) then
|
||||||
|
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
||||||
|
byte_count <= byte_count - 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
case state is
|
||||||
|
when IDLE =>
|
||||||
|
if tx_response then
|
||||||
|
ipv4_protocol_in.tx_ip_address <= ipv4_protocol_out.rx_ip_address; -- TODO: This is technically too late, but ¯\_(ツ)_/¯
|
||||||
|
ipv4_protocol_in.tx_length <= ipv4_protocol_out.rx_length;
|
||||||
|
sr <= byte_vector'(
|
||||||
|
x"00",
|
||||||
|
x"00",
|
||||||
|
std_logic_vector(checksum_ones(15 downto 8)),
|
||||||
|
std_logic_vector(checksum_ones(7 downto 0))
|
||||||
|
);
|
||||||
|
byte_count <= sr'subtype'high;
|
||||||
|
state <= HEADER;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when HEADER =>
|
||||||
|
if (byte_count = 0) and (ipv4_protocol_out.tx_data_ack = '1') then
|
||||||
|
state <= PAYLOAD;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when PAYLOAD =>
|
||||||
|
if fifo_empty then
|
||||||
|
state <= IDLE;
|
||||||
|
end if;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process tx_fsm;
|
||||||
|
|
||||||
|
fifo_pop <= ipv4_protocol_out.tx_data_ack when state = PAYLOAD else '0';
|
||||||
|
ipv4_protocol_in.tx_en <= '1' when (state = HEADER) or (state = PAYLOAD) else '0';
|
||||||
|
ipv4_protocol_in.tx_data <= sr(sr'low) when state = HEADER else fifo_data_out;
|
||||||
|
end block tx;
|
||||||
|
end architecture rtl;
|
249
trashernet/trashernet_ipv4.vhd
Normal file
249
trashernet/trashernet_ipv4.vhd
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- trashernet_ipv4.vhd : Ethernet OSI Layer 3, Network (IPv4)
|
||||||
|
-- Implements packet handling and IP-Layer en-/decoding.
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- 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.trashernet_pkg.all;
|
||||||
|
|
||||||
|
entity trashernet_ipv4 is
|
||||||
|
port(
|
||||||
|
-- Global
|
||||||
|
clk : in std_logic; -- Global clock
|
||||||
|
rst : in std_logic; -- Asynchronous reset
|
||||||
|
|
||||||
|
-- Configuration
|
||||||
|
ipv4_config : in ipv4_configuration_t; -- Trashernet IP configuration
|
||||||
|
|
||||||
|
-- ARP application interface
|
||||||
|
arp_out : in arp_out_t; -- ARP IF (out from ARP)
|
||||||
|
arp_in : out arp_in_t; -- ARP IF (into ARP)
|
||||||
|
|
||||||
|
-- Ethernet II application interface
|
||||||
|
ethernet_ii_out : in ethernet_ii_out_t; -- Ethernet II IF (out from MAC)
|
||||||
|
ethernet_ii_in : out ethernet_ii_in_t; -- Ethernet II IF (into MAC)
|
||||||
|
|
||||||
|
-- IPv4 application interface
|
||||||
|
ipv4_out : out ipv4_out_t; -- IPv4 IF (out from IP)
|
||||||
|
ipv4_in : in ipv4_in_t -- IPv4 IF (into IP)
|
||||||
|
);
|
||||||
|
end entity trashernet_ipv4;
|
||||||
|
|
||||||
|
architecture rtl of trashernet_ipv4 is
|
||||||
|
begin
|
||||||
|
rx : block
|
||||||
|
constant BYTECOUNT_HEADER : integer := 20; -- Mandatory header fields
|
||||||
|
|
||||||
|
signal sr : byte_vector(0 to BYTECOUNT_HEADER - 1) := (others => x"00"); -- Init to zero to squelch metavalue warnings
|
||||||
|
alias sr_version is sr(0)(7 downto 4);
|
||||||
|
alias sr_ihl is sr(0)(3 downto 0);
|
||||||
|
alias sr_dscp is sr(1)(7 downto 2);
|
||||||
|
alias sr_ecn is sr(1)(1 downto 0);
|
||||||
|
alias sr_total_length is sr(2 to 3);
|
||||||
|
alias sr_identification is sr(4 to 5);
|
||||||
|
alias sr_flags is sr(6)(7 downto 5);
|
||||||
|
signal sr_fragment_offset : std_logic_vector(12 downto 0);
|
||||||
|
alias sr_ttl is sr(8);
|
||||||
|
alias sr_protocol is sr(9);
|
||||||
|
alias sr_header_cks is sr(10 to 11);
|
||||||
|
alias sr_source_ip is sr(12 to 15);
|
||||||
|
alias sr_destination_ip is sr(16 to 19);
|
||||||
|
|
||||||
|
signal header_ok : std_logic;
|
||||||
|
|
||||||
|
signal bytecount : integer range 0 to 65535;
|
||||||
|
signal block_done : std_logic;
|
||||||
|
|
||||||
|
type state_t is (HEADER, OPT, PAYLOAD, DONE);
|
||||||
|
signal state : state_t;
|
||||||
|
begin
|
||||||
|
sr_fragment_offset <= sr(6)(4 downto 0) & sr(7);
|
||||||
|
|
||||||
|
block_done <= '1' when bytecount = 0 else '0';
|
||||||
|
header_ok <= '1' when --
|
||||||
|
(std_logic_vector'(sr_flags(7) & sr_flags(5)) = "00") and -- Reserved = 0, MF unset
|
||||||
|
(to_integer(unsigned(sr_fragment_offset)) = 0) and -- No fragment offset -> not last fragment
|
||||||
|
(sr_destination_ip = ipv4_config.ip_address) else -- It's addressed to us. TODO: We do not support broadcasts
|
||||||
|
'0';
|
||||||
|
rx_fsm : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
state <= HEADER;
|
||||||
|
ipv4_out.rx_ok_stb <= '0';
|
||||||
|
ipv4_out.rx_error_stb <= '0';
|
||||||
|
ipv4_out.rx_header_rcv <= '0';
|
||||||
|
bytecount <= BYTECOUNT_HEADER;
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
ipv4_out.rx_ok_stb <= '0';
|
||||||
|
ipv4_out.rx_error_stb <= '0';
|
||||||
|
ipv4_out.rx_header_rcv <= '0';
|
||||||
|
|
||||||
|
if (ethernet_ii_out.rx_crc_ok or ethernet_ii_out.rx_crc_error) then
|
||||||
|
state <= HEADER;
|
||||||
|
bytecount <= BYTECOUNT_HEADER;
|
||||||
|
|
||||||
|
ipv4_out.rx_error_stb <= ethernet_ii_out.rx_crc_error or to_std_logic(state = PAYLOAD);
|
||||||
|
ipv4_out.rx_ok_stb <= ethernet_ii_out.rx_crc_ok and to_std_logic(state = DONE);
|
||||||
|
end if;
|
||||||
|
if (ethernet_ii_out.rx_data_valid = '1') and (bytecount > 0) then
|
||||||
|
if state = HEADER then
|
||||||
|
sr <= sr(sr'low + 1 to sr'high) & ethernet_ii_out.rx_data;
|
||||||
|
end if;
|
||||||
|
bytecount <= bytecount - 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
case state is
|
||||||
|
when HEADER =>
|
||||||
|
if block_done then
|
||||||
|
bytecount <= to_integer(unsigned(sr_ihl) - 5) * 4; -- five 32-bit words is the header itself
|
||||||
|
if header_ok then
|
||||||
|
state <= OPT;
|
||||||
|
ipv4_out.rx_header_rcv <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when OPT =>
|
||||||
|
if block_done then
|
||||||
|
bytecount <= to_integer(unsigned(std_logic_vector'(sr_total_length(2) & sr_total_length(3)))) - to_integer(unsigned(sr_ihl)) * 4;
|
||||||
|
state <= PAYLOAD;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when PAYLOAD =>
|
||||||
|
if block_done then
|
||||||
|
state <= DONE;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when DONE => -- @suppress "Dead state 'DONE'": Outgoing state transition is outside of case statement
|
||||||
|
null; -- We just wait here until the MAC gives us a CRC OK/error
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process rx_fsm;
|
||||||
|
|
||||||
|
ipv4_out.rx_data <= ethernet_ii_out.rx_data;
|
||||||
|
ipv4_out.rx_data_valid <= ethernet_ii_out.rx_data_valid when state = PAYLOAD else '0';
|
||||||
|
ipv4_out.rx_ip_address <= sr_source_ip;
|
||||||
|
ipv4_out.rx_protocol <= sr_protocol;
|
||||||
|
ipv4_out.rx_length <= unsigned(std_logic_vector'(sr_total_length(2) & sr_total_length(3))) - to_integer(unsigned(sr_ihl)) * 4;
|
||||||
|
|
||||||
|
end block rx;
|
||||||
|
|
||||||
|
tx : block
|
||||||
|
type state_t is (IDLE, ARP, CALC_CKS, HEADER, PAYLOAD);
|
||||||
|
signal state : state_t;
|
||||||
|
|
||||||
|
signal full_length : ipv4_length;
|
||||||
|
|
||||||
|
signal sr : byte_vector(0 to 19);
|
||||||
|
signal byte_cnt : integer range 0 to sr'length - 1;
|
||||||
|
signal alt_byte : std_logic;
|
||||||
|
signal checksum : unsigned(20 downto 0); -- 20 Header fields -> 19 chances for carry -> 5 additional bits
|
||||||
|
signal checksum_ones : unsigned(15 downto 0);
|
||||||
|
|
||||||
|
constant TTL : byte := x"40";
|
||||||
|
impure function get_header(checksum : std_logic_vector(15 downto 0)) return byte_vector is
|
||||||
|
variable ret : byte_vector(sr'range);
|
||||||
|
begin
|
||||||
|
ret := --
|
||||||
|
byte_vector'(
|
||||||
|
x"45", x"00", byte(full_length(15 downto 8)), byte(full_length(7 downto 0)), -- Ver/IHL, DSCP/ECN, Len
|
||||||
|
x"00", x"00", x"00", x"00" -- Identification, Flags/FragOffset
|
||||||
|
) & TTL & ipv4_in.tx_protocol & checksum(15 downto 8) & checksum(7 downto 0) & -- TTL, Protocol, Header Checksum
|
||||||
|
ipv4_config.ip_address & -- Source IP
|
||||||
|
ipv4_in.tx_ip_address -- Destination IP
|
||||||
|
;
|
||||||
|
return ret;
|
||||||
|
end function get_header;
|
||||||
|
begin
|
||||||
|
full_length <= sr'length + ipv4_in.tx_length;
|
||||||
|
checksum_ones <= checksum(15 downto 0) + checksum(checksum'high downto 16);
|
||||||
|
|
||||||
|
tx_fsm : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
state <= IDLE;
|
||||||
|
ipv4_out.tx_data_ack <= '0';
|
||||||
|
arp_in.arp_query_stb <= '0';
|
||||||
|
ipv4_out.tx_err_stb <= '0';
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
arp_in.arp_query_stb <= '0';
|
||||||
|
ipv4_out.tx_data_ack <= '0';
|
||||||
|
ipv4_out.tx_err_stb <= '0';
|
||||||
|
|
||||||
|
if (ethernet_ii_out.tx_data_ack = '1') or (state = CALC_CKS) then
|
||||||
|
if byte_cnt > 0 then
|
||||||
|
byte_cnt <= byte_cnt - 1;
|
||||||
|
end if;
|
||||||
|
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
case state is
|
||||||
|
when IDLE =>
|
||||||
|
if ipv4_in.tx_en then
|
||||||
|
arp_in.arp_query_stb <= '1';
|
||||||
|
state <= ARP;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ARP =>
|
||||||
|
if arp_out.arp_ok_stb then
|
||||||
|
ethernet_ii_in.tx_mac_address <= arp_out.arp_mac;
|
||||||
|
|
||||||
|
byte_cnt <= sr'length - 1;
|
||||||
|
sr <= get_header(x"0000");
|
||||||
|
alt_byte <= '1';
|
||||||
|
checksum <= (others => '0');
|
||||||
|
state <= CALC_CKS;
|
||||||
|
end if;
|
||||||
|
if arp_out.arp_fail_stb then
|
||||||
|
ipv4_out.tx_err_stb <= '1';
|
||||||
|
-- Then we lock up in this state until tx_en is disabled
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when CALC_CKS =>
|
||||||
|
alt_byte <= not alt_byte;
|
||||||
|
|
||||||
|
if alt_byte then
|
||||||
|
checksum <= checksum + unsigned(std_logic_vector'(sr(sr'low) & sr(sr'low + 1)));
|
||||||
|
else
|
||||||
|
if byte_cnt = 0 then
|
||||||
|
state <= HEADER;
|
||||||
|
byte_cnt <= sr'length - 1;
|
||||||
|
sr <= get_header(not std_logic_vector(checksum_ones));
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when HEADER =>
|
||||||
|
if byte_cnt = 0 then
|
||||||
|
state <= PAYLOAD;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when PAYLOAD =>
|
||||||
|
if ethernet_ii_out.tx_data_ack then
|
||||||
|
sr(sr'low) <= ipv4_in.tx_data;
|
||||||
|
ipv4_out.tx_data_ack <= '1';
|
||||||
|
if not ipv4_in.tx_en then
|
||||||
|
state <= IDLE;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process tx_fsm;
|
||||||
|
|
||||||
|
ethernet_ii_in.tx_data <= sr(sr'low);
|
||||||
|
ethernet_ii_in.tx_en <= '1' when (state = HEADER) or (state = PAYLOAD) else '0';
|
||||||
|
|
||||||
|
arp_in.arp_ip <= ipv4_in.tx_ip_address;
|
||||||
|
|
||||||
|
end block tx;
|
||||||
|
|
||||||
|
end architecture rtl;
|
122
trashernet/trashernet_ipv4prot.vhd
Normal file
122
trashernet/trashernet_ipv4prot.vhd
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- trashernet_eth.vhd : Ethernet OSI Layer 3, Network, Protocol Muxing
|
||||||
|
-- Implements arbitration of different IP protocols.
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- 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.trashernet_pkg.all;
|
||||||
|
|
||||||
|
entity trashernet_ipv4prot is
|
||||||
|
generic(
|
||||||
|
IPV4_PROTOCOLS : ipv4_protocol_vector
|
||||||
|
);
|
||||||
|
port(
|
||||||
|
-- Global
|
||||||
|
clk : in std_logic; -- Global clock
|
||||||
|
rst : in std_logic; -- Asynchronous reset
|
||||||
|
|
||||||
|
-- IPv4 application interface
|
||||||
|
ipv4_out : in ipv4_out_t; -- IPv4 IF (out from IP)
|
||||||
|
ipv4_in : out ipv4_in_t; -- IPv4 IF (into IP)
|
||||||
|
|
||||||
|
-- IPv4 protocol interface
|
||||||
|
ipv4_protocol_out : out ipv4_protocol_out_vector(IPV4_PROTOCOLS'range); -- IPv4 Protocol IF (out from IP Mux)
|
||||||
|
ipv4_protocol_in : in ipv4_protocol_in_vector(IPV4_PROTOCOLS'range) -- IPv4 Protocol IF (into IP Mux)
|
||||||
|
);
|
||||||
|
end entity trashernet_ipv4prot;
|
||||||
|
|
||||||
|
architecture rtl of trashernet_ipv4prot is
|
||||||
|
constant SEL_PROTOCOL_NONE : integer := ipv4_protocol_out'low - 1;
|
||||||
|
|
||||||
|
signal rx_sel : integer range SEL_PROTOCOL_NONE to ipv4_protocol_out'high;
|
||||||
|
signal tx_sel : integer range ipv4_protocol_in'low to ipv4_protocol_in'high;
|
||||||
|
|
||||||
|
begin
|
||||||
|
rx : block
|
||||||
|
signal rx_header_rcv_delayed : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
arb : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
rx_sel <= SEL_PROTOCOL_NONE;
|
||||||
|
rx_header_rcv_delayed <= '0';
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
rx_header_rcv_delayed <= ipv4_out.rx_header_rcv;
|
||||||
|
|
||||||
|
if ipv4_out.rx_header_rcv then
|
||||||
|
rx_sel <= SEL_PROTOCOL_NONE;
|
||||||
|
for i in IPV4_PROTOCOLS'range loop
|
||||||
|
if (ipv4_out.rx_protocol = IPV4_PROTOCOLS(i)) then
|
||||||
|
rx_sel <= i;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process arb;
|
||||||
|
|
||||||
|
mux : for i in ipv4_protocol_out'range generate
|
||||||
|
ipv4_protocol_out(i).rx_data <= ipv4_out.rx_data;
|
||||||
|
ipv4_protocol_out(i).rx_ip_address <= ipv4_out.rx_ip_address;
|
||||||
|
ipv4_protocol_out(i).rx_length <= ipv4_out.rx_length;
|
||||||
|
ipv4_protocol_out(i).rx_data_valid <= ipv4_out.rx_data_valid when rx_sel = i else '0';
|
||||||
|
ipv4_protocol_out(i).rx_error_stb <= ipv4_out.rx_error_stb when rx_sel = i else '0';
|
||||||
|
ipv4_protocol_out(i).rx_ok_stb <= ipv4_out.rx_ok_stb when rx_sel = i else '0';
|
||||||
|
ipv4_protocol_out(i).rx_header_rcv <= rx_header_rcv_delayed when rx_sel = i else '0';
|
||||||
|
end generate mux;
|
||||||
|
|
||||||
|
tx_mux : for i in ipv4_protocol_out'range generate
|
||||||
|
ipv4_protocol_out(i).tx_data_ack <= ipv4_out.tx_data_ack when tx_sel = i else '0';
|
||||||
|
ipv4_protocol_out(i).tx_err_stb <= ipv4_out.tx_err_stb when tx_sel = i else '0';
|
||||||
|
ipv4_protocol_out(i).tx_ok_stb <= ipv4_out.tx_ok_stb when tx_sel = i else '0';
|
||||||
|
end generate;
|
||||||
|
end block rx;
|
||||||
|
|
||||||
|
tx : block
|
||||||
|
type state_t is (IDLE, TXD);
|
||||||
|
signal state : state_t;
|
||||||
|
|
||||||
|
begin
|
||||||
|
arb : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
state <= IDLE;
|
||||||
|
tx_sel <= ipv4_protocol_in'left;
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
case state is
|
||||||
|
when IDLE =>
|
||||||
|
for i in ipv4_protocol_in'range loop
|
||||||
|
if ipv4_protocol_in(i).tx_en then
|
||||||
|
tx_sel <= i;
|
||||||
|
state <= TXD;
|
||||||
|
exit; -- Prioritize according to vector
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
when TXD =>
|
||||||
|
state <= IDLE when (not ipv4_in.tx_en);
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process arb;
|
||||||
|
|
||||||
|
demux : block
|
||||||
|
begin
|
||||||
|
ipv4_in.tx_data <= ipv4_protocol_in(tx_sel).tx_data;
|
||||||
|
ipv4_in.tx_en <= ipv4_protocol_in(tx_sel).tx_en;
|
||||||
|
ipv4_in.tx_ip_address <= ipv4_protocol_in(tx_sel).tx_ip_address;
|
||||||
|
ipv4_in.tx_length <= ipv4_protocol_in(tx_sel).tx_length;
|
||||||
|
ipv4_in.tx_protocol <= IPV4_PROTOCOLS(tx_sel);
|
||||||
|
end block demux;
|
||||||
|
end block tx;
|
||||||
|
end architecture rtl;
|
@ -253,6 +253,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
phy_out.rx_data_valid <= '0';
|
phy_out.rx_data_valid <= '0';
|
||||||
|
phy_out.rx_data <= (others => '0'); -- Needed for yosys to compile
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
phy_out.rx_data_valid <= '0';
|
phy_out.rx_data_valid <= '0';
|
||||||
@ -296,8 +297,11 @@ begin
|
|||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
|
|
||||||
transmitter : block
|
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));
|
||||||
signal tx_stb_cnt : integer range 0 to TX_STB_CNT_MAX;
|
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);
|
type tx_state_t is (IDLE, NLP, TX, IPG);
|
||||||
signal tx_state : tx_state_t;
|
signal tx_state : tx_state_t;
|
||||||
@ -367,6 +371,9 @@ begin
|
|||||||
|
|
||||||
if tx_stb_cnt = 0 then
|
if tx_stb_cnt = 0 then
|
||||||
tx_stb_cnt <= TX_STB_CNT_MAX;
|
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
|
else
|
||||||
tx_stb_cnt <= tx_stb_cnt - 1;
|
tx_stb_cnt <= tx_stb_cnt - 1;
|
||||||
end if;
|
end if;
|
||||||
|
@ -44,14 +44,14 @@ architecture rtl of trashernet_phy_cdc is
|
|||||||
signal phy_phy_in : phy_in_t;
|
signal phy_phy_in : phy_in_t;
|
||||||
|
|
||||||
-- Helper signals
|
-- Helper signals
|
||||||
signal rx_data_valid_i : std_logic;
|
signal rx_data_i : byte;
|
||||||
|
|
||||||
begin
|
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
|
-- Drives: PHY clock domain
|
||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Reset synchronizer for PHY
|
||||||
rstsync : process(phy_clk, rst) is
|
rstsync : process(phy_clk, rst) is
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
@ -61,6 +61,7 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
end process rstsync;
|
end process rstsync;
|
||||||
|
|
||||||
|
-- Operate Trashernet in PHY clock domain
|
||||||
trashernet_phy_inst : entity work.trashernet_phy
|
trashernet_phy_inst : entity work.trashernet_phy
|
||||||
generic map(
|
generic map(
|
||||||
F_CLK => F_CLK_PHY
|
F_CLK => F_CLK_PHY
|
||||||
@ -75,6 +76,22 @@ begin
|
|||||||
tx_n => tx_n
|
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
|
synchronizer_txen_inst : entity work.synchronizer
|
||||||
generic map(
|
generic map(
|
||||||
SIZE => 5
|
SIZE => 5
|
||||||
@ -98,18 +115,10 @@ begin
|
|||||||
a_in => phy_phy_out.rx_data_valid,
|
a_in => phy_phy_out.rx_data_valid,
|
||||||
b_clk => clk,
|
b_clk => clk,
|
||||||
b_rst => rst,
|
b_rst => rst,
|
||||||
b_out => rx_data_valid_i
|
b_out => phy_out.rx_data_valid
|
||||||
);
|
);
|
||||||
|
|
||||||
rxdvff : process(clk, rst) is
|
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
|
||||||
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;
|
|
||||||
|
|
||||||
cdc_strobe_rxer_inst : entity work.cdc_strobe
|
cdc_strobe_rxer_inst : entity work.cdc_strobe
|
||||||
port map(
|
port map(
|
||||||
|
@ -37,9 +37,11 @@ package trashernet_pkg is
|
|||||||
type configuration_t is record
|
type configuration_t is record
|
||||||
mac_address : mac_addr_t; -- MAC address of this node
|
mac_address : mac_addr_t; -- MAC address of this node
|
||||||
end record configuration_t;
|
end record configuration_t;
|
||||||
type ip_configuration_t is record
|
type ipv4_configuration_t is record
|
||||||
ip_address : ip_addr_t; -- IP address of this node
|
ip_address : ip_addr_t; -- IP address of this node
|
||||||
end record ip_configuration_t;
|
gateway : ip_addr_t; -- Peer to use when target is outside of subnet
|
||||||
|
subnet_mask : ip_addr_t; -- Subnet mask of this node
|
||||||
|
end record ipv4_configuration_t;
|
||||||
|
|
||||||
-- PHY interface
|
-- PHY interface
|
||||||
type phy_in_t is record
|
type phy_in_t is record
|
||||||
@ -83,7 +85,7 @@ package trashernet_pkg is
|
|||||||
end record;
|
end record;
|
||||||
type ethernet_ii_protocol_vector is array (natural range <>) of ethernet_ii_protocol_t;
|
type ethernet_ii_protocol_vector is array (natural range <>) of ethernet_ii_protocol_t;
|
||||||
constant ETHERNET_II_PROTOCOLS_NONE : ethernet_ii_protocol_vector(0 to -1) := (others => (ethertype => (x"00", x"00"))); -- @suppress "Null range": We want a NULL vector here to remove the logic
|
constant ETHERNET_II_PROTOCOLS_NONE : ethernet_ii_protocol_vector(0 to -1) := (others => (ethertype => (x"00", x"00"))); -- @suppress "Null range": We want a NULL vector here to remove the logic
|
||||||
constant ETHERNET_II_PROTOCOL_IP : ethernet_ii_protocol_t := (ethertype => (x"08", x"00"));
|
constant ETHERNET_II_PROTOCOL_IPV4 : ethernet_ii_protocol_t := (ethertype => (x"08", x"00"));
|
||||||
constant ETHERNET_II_PROTOCOL_ARP : ethernet_ii_protocol_t := (ethertype => (x"08", x"06"));
|
constant ETHERNET_II_PROTOCOL_ARP : ethernet_ii_protocol_t := (ethertype => (x"08", x"06"));
|
||||||
|
|
||||||
type ethernet_i_out_t is record
|
type ethernet_i_out_t is record
|
||||||
@ -123,6 +125,7 @@ package trashernet_pkg is
|
|||||||
type ethernet_ii_in_vector is array (natural range <>) of ethernet_ii_in_t;
|
type ethernet_ii_in_vector is array (natural range <>) of ethernet_ii_in_t;
|
||||||
constant ETHERNET_II_IN_UNUSED : ethernet_ii_in_t := (tx_mac_address => (others => x"00"), tx_data => x"00", others => '0');
|
constant ETHERNET_II_IN_UNUSED : ethernet_ii_in_t := (tx_mac_address => (others => x"00"), tx_data => x"00", others => '0');
|
||||||
|
|
||||||
|
-- ARP interface
|
||||||
type arp_out_t is record
|
type arp_out_t is record
|
||||||
arp_mac : mac_addr_t; -- Resulting MAC address for query
|
arp_mac : mac_addr_t; -- Resulting MAC address for query
|
||||||
arp_ok_stb : std_logic; -- ARP request successful, `arp_mac` valid
|
arp_ok_stb : std_logic; -- ARP request successful, `arp_mac` valid
|
||||||
@ -132,6 +135,64 @@ package trashernet_pkg is
|
|||||||
arp_ip : ip_addr_t; -- IP address to query
|
arp_ip : ip_addr_t; -- IP address to query
|
||||||
arp_query_stb : std_logic; -- Request MAC for IP
|
arp_query_stb : std_logic; -- Request MAC for IP
|
||||||
end record arp_in_t;
|
end record arp_in_t;
|
||||||
|
|
||||||
|
-- IPv4 interface
|
||||||
|
subtype ipv4_protocol is byte;
|
||||||
|
type ipv4_protocol_vector is array (natural range <>) of ipv4_protocol;
|
||||||
|
constant IPV4_PROTOCOL_ICMP : ipv4_protocol := x"01";
|
||||||
|
constant IPV4_PROTOCOL_TCP : ipv4_protocol := x"06";
|
||||||
|
constant IPV4_PROTOCOL_UDP : ipv4_protocol := x"11";
|
||||||
|
subtype ipv4_length is unsigned(15 downto 0);
|
||||||
|
|
||||||
|
type ipv4_out_t is record
|
||||||
|
rx_ip_address : ip_addr_t; -- Source IP address
|
||||||
|
rx_protocol : ipv4_protocol; -- Transport Protocol
|
||||||
|
rx_length : ipv4_length; -- Telegram length (excluding header)
|
||||||
|
|
||||||
|
rx_data : byte; -- RX data
|
||||||
|
rx_data_valid : std_logic; -- RX data valid strobe
|
||||||
|
rx_ok_stb : std_logic; -- End of packet, checksum OK
|
||||||
|
rx_error_stb : std_logic; -- End of packet, checksum invalid
|
||||||
|
rx_header_rcv : std_logic; -- Start of reception (`rx_ip_address` and `rx_protocol` are valid)
|
||||||
|
|
||||||
|
tx_data_ack : std_logic; -- Give next data byte of disable `tx_en`
|
||||||
|
tx_ok_stb : std_logic; -- Transmission successful
|
||||||
|
tx_err_stb : std_logic; -- Transmission failed
|
||||||
|
end record ipv4_out_t;
|
||||||
|
type ipv4_in_t is record
|
||||||
|
tx_ip_address : ip_addr_t; -- Destination IP address
|
||||||
|
tx_protocol : ipv4_protocol; -- Transport Protocol
|
||||||
|
tx_length : ipv4_length; -- Length of payload
|
||||||
|
tx_data : byte; -- TX data
|
||||||
|
tx_en : std_logic; -- Start and continue transmitting
|
||||||
|
end record ipv4_in_t;
|
||||||
|
|
||||||
|
type ipv4_protocol_out_t is record
|
||||||
|
rx_ip_address : ip_addr_t; -- Source IP address
|
||||||
|
rx_length : ipv4_length; -- Telegram length (excluding header)
|
||||||
|
|
||||||
|
rx_data : byte; -- RX data
|
||||||
|
rx_data_valid : std_logic; -- RX data valid strobe
|
||||||
|
rx_ok_stb : std_logic; -- End of packet, checksum OK
|
||||||
|
rx_error_stb : std_logic; -- End of packet, checksum invalid
|
||||||
|
rx_header_rcv : std_logic; -- Start of reception
|
||||||
|
|
||||||
|
tx_data_ack : std_logic; -- Give next data byte of disable `tx_en`
|
||||||
|
tx_ok_stb : std_logic; -- Transmission successful
|
||||||
|
tx_err_stb : std_logic; -- Transmission failed
|
||||||
|
end record ipv4_protocol_out_t;
|
||||||
|
type ipv4_protocol_in_t is record
|
||||||
|
tx_ip_address : ip_addr_t; -- Destination IP address
|
||||||
|
tx_length : ipv4_length; -- Length of payload
|
||||||
|
|
||||||
|
tx_data : byte; -- TX data
|
||||||
|
tx_en : std_logic; -- Start and continue transmitting
|
||||||
|
end record ipv4_protocol_in_t;
|
||||||
|
type ipv4_protocol_out_vector is array (natural range <>) of ipv4_protocol_out_t;
|
||||||
|
type ipv4_protocol_in_vector is array (natural range <>) of ipv4_protocol_in_t;
|
||||||
|
|
||||||
|
-- General helper functions
|
||||||
|
function to_std_logic(constant bool : boolean) return std_logic;
|
||||||
end package trashernet_pkg;
|
end package trashernet_pkg;
|
||||||
|
|
||||||
package body trashernet_pkg is
|
package body trashernet_pkg is
|
||||||
@ -156,4 +217,11 @@ package body trashernet_pkg is
|
|||||||
to_string(to_integer(unsigned(ip_address(3)))) --
|
to_string(to_integer(unsigned(ip_address(3)))) --
|
||||||
;
|
;
|
||||||
end function ip_to_string;
|
end function ip_to_string;
|
||||||
|
|
||||||
|
function to_std_logic(constant bool : boolean) return std_logic is
|
||||||
|
variable ret : std_logic;
|
||||||
|
begin
|
||||||
|
ret := '1' when bool else '0';
|
||||||
|
return ret;
|
||||||
|
end function to_std_logic;
|
||||||
end package body trashernet_pkg;
|
end package body trashernet_pkg;
|
||||||
|
Loading…
Reference in New Issue
Block a user