------------------------------------------------------------------------------- -- Title : LED Demo File -- Project : EthMAC ------------------------------------------------------------------------------- -- File : design/led-demo.vhd -- Author : Mario Hüttel -- 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 . -- ------------------------------------------------------------------------------- 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;