249 lines
6.7 KiB
VHDL
249 lines
6.7 KiB
VHDL
-------------------------------------------------------------------------------
|
|
-- Title : LED Demo File
|
|
-- Project : EthMAC
|
|
-------------------------------------------------------------------------------
|
|
-- File : design/led-demo.vhd
|
|
-- Author : Mario Hüttel <mario.huettel@gmx.net>
|
|
-- Standard : VHDL'93/02
|
|
-------------------------------------------------------------------------------
|
|
-- Description: LED Demonstration for Ethernet RX + TX
|
|
-------------------------------------------------------------------------------
|
|
-- Copyright (c) 2016
|
|
--
|
|
-- This file is part of EthMAC.
|
|
--
|
|
-- EthMAC is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation, version 2 of the License.
|
|
--
|
|
-- 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
|
|
-- GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License
|
|
-- along with this code. If not, see <http://www.gnu.org/licenses/>.
|
|
--
|
|
-------------------------------------------------------------------------------
|
|
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
entity leddemo is
|
|
port(
|
|
clk_tx : in std_logic;
|
|
clk_rx : in std_logic;
|
|
data_in : in std_logic_vector(3 downto 0);
|
|
data_out : out std_logic_vector(3 downto 0);
|
|
rst_hw : in std_logic;
|
|
rmii_tx : out std_logic_vector(1 downto 0);
|
|
rmii_txen : out std_logic;
|
|
rmii_rx : in std_logic_vector(1 downto 0);
|
|
rmii_rxen : in std_logic;
|
|
mdc : out std_logic_vector(1 downto 0);
|
|
mdio : out std_logic_vector(1 downto 0)
|
|
);
|
|
end entity leddemo;
|
|
|
|
architecture RTL of leddemo is
|
|
constant DELAYCNTVAL : integer := 100000
|
|
-- pragma synthesis_off
|
|
/50000
|
|
-- pragma synthesis_on
|
|
;
|
|
|
|
type smisend_t is (IDLE, STROBE);
|
|
type rx_state_t is (RXSOFWAIT, RXDATA, RXCRCCHECK);
|
|
type tx_state_t is (TXWAIT, TXSEND);
|
|
type smiinit_t is (RESET, INIT, DELAY, INIT_COMPLETE);
|
|
signal rx_state : rx_state_t;
|
|
signal tx_state : tx_state_t;
|
|
signal sendstate : smisend_t;
|
|
signal delaycounter : unsigned(19 downto 0);
|
|
signal regaddr_s : std_logic_vector(4 downto 0);
|
|
signal smi_data_s : std_logic_vector(15 downto 0);
|
|
signal smi_strb_s : std_logic;
|
|
signal rst_rxtx : std_logic;
|
|
signal rst : std_logic;
|
|
signal smi_busy_s : std_logic;
|
|
signal initstate : smiinit_t;
|
|
signal mdio_s : std_logic;
|
|
signal mdc_s : std_logic;
|
|
signal rx_crc : std_logic;
|
|
signal rx_strb : std_logic;
|
|
signal rx_data : std_logic_vector(7 downto 0);
|
|
signal rx_eof : std_logic;
|
|
signal rx_sof : std_logic;
|
|
signal rx_mem : std_logic_vector(3 downto 0);
|
|
signal tx_ack : std_logic;
|
|
signal tx_data : std_logic_vector(7 downto 0);
|
|
signal tx_eof : std_logic;
|
|
signal tx_sof : std_logic;
|
|
begin
|
|
rst <= not rst_hw;
|
|
|
|
mdc <= (others => mdc_s);
|
|
mdio <= (others => mdio_s);
|
|
|
|
smi_inst : entity work.smi
|
|
generic map(
|
|
clockdiv => 30
|
|
-- pragma synthesis_off
|
|
/10
|
|
-- pragma synthesis_on
|
|
)
|
|
port map(
|
|
clk_i => clk_tx,
|
|
rst_i => rst,
|
|
mdio_io => mdio_s,
|
|
mdc_o => mdc_s,
|
|
busy_o => smi_busy_s,
|
|
data_o => open, -- ignore read outputs
|
|
data_o_strb => open, -- ignore read outputs
|
|
phyaddr_i => "00001",
|
|
regaddr_i => regaddr_s,
|
|
data_i => smi_data_s,
|
|
strb_i => smi_strb_s,
|
|
rw_i => '0' -- Fix for write operation
|
|
);
|
|
|
|
initphy : process(clk_tx, rst) is
|
|
procedure sendsmi(regaddr : in std_logic_vector(4 downto 0);
|
|
data : in std_logic_vector(15 downto 0);
|
|
nextstate : in smiinit_t) is
|
|
begin
|
|
case sendstate is
|
|
when IDLE =>
|
|
regaddr_s <= regaddr;
|
|
smi_data_s <= data;
|
|
if smi_busy_s = '0' then
|
|
smi_strb_s <= '1';
|
|
sendstate <= STROBE;
|
|
end if;
|
|
when STROBE =>
|
|
initstate <= nextstate;
|
|
sendstate <= IDLE;
|
|
end case;
|
|
end procedure sendsmi;
|
|
|
|
begin
|
|
if rst = '1' then
|
|
regaddr_s <= (others => '0');
|
|
smi_data_s <= (others => '0');
|
|
smi_strb_s <= '0';
|
|
rst_rxtx <= '1';
|
|
initstate <= RESET;
|
|
sendstate <= IDLE;
|
|
delaycounter <= (others => '0');
|
|
elsif rising_edge(clk_tx) then
|
|
smi_strb_s <= '0';
|
|
rst_rxtx <= '1';
|
|
case initstate is
|
|
when RESET =>
|
|
sendsmi((others => '0'), x"8000", DELAY);
|
|
when DELAY =>
|
|
delaycounter <= delaycounter + 1;
|
|
if delaycounter = DELAYCNTVAL then -- Set to 100000
|
|
initstate <= INIT;
|
|
end if;
|
|
when INIT =>
|
|
sendsmi((others => '0'), "00" & '1' & '1' & "000" & '1' & "00000000", INIT_COMPLETE);
|
|
when INIT_COMPLETE =>
|
|
initstate <= INIT_COMPLETE;
|
|
rst_rxtx <= '0';
|
|
end case;
|
|
end if;
|
|
end process initphy;
|
|
|
|
ethmac_rx_inst : entity work.ethmac_rx
|
|
port map(
|
|
clk_50 => clk_rx,
|
|
rst => rst,
|
|
rmii_rx => rmii_rx,
|
|
rmii_dv => rmii_rxen,
|
|
start_of_frame => rx_sof,
|
|
end_of_frame => rx_eof,
|
|
data_out => rx_data,
|
|
data_strb => rx_strb,
|
|
crc_check_valid => rx_crc
|
|
);
|
|
|
|
receiver : process(clk_rx, rst) is
|
|
begin
|
|
if rst = '1' then
|
|
rx_state <= RXSOFWAIT;
|
|
rx_mem <= (others => '0');
|
|
data_out <= (others => '0');
|
|
elsif rising_edge(clk_rx) then
|
|
case rx_state is
|
|
when RXSOFWAIT =>
|
|
if rx_sof = '1' then
|
|
rx_state <= RXDATA;
|
|
end if;
|
|
when RXDATA =>
|
|
if rx_strb = '1' then
|
|
rx_mem <= rx_data(3 downto 0);
|
|
rx_state <= RXCRCCHECK;
|
|
end if;
|
|
when RXCRCCHECK =>
|
|
if rx_eof = '1' then
|
|
rx_state <= RXSOFWAIT;
|
|
if rx_crc = '1' then
|
|
data_out <= rx_mem(3 downto 0);
|
|
end if;
|
|
end if;
|
|
end case;
|
|
end if;
|
|
end process receiver;
|
|
|
|
ethmac_tx_inst : entity work.ethmac_tx
|
|
port map(
|
|
clk_50 => clk_tx,
|
|
rst => rst,
|
|
tx_ready => open,
|
|
start_of_frame => tx_sof,
|
|
end_of_frame => tx_eof,
|
|
data_in => tx_data,
|
|
data_ack => tx_ack,
|
|
abort => '0',
|
|
rmii_tx => rmii_tx,
|
|
rmii_txen => rmii_txen
|
|
);
|
|
|
|
sender : process(clk_tx, rst_rxtx) is
|
|
variable dummycnt : integer range 0 to 511 := 0;
|
|
|
|
begin
|
|
if rst_rxtx = '1' then
|
|
tx_state <= TXWAIT;
|
|
tx_sof <= '0';
|
|
tx_eof <= '0';
|
|
tx_data <= x"00";
|
|
dummycnt := 0;
|
|
elsif rising_edge(clk_tx) then
|
|
case tx_state is
|
|
when TXWAIT =>
|
|
tx_sof <= '1';
|
|
tx_state <= TXSEND;
|
|
tx_data <= "0000" & data_in;
|
|
dummycnt := 0;
|
|
when TXSEND =>
|
|
if tx_ack = '1' then
|
|
tx_sof <= '0';
|
|
dummycnt := dummycnt + 1;
|
|
if dummycnt = 500 then
|
|
tx_eof <= '1';
|
|
end if;
|
|
if dummycnt = 501 then
|
|
tx_eof <= '0';
|
|
tx_state <= TXWAIT;
|
|
end if;
|
|
end if;
|
|
end case;
|
|
end if;
|
|
end process sender;
|
|
|
|
end architecture RTL;
|