Make design MII compatible
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
-- Title : Ethernet RX Core
|
||||
-- Project : EthMAC
|
||||
-------------------------------------------------------------------------------
|
||||
-- File : design/ethmac_rx.vhd
|
||||
-- File : design/ethmac_rx.vhd
|
||||
-- Author : Mario Hüttel <mario.huettel@gmx.net>
|
||||
-- Standard : VHDL'93/02
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -18,7 +18,7 @@
|
||||
--
|
||||
-- This code is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
@@ -33,32 +33,38 @@ use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity ethmac_rx is
|
||||
generic(
|
||||
IFACE_WIDTH : natural := 2);
|
||||
port(
|
||||
clk_50 : in std_logic;
|
||||
rst : in std_logic;
|
||||
rmii_rx : in std_logic_vector(1 downto 0);
|
||||
rmii_dv : in std_logic;
|
||||
start_of_frame : out std_logic;
|
||||
end_of_frame : out std_logic;
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
data_strb : out std_logic;
|
||||
clk_50 : in std_logic;
|
||||
rst : in std_logic;
|
||||
rmii_rx : in std_logic_vector(IFACE_WIDTH - 1 downto 0);
|
||||
rmii_dv : in std_logic;
|
||||
start_of_frame : out std_logic;
|
||||
end_of_frame : out std_logic;
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
data_strb : out std_logic;
|
||||
crc_check_valid : out std_logic
|
||||
);
|
||||
);
|
||||
end entity ethmac_rx;
|
||||
|
||||
architecture RTL of ethmac_rx is
|
||||
|
||||
constant DIBIT_COUNT : natural := 8 / IFACE_WIDTH;
|
||||
|
||||
|
||||
type ethstate_t is (ETH_INIT, ETH_PREAMBLE, ETH_DATA);
|
||||
signal framestate : ethstate_t;
|
||||
signal crc_data_in : std_logic_vector(7 downto 0);
|
||||
signal crc_init : std_logic;
|
||||
signal crc_calc_en : std_logic;
|
||||
signal crc_data_valid : std_logic;
|
||||
signal crc_valid : std_logic;
|
||||
signal dibit_counter : integer range 0 to 3 := 0;
|
||||
signal data_delay_in : std_logic_vector(7 downto 0);
|
||||
signal framestate : ethstate_t;
|
||||
signal crc_data_in : std_logic_vector(7 downto 0);
|
||||
signal crc_init : std_logic;
|
||||
signal crc_calc_en : std_logic;
|
||||
signal crc_data_valid : std_logic;
|
||||
signal crc_valid : std_logic;
|
||||
signal dibit_counter : integer range 0 to (DIBIT_COUNT - 1) := 0;
|
||||
signal data_delay_in : std_logic_vector(7 downto 0);
|
||||
signal data_delay_in_strb : std_logic;
|
||||
signal data_delay_truncate : std_logic;
|
||||
signal end_of_frame_s : std_logic;
|
||||
signal end_of_frame_s : std_logic;
|
||||
type data_fifo_t is array (0 to 3) of std_logic_vector(7 downto 0);
|
||||
|
||||
signal data_delay_fifo : data_fifo_t;
|
||||
@@ -68,14 +74,14 @@ architecture RTL of ethmac_rx is
|
||||
begin
|
||||
ethfcs_inst : entity work.ethfcs
|
||||
port map(
|
||||
CLOCK => clk_50,
|
||||
RESET => rst,
|
||||
DATA => crc_data_in,
|
||||
CLOCK => clk_50,
|
||||
RESET => rst,
|
||||
DATA => crc_data_in,
|
||||
LOAD_INIT => crc_init,
|
||||
CALC => crc_calc_en,
|
||||
D_VALID => crc_data_valid,
|
||||
CRC => open,
|
||||
CRC_REG => open,
|
||||
CALC => crc_calc_en,
|
||||
D_VALID => crc_data_valid,
|
||||
CRC => open,
|
||||
CRC_REG => open,
|
||||
CRC_VALID => crc_valid);
|
||||
|
||||
rx_framefsm : process(clk_50, rst) is
|
||||
@@ -83,63 +89,63 @@ begin
|
||||
|
||||
begin
|
||||
if rst = '1' then
|
||||
framestate <= ETH_INIT;
|
||||
dibit_counter <= 0;
|
||||
recv_byte := (others => '0');
|
||||
crc_calc_en <= '0';
|
||||
framestate <= ETH_INIT;
|
||||
dibit_counter <= 0;
|
||||
recv_byte := (others => '0');
|
||||
crc_calc_en <= '0';
|
||||
data_delay_truncate <= '0';
|
||||
data_delay_in_strb <= '0';
|
||||
data_delay_in <= (others => '0');
|
||||
crc_init <= '0';
|
||||
crc_data_in <= (others => '0');
|
||||
crc_data_valid <= '0';
|
||||
crc_calc_en <= '0';
|
||||
start_of_frame <= '0';
|
||||
end_of_frame_s <= '0';
|
||||
data_delay_in <= (others => '0');
|
||||
crc_init <= '0';
|
||||
crc_data_in <= (others => '0');
|
||||
crc_data_valid <= '0';
|
||||
crc_calc_en <= '0';
|
||||
start_of_frame <= '0';
|
||||
end_of_frame_s <= '0';
|
||||
elsif rising_edge(clk_50) then
|
||||
end_of_frame_s <= '0';
|
||||
crc_calc_en <= '0';
|
||||
start_of_frame <= '0';
|
||||
end_of_frame_s <= '0';
|
||||
crc_calc_en <= '0';
|
||||
start_of_frame <= '0';
|
||||
data_delay_truncate <= '0';
|
||||
data_delay_in_strb <= '0';
|
||||
crc_init <= '0';
|
||||
crc_data_valid <= '0';
|
||||
if dibit_counter = 3 then
|
||||
crc_init <= '0';
|
||||
crc_data_valid <= '0';
|
||||
if dibit_counter = DIBIT_COUNT - 1 then
|
||||
dibit_counter <= 0;
|
||||
else
|
||||
dibit_counter <= dibit_counter + 1;
|
||||
end if;
|
||||
|
||||
-- input data shift register (LSB first)
|
||||
recv_byte := rmii_rx & recv_byte(7 downto 2);
|
||||
recv_byte := rmii_rx & recv_byte(7 downto IFACE_WIDTH);
|
||||
|
||||
case framestate is
|
||||
when ETH_INIT =>
|
||||
if rmii_dv = '0' then -- Wait for inter frame gap for sync
|
||||
if rmii_dv = '0' then -- Wait for inter frame gap for sync
|
||||
crc_init <= '1';
|
||||
framestate <= ETH_PREAMBLE;
|
||||
end if;
|
||||
when ETH_PREAMBLE =>
|
||||
if rmii_dv = '1' and rmii_rx = "11" then -- Data valid and last dibit of preamble recieved
|
||||
-- reset dibit counter
|
||||
if rmii_dv = '1' and rmii_rx(rmii_rx'left downto rmii_rx'left - 1) = "11" then -- Data valid and last dibit of preamble recieved
|
||||
-- reset dibit counter
|
||||
dibit_counter <= 0;
|
||||
start_of_frame <= '1';
|
||||
framestate <= ETH_DATA;
|
||||
-- crc_init <= '1';
|
||||
-- crc_init <= '1';
|
||||
end if;
|
||||
when ETH_DATA =>
|
||||
crc_calc_en <= '1';
|
||||
if rmii_dv = '1' then
|
||||
if dibit_counter = 3 then -- Data word received
|
||||
data_delay_in <= recv_byte;
|
||||
if dibit_counter = DIBIT_COUNT -1 then -- Data word received
|
||||
data_delay_in <= recv_byte;
|
||||
data_delay_in_strb <= '1';
|
||||
crc_data_in <= recv_byte;
|
||||
crc_data_valid <= '1';
|
||||
crc_data_in <= recv_byte;
|
||||
crc_data_valid <= '1';
|
||||
end if;
|
||||
else
|
||||
framestate <= ETH_INIT;
|
||||
end_of_frame_s <= '1';
|
||||
crc_calc_en <= '0';
|
||||
framestate <= ETH_INIT;
|
||||
end_of_frame_s <= '1';
|
||||
crc_calc_en <= '0';
|
||||
data_delay_truncate <= '1';
|
||||
end if;
|
||||
end case;
|
||||
@@ -147,7 +153,7 @@ begin
|
||||
end if;
|
||||
end process rx_framefsm;
|
||||
|
||||
data_delay : process(rst, clk_50) is -- This implements a four byte big delay buffer/FIFO used for removing the crc
|
||||
data_delay : process(rst, clk_50) is -- This implements a four byte big delay buffer/FIFO used for removing the crc
|
||||
variable data_count : integer range 0 to 4 := 0;
|
||||
begin
|
||||
if rst = '1' then
|
||||
@@ -161,7 +167,7 @@ begin
|
||||
elsif rising_edge(clk_50) then
|
||||
data_strb <= '0';
|
||||
if data_delay_truncate = '1' then
|
||||
data_count := 0; -- resetting counter is enough. FIFO itself has not to be cleared
|
||||
data_count := 0; -- resetting counter is enough. FIFO itself has not to be cleared
|
||||
elsif data_delay_in_strb = '1' then
|
||||
data_delay_fifo(0) <= data_delay_in;
|
||||
for i in 3 downto 1 loop
|
||||
@@ -170,7 +176,7 @@ begin
|
||||
|
||||
if data_count < 4 then
|
||||
data_count := data_count + 1;
|
||||
else -- Enable output
|
||||
else -- Enable output
|
||||
data_out <= data_delay_fifo(3);
|
||||
data_strb <= '1';
|
||||
end if;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
-- Title : Ethernet TX Core
|
||||
-- Project : EthMAC
|
||||
-------------------------------------------------------------------------------
|
||||
-- File : design/ethmac_tx.vhd
|
||||
-- File : design/ethmac_tx.vhd
|
||||
-- Author : Mario Hüttel <mario.huettel@gmx.net>
|
||||
-- Standard : VHDL'93/02
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -18,7 +18,7 @@
|
||||
--
|
||||
-- This code is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
@@ -33,50 +33,57 @@ use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity ethmac_tx is
|
||||
generic(
|
||||
IFACE_WIDTH : natural := 2);
|
||||
port(
|
||||
clk_50 : in std_logic;
|
||||
rst : in std_logic;
|
||||
clk_50 : in std_logic;
|
||||
rst : in std_logic;
|
||||
tx_ready : out std_logic;
|
||||
start_of_frame : in std_logic;
|
||||
end_of_frame : in std_logic;
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
data_ack : out std_logic;
|
||||
abort : in std_logic;
|
||||
abort : in std_logic;
|
||||
--- RMII Interface
|
||||
rmii_tx : out std_logic_vector(1 downto 0);
|
||||
rmii_tx : out std_logic_vector(IFACE_WIDTH -1 downto 0);
|
||||
rmii_txen : out std_logic
|
||||
);
|
||||
);
|
||||
end entity ethmac_tx;
|
||||
|
||||
architecture RTL of ethmac_tx is
|
||||
|
||||
constant DIBIT_COUNT : natural := 8 / IFACE_WIDTH;
|
||||
constant PREAMBLE_BYTE : std_logic_vector(7 downto 0) := x"55";
|
||||
constant PREAMBLE_SFD : std_logic_vector(7 downto 0) := x"D5";
|
||||
|
||||
type eth_tx_state_t is (INIT, PREAMBLE, DATA, CRC, IPG);
|
||||
|
||||
signal crc_data_in : std_logic_vector(7 downto 0);
|
||||
signal crc_init : std_logic;
|
||||
signal crc_init : std_logic;
|
||||
signal crc_data_out : std_logic_vector(7 downto 0);
|
||||
signal crc_data_valid : std_logic;
|
||||
signal crc_calc : std_logic;
|
||||
signal dibit_counter : integer range 0 to 3 := 0;
|
||||
signal byte_counter : integer range 0 to 15 := 0;
|
||||
signal tx_state : eth_tx_state_t;
|
||||
signal crc_calc : std_logic;
|
||||
signal dibit_counter : integer range 0 to DIBIT_COUNT - 1 := 0;
|
||||
signal byte_counter : integer range 0 to 15 := 0;
|
||||
signal tx_state : eth_tx_state_t;
|
||||
|
||||
signal data_reg : std_logic_vector(7 downto 0);
|
||||
signal eof_reg : std_logic;
|
||||
signal data_reg : std_logic_vector(7 downto 0);
|
||||
signal eof_reg : std_logic;
|
||||
signal byte_counter_disable : std_logic;
|
||||
|
||||
begin
|
||||
ethfcs_inst : entity work.ethfcs
|
||||
port map(
|
||||
CLOCK => clk_50,
|
||||
RESET => rst,
|
||||
DATA => crc_data_in,
|
||||
CLOCK => clk_50,
|
||||
RESET => rst,
|
||||
DATA => crc_data_in,
|
||||
LOAD_INIT => crc_init,
|
||||
CALC => crc_calc,
|
||||
D_VALID => crc_data_valid,
|
||||
CRC => crc_data_out,
|
||||
CRC_REG => open,
|
||||
CALC => crc_calc,
|
||||
D_VALID => crc_data_valid,
|
||||
CRC => crc_data_out,
|
||||
CRC_REG => open,
|
||||
CRC_VALID => open
|
||||
);
|
||||
);
|
||||
|
||||
eth_tx_fsm : process(clk_50, rst) is
|
||||
begin
|
||||
@@ -88,7 +95,7 @@ begin
|
||||
dibit_counter <= 0;
|
||||
byte_counter <= 0;
|
||||
rmii_txen <= '0';
|
||||
rmii_tx <= "00";
|
||||
rmii_tx <= (others => '0');
|
||||
tx_state <= INIT;
|
||||
data_reg <= (others => '0');
|
||||
data_ack <= '0';
|
||||
@@ -100,10 +107,10 @@ begin
|
||||
crc_data_valid <= '0';
|
||||
|
||||
-- Shift data register
|
||||
data_reg <= "00" & data_reg(7 downto 2);
|
||||
data_reg <= std_logic_vector(to_unsigned(0, IFACE_WIDTH)) & data_reg(7 downto IFACE_WIDTH);
|
||||
|
||||
-- Increment counters:
|
||||
if dibit_counter = 3 then
|
||||
if dibit_counter = DIBIT_COUNT - 1 then
|
||||
dibit_counter <= 0;
|
||||
if byte_counter_disable /= '1' then
|
||||
if byte_counter = 15 then
|
||||
@@ -123,73 +130,75 @@ begin
|
||||
case tx_state is
|
||||
when INIT =>
|
||||
byte_counter_disable <= '1';
|
||||
-- Wait for start of frame
|
||||
-- Wait for start of frame
|
||||
if start_of_frame = '1' then
|
||||
crc_init <= '1';
|
||||
tx_state <= PREAMBLE;
|
||||
crc_init <= '1';
|
||||
tx_state <= PREAMBLE;
|
||||
byte_counter_disable <= '0';
|
||||
dibit_counter <= 0;
|
||||
byte_counter <= 0;
|
||||
eof_reg <= '0';
|
||||
dibit_counter <= 0;
|
||||
byte_counter <= 0;
|
||||
eof_reg <= '0';
|
||||
end if;
|
||||
when PREAMBLE =>
|
||||
rmii_txen <= '1';
|
||||
rmii_txen <= '1';
|
||||
byte_counter_disable <= '0';
|
||||
if (byte_counter = 7 and dibit_counter = 3) then -- Last dibit of preamble+SFD
|
||||
rmii_tx <= "11";
|
||||
-- latch data_in and continue to data phase
|
||||
data_reg <= data_in;
|
||||
data_ack <= '1';
|
||||
tx_state <= DATA;
|
||||
eof_reg <= end_of_frame;
|
||||
if (byte_counter = 7 and dibit_counter = DIBIT_COUNT -1) then -- Last dibit of preamble+SFD
|
||||
|
||||
rmii_tx <= PREAMBLE_SFD(7 downto 8 - IFACE_WIDTH);
|
||||
-- latch data_in and continue to data phase
|
||||
data_reg <= data_in;
|
||||
data_ack <= '1';
|
||||
tx_state <= DATA;
|
||||
eof_reg <= end_of_frame;
|
||||
crc_data_valid <= '1';
|
||||
crc_calc <= '1';
|
||||
crc_data_in <= data_in;
|
||||
else
|
||||
rmii_tx <= "01";
|
||||
rmii_tx <= PREAMBLE_BYTE(IFACE_WIDTH -1 downto 0);
|
||||
end if;
|
||||
when DATA =>
|
||||
rmii_txen <= '1';
|
||||
crc_calc <= '1';
|
||||
rmii_txen <= '1';
|
||||
crc_calc <= '1';
|
||||
byte_counter_disable <= '1';
|
||||
rmii_tx <= data_reg(1 downto 0);
|
||||
if dibit_counter = 0 then -- first dibit to transmit => shift register yet intact => Load crc;
|
||||
crc_data_in <= data_reg;
|
||||
rmii_tx <= data_reg(IFACE_WIDTH - 1 downto 0);
|
||||
|
||||
if dibit_counter = DIBIT_COUNT - 1 and eof_reg = '0' then -- Ladt dibit sent => latch new data
|
||||
data_reg <= data_in;
|
||||
data_ack <= '1';
|
||||
eof_reg <= end_of_frame;
|
||||
crc_data_valid <= '1';
|
||||
end if;
|
||||
-- Output Least significant dibit of data reg
|
||||
if dibit_counter = 3 and eof_reg = '0' then -- Ladt dibit sent => latch new data
|
||||
data_reg <= data_in;
|
||||
data_ack <= '1';
|
||||
eof_reg <= end_of_frame;
|
||||
elsif dibit_counter = 3 and eof_reg = '1' then -- Last dibit sent, no further data => CRC
|
||||
tx_state <= CRC;
|
||||
data_reg <= crc_data_out;
|
||||
byte_counter <= 0;
|
||||
crc_data_in <= data_in;
|
||||
elsif dibit_counter = DIBIT_COUNT - 1 and eof_reg = '1' then -- Last dibit sent, no further data => CRC
|
||||
tx_state <= CRC;
|
||||
data_reg <= crc_data_out;
|
||||
crc_data_valid <= '1';
|
||||
byte_counter <= 0;
|
||||
byte_counter_disable <= '0';
|
||||
crc_calc <= '0';
|
||||
crc_calc <= '0';
|
||||
end if;
|
||||
when CRC =>
|
||||
byte_counter_disable <= '0';
|
||||
rmii_txen <= '1';
|
||||
rmii_tx <= data_reg(1 downto 0);
|
||||
if dibit_counter = 1 and byte_counter /= 3 then -- Request new data byte
|
||||
crc_data_valid <= '1';
|
||||
elsif dibit_counter = 3 then -- Either latch new CRC data or proceed to IPG when CRC is finished.
|
||||
rmii_txen <= '1';
|
||||
rmii_tx <= data_reg(IFACE_WIDTH - 1 downto 0);
|
||||
if dibit_counter = DIBIT_COUNT - 1 then -- Either latch new CRC data or proceed to IPG when CRC is finished.
|
||||
if byte_counter = 3 then
|
||||
byte_counter <= 0;
|
||||
tx_state <= IPG;
|
||||
else
|
||||
data_reg <= crc_data_out;
|
||||
data_reg <= crc_data_out;
|
||||
crc_data_valid <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when IPG =>
|
||||
rmii_txen <= '0';
|
||||
rmii_txen <= '0';
|
||||
byte_counter_disable <= '0';
|
||||
if byte_counter = 11 and dibit_counter = 3 then
|
||||
if byte_counter = 11 and dibit_counter = DIBIT_COUNT - 1 then
|
||||
tx_state <= INIT;
|
||||
end if;
|
||||
end case;
|
||||
end if; -- abort condition
|
||||
end if; -- rising edge end process eth_tx_fsm;
|
||||
end if; -- abort condition
|
||||
end if; -- rising edge end process eth_tx_fsm;
|
||||
end process eth_tx_fsm;
|
||||
|
||||
tx_ready <= '1' when tx_state = INIT else '0';
|
||||
|
Reference in New Issue
Block a user