Hallo Forum,
ich versuche, einem Ethernet PHY ein paar Pakete zu entlocken.
Dazu habe ich folgendes gemacht. Von
http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/2001_w/interfacing/ethernet_mii/eth_mii.html
habe ich die Datei sub_sync.vhdl übernommen. Mit dieser werden die
Signale vom PHY, die auf dessen TXCLK und RXCLK synchronisiert sind, auf
den FPGA-Takt synchronisiert.
Mein FPGA arbeitet mit 50 MHz, der RXCLK vom PHY ist 25 MHz. Die
Synchronisierung funktioniert ansich sehr zuverlässig, auf dem Logic
Analyser sieht alles schön plausibel aus.
Um dann Daten zu empfangen, habe ich folgenden Code geschrieben:
1 | library ieee;
| 2 | use ieee.std_logic_1164.all;
| 3 | use ieee.numeric_std.all;
| 4 |
| 5 | --------------------------------------------------------------------------------
| 6 |
| 7 | entity mii_inout is
| 8 | generic(
| 9 | PREAMBLE_LEN : natural := 7;
| 10 | IPGT_CLOCKS : natural := 48
| 11 | );
| 12 | port(
| 13 | -- clocking and reset
| 14 | clk : in std_logic;
| 15 | rst : in std_logic;
| 16 |
| 17 | -- mii interface
| 18 | phy_txd : out std_logic_vector(3 downto 0);
| 19 | phy_txerr : out std_logic;
| 20 | phy_txen : out std_logic;
| 21 | phy_txclk : in std_logic;
| 22 | phy_rxd : in std_logic_vector(3 downto 0);
| 23 | phy_rxdv : in std_logic;
| 24 | phy_rxerr : in std_logic;
| 25 | phy_rxclk : in std_logic;
| 26 |
| 27 | -- byte stream interface
| 28 | rx_data_o : out std_logic_vector(7 downto 0);
| 29 | rx_stb_o : out std_logic;
| 30 | rx_dv_o : out std_logic;
| 31 | tx_data_i : in std_logic_vector(7 downto 0);
| 32 | tx_en_i : in std_logic;
| 33 | tx_ack_o : out std_logic;
| 34 |
| 35 | frame_start : out std_logic;
| 36 | frame_end : out std_logic
| 37 | );
| 38 | end mii_inout;
| 39 |
| 40 | --------------------------------------------------------------------------------
| 41 |
| 42 | architecture rtl of mii_inout is
| 43 |
| 44 | component sub_sync is
| 45 | port(
| 46 | clk_in, clk_out: in std_logic;
| 47 | data_in: in std_logic_vector(3 downto 0);
| 48 | data_out: out std_logic_vector(3 downto 0);
| 49 | dv_in: in std_logic;
| 50 | dv_out: out std_logic
| 51 | );
| 52 | end component;
| 53 |
| 54 | signal rxd : std_logic_vector(3 downto 0);
| 55 | signal rxdv : std_logic;
| 56 | signal txd : std_logic_vector(3 downto 0);
| 57 | signal txen : std_logic;
| 58 |
| 59 | type state_t is (idle, wa, data_lo, data_hi);
| 60 | signal rxstate, txstate : state_t;
| 61 |
| 62 | signal rx_buffer : std_logic_vector(7 downto 0);
| 63 | signal rxclk_sync : std_logic;
| 64 | signal txclk_sync : std_logic;
| 65 |
| 66 | begin
| 67 |
| 68 | rxsync : component sub_sync
| 69 | port map(
| 70 | clk_in => phy_rxclk,
| 71 | clk_out => clk,
| 72 | data_in => phy_rxd,
| 73 | dv_in => phy_rxdv,
| 74 | data_out => rxd,
| 75 | dv_out => rxdv
| 76 | );
| 77 |
| 78 | txsync : component sub_sync
| 79 | port map(
| 80 | clk_in => clk,
| 81 | clk_out => phy_txclk,
| 82 | data_in => txd,
| 83 | dv_in => txen,
| 84 | data_out => phy_txd,
| 85 | dv_out => phy_txen
| 86 | );
| 87 |
| 88 | -- txerr is not used
| 89 | phy_txerr <= '0';
| 90 |
| 91 | -- for test only
| 92 | txd <= (others => '0');
| 93 | txen <= '0';
| 94 |
| 95 | process(clk)
| 96 | begin
| 97 | if rising_edge(clk) then
| 98 | rxclk_sync <= phy_rxclk;
| 99 | txclk_sync <= phy_txclk;
| 100 | end if;
| 101 | end process;
| 102 |
| 103 | -- receiver process
| 104 | process(rst, clk)
| 105 | begin
| 106 | if rst = '1' then
| 107 | rxstate <= idle;
| 108 | rx_buffer <= (others => '0');
| 109 |
| 110 | elsif rising_edge(clk) and (rxclk_sync = '0') then
| 111 |
| 112 | rx_stb_o <= '0';
| 113 | frame_start <= '0';
| 114 |
| 115 | case rxstate is
| 116 | when idle =>
| 117 | if rxdv = '1' then
| 118 | rxstate <= wa;
| 119 | rx_buffer <= (others => '0');
| 120 | end if;
| 121 |
| 122 | when wa =>
| 123 | rxstate <= data_lo;
| 124 |
| 125 | when data_lo =>
| 126 | frame_start <= '1';
| 127 | if rxdv = '0' then
| 128 | rxstate <= idle;
| 129 | else
| 130 | rx_buffer(7 downto 4) <= rxd;
| 131 | rxstate <= data_hi;
| 132 | end if;
| 133 |
| 134 |
| 135 | when data_hi =>
| 136 | frame_start <= '1';
| 137 | if rxdv = '0' then
| 138 | rxstate <= idle;
| 139 | else
| 140 | rx_buffer(3 downto 0) <= rxd;
| 141 | rxstate <= data_lo;
| 142 | rx_stb_o <= '1';
| 143 | rx_data_o <= rx_buffer;
| 144 | end if;
| 145 |
| 146 |
| 147 |
| 148 | end case;
| 149 | end if;
| 150 | end process;
| 151 |
| 152 |
| 153 | -- transmitter process
| 154 | process(rst, clk)
| 155 | begin
| 156 | if rst = '1' then
| 157 | null;
| 158 | elsif rising_edge(clk) and (txclk_sync = '0') then
| 159 | null;
| 160 | end if;
| 161 | end process;
| 162 | end rtl;
|
Mit dem einen Prozess synchronisiere ich die Taktsignale ein, mit dem
receiver Prozess versuche ich ein Paket zu empfangen und es als
parallele 8 Bit Daten an ein paar IO-Pins auszugeben. Das Signal
tx_stb_o soll auf 1 gehen, sobald 8 neue Datenbits vorhanden sind.
Das Signal frame_start soll so lange auf 1 sein, wie ein Frame
übertragen wird.
Wie ihr im angehängten Bild sehen könnt, funktioniert es prinzipiell.
Ich sende einen Ethernet Frame an den FPGA, der Als Ziel-MAC
FF:FF:FF:FF:FF:FF hat und als Quell-Mac 00:16:35:ac:4b:ae. Ansich würde
ich erwarten, dass ich auf dem Logic Analyser nun zuerst die Präambel
sehen kann, 55 55 55 , ... D5, und dann die Ziel- und Quell-MAC....
Ansatzweise stimmt es, aber eben nicht ganz. Zu beginn sieht man ein F0,
das ist definitiv falsch, woher kommt die 0? die bringt alles
durcheinander. Wenn die eine 0 zu Beginn nicht wäre, dann würden
wenigstens schon mal die richtigen Nibbles beieinander sein. Kann mir
einer auf die Sprünge helfen, was ich anpassen könnte? Ich wäre sehr
froh :-)
Vielen Dank.
Gruss Tobias.
Tobias Plüss schrieb:
> Kann mir
> einer auf die Sprünge helfen, was ich anpassen könnte? Ich wäre sehr
> froh :-)
Um das 4Bit Nibble-Port RXD[3:0]
via RX_CLK sicher einzusychroiesieren sind minimal 65 @MHz nötig.
Zitat: Aus meinem SPARTAN 3E USER GUIDE ug230.pdf
############################################################
Ethernet MAC IP Cores for the Spartan-3E Starter Kit Board
The Ethernet MAC core requires design constraints to meet the required
performance.
Refer to the OPB Ethernet MAC data sheet (v1.02) for details. The OPB
bus clock frequency
must be 65 MHz or higher for 100 Mbps Ethernet operations and 6.5 MHz or
faster for
10 Mbps Ethernet operations.
RX_CLK sample 2 times via sys_clk 50MHz
Anhang: PHY 83c185.pdf
Anhang: Bild: phy_rec_1dv.PNG
############
Viel Erfolg.
Gruss Holger.
###################################
SMSC LAN83C185 10/100 Ethernet PHY
###################################
Nein. Meine Bits werden ja richtig erkannt. Dass das Low- und das
High-Nibble vertauscht sind, liegt halt daran dass ich sie in der
falschen Reihenfolge speichere. Das kann man einfach tauschen.
Was aber definitiv falsch ist, ist, dass das erste Nibble immer 0 ist.
Das kann nicht sein. Es liegt garantiert an meiner FSM, die noch irgend
einen Zustandsübergang hat, der falsch ist. Aber ich steh da grade auf
dem Schlauch... :-(
Anhang: phy_rec_1dv.PNG.
Mit dem Data-Valid Signal.
Gruss Holger.
Hallo Holger
ja genau so mache ich das ja im Prinzip auch.
Meine Statemachine wird vom normalen Systemclock (50MHz) getaktet. Der
RXCLK vom PHY dient als Clock Enable.
So, und nun startet die FSM im Zustand idle. Dort wird RXDV abgefragt,
ob es 1 ist. Wenn ja, dann wird in den data_lo state gewechselt. dort
wird das low nibble empfangen. Anschliessend wird das high nibble
empfangen. Sollte so ja gehen. Aber eben, wenn ich dann die Nibbles
zusammensetze, ist da was vertauscht... und ich frage mich weshalb.
Gruss!
Tobias Plüss schrieb:
> Was aber definitiv falsch ist, ist, dass das erste Nibble immer 0 ist.
> Das kann nicht sein.
Das Verhalten "erste Nibble" J/K ist einstellbar. 0 oder 1 ..
Steht da im Datenblatt vom SMSC LAN83C185 10/100 Ethernet PHY.
Frage:
Was hast du den da für einen PHY ?
#####################################################
Wichtig ist Data_Valid mit in die FSM einbezogen wird.
Siehe Bild.
0x5 0x5 0xD ...
Nach den Nibble 0xD kommt das erste Data-Nibble.
Gruss Holger.
Frage: Was hast du für einen PHY ?.
Anhang: phy_mode_1rd.PNG
Tobias Plüss schrieb:
> FF:FF:FF:FF:FF:FF hat und als Quell-Mac 00:16:35:ac:4b:ae. Ansich würde
> ich erwarten, dass ich auf dem Logic Analyser nun zuerst die Präambel
> sehen kann, 55 55 55 , ... D5, und dann die Ziel- und Quell-MAC....
> Ansatzweise stimmt es, aber eben nicht ganz. Zu beginn sieht man ein F0,
> das ist definitiv falsch, woher kommt die 0? die bringt alles
> durcheinander. Wenn die eine 0 zu Beginn nicht wäre, dann würden
> Zu beginn sieht man ein F0,
woher kommt die 0?
Der PHY-Buss geht von über in die Data-Phase.
Der Bus macht einen Turn-Around '(TA),
für einen @25Mkz RX_CLK.
Jetz soll man den RX_ERR Pin auswerten.
--> wait ..@RX_ERR Pin = bool_monitor.!
( and (not RX_ERR[0] and RXDV[0] ) )
######################################
4_Bit_Data-Port. Vector-Order[3:0]. (MSB to LSB)
kann jetz gelesen werden.
4_Bit_Data-Port. Vector-Order[3:0]. (MSB to LSB)
Also noch der 'Nibble-Port 0x5 0x5 ..0xD .. für eine 'clk-Periode, d.h
Stufige-Umschaltung der FSM-PHY
via j/K.._(Präambel+Data_Valid)-State .. auf (Data)-State.
bingo>.
Und somit kommt der Bus auf <|NULL> .
RX_ERR[0] ist ein Status-Monitor in dem Mode mit 100Mbit.
RX_ERR[0] reflektiert somit in der Bedingung: via Bus-transit-.0 1 0.
Gleichung_: im (Data)-State.Data-Mode --> ( RXDV[0] and (not RX_ERR[0])
).
Gruss Holger.
Tobias Plüss schrieb:
> So, und nun startet die FSM im Zustand idle. Dort wird RXDV abgefragt,
> ob es 1 ist. Wenn ja, dann wird in den data_lo state gewechselt. dort
> wird das low nibble empfangen. Anschliessend wird das high nibble
> empfangen. Sollte so ja gehen. Aber eben, wenn ich dann die Nibbles
> zusammensetze, ist da was vertauscht... und ich frage mich weshalb.
vertauscht ?
Die Daten vom Pc sind gespiegelt via PHY-Port[3:0], vermute ich mal.
a bit-mirrored 4-Bit-Port.
Rezept:
Das Rezept aber nur in der Daten-Phase anwenden !
RX_DATA_nibble : out STD_LOGIC_VECTOR (3 to 0) := "0000");
RX_DATA_nibble_mirrord : out STD_LOGIC_VECTOR (0 to 3) := "0000");
-- Auf diese Art passiert das Tauschen der 4-Bits implizit und quasi
automatisch...
RX_DATA_nibble_mirrord(0) <= RX_DATA_nibble(3);
########################################################################
############
Mit RX_DATA_nibble_mirrord wird jetzt weiter gemacht.
Test-Muster:
......0xBADCAFFE .... 0xFFEFE ... 0XD ...0x5
Gruss Holger.
##########################################################
In einem 8Bit Port ist das auch so,
wo erwarte ich das 'LSB der 8-Bit Nachricht.
Siehe RS232: Da wird 'LSB Bit vom Data-Byte zuerst gesendet.
Und ich schiebe die empfangenen Data-Bits immer nach links,
und nehme dann das neue databit und setze es zusammen
via index 0 .
Anhang: endian_to_phy.PNG
Daten im PC zu dem RX_4-Bit Port (3:0)
Also nur im 'Data-Read-Mode muss der Nibble-Bus-3:0 auf Bus-0:3
( '4_Nibble ''LSB kommt zuerst)
-blaue Linie --> siehe Bild.
umkopiert werden.
Anhang:
endian_to_phy.PNG
Bei $F bzw $FF. ist das erst mal nicht aufgefallen, aber wenn
aus $1 $8 werden muss man das 4rer-nibble ''MSB to 'LSB tauschen.
- mirrored bits in a Nibble-Byte.
Frage:
(expect LSB on D0, not on D3.)
(expect LSB on D3, not on D0.)
Gruss Holger.
Hallo Holger
vielen Dank für deine Hilfe. Ich glaube, ich habe das Problem gefunden.
Morgen werde ich das ganze nochmals synthetisieren und auf den FPGA
laden, ich glaube, das könnte fast funktionieren!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|