From 6d7492a98d21d6519c30d1826c0a1006b01c7516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 9 Aug 2020 23:14:44 +0200 Subject: [PATCH] Add read support to SMI --- design/led-demo.vhd | 149 ++++++++++++++++++++++---------------------- design/smi.vhd | 132 +++++++++++++++++++++------------------ 2 files changed, 147 insertions(+), 134 deletions(-) diff --git a/design/led-demo.vhd b/design/led-demo.vhd index 9fd7620..ea4a10d 100644 --- a/design/led-demo.vhd +++ b/design/led-demo.vhd @@ -2,7 +2,7 @@ -- Title : LED Demo File -- Project : EthMAC ------------------------------------------------------------------------------- --- File : design/led-demo.vhd +-- File : design/led-demo.vhd -- Author : Mario Hüttel -- 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,54 +33,54 @@ 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); + 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); + 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) - ); + 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 - ; - + -- 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 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 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; + 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; @@ -92,26 +92,27 @@ begin clockdiv => 30 -- pragma synthesis_off /10 - -- pragma synthesis_on - ) + -- 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, - phyaddr_i => "00001", - regaddr_i => regaddr_s, - data_i => smi_data_s, - strb_i => smi_strb_s, - rw_i => '0' - ); + 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 + data : in std_logic_vector(15 downto 0); + nextstate : in smiinit_t) is begin case sendstate is when IDLE => @@ -144,7 +145,7 @@ begin sendsmi((others => '0'), x"8000", DELAY); when DELAY => delaycounter <= delaycounter + 1; - if delaycounter = DELAYCNTVAL then -- Set to 100000 + if delaycounter = DELAYCNTVAL then -- Set to 100000 initstate <= INIT; end if; when INIT => @@ -158,22 +159,22 @@ begin 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, + 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'); + rx_mem <= (others => '0'); data_out <= (others => '0'); elsif rising_edge(clk_rx) then case rx_state is @@ -183,7 +184,7 @@ begin end if; when RXDATA => if rx_strb = '1' then - rx_mem <= rx_data(3 downto 0); + rx_mem <= rx_data(3 downto 0); rx_state <= RXCRCCHECK; end if; when RXCRCCHECK => @@ -199,17 +200,17 @@ begin ethmac_tx_inst : entity work.ethmac_tx port map( - clk_50 => clk_tx, - rst => rst, + clk_50 => clk_tx, + rst => rst, tx_ready => open, start_of_frame => tx_sof, end_of_frame => tx_eof, - data_in => tx_data, + data_in => tx_data, data_ack => tx_ack, - abort => '0', - rmii_tx => rmii_tx, + 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; @@ -217,26 +218,26 @@ begin begin if rst_rxtx = '1' then tx_state <= TXWAIT; - tx_sof <= '0'; - tx_eof <= '0'; - tx_data <= x"00"; + 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_sof <= '1'; tx_state <= TXSEND; - tx_data <= "0000" & data_in; + tx_data <= "0000" & data_in; dummycnt := 0; when TXSEND => if tx_ack = '1' then - tx_sof <= '0'; + tx_sof <= '0'; dummycnt := dummycnt + 1; if dummycnt = 500 then tx_eof <= '1'; end if; if dummycnt = 501 then - tx_eof <= '0'; + tx_eof <= '0'; tx_state <= TXWAIT; end if; end if; diff --git a/design/smi.vhd b/design/smi.vhd index 545f53a..142325f 100644 --- a/design/smi.vhd +++ b/design/smi.vhd @@ -2,7 +2,7 @@ -- Title : SMI (MDIO) -- Project : EthMAC ------------------------------------------------------------------------------- --- File : design/smi.vhd +-- File : design/smi.vhd -- Author : Mario Hüttel -- 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 @@ -32,49 +32,49 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Implementation of the SMI --- Only write Access implemented --- I think i won't implement read access because.........IT'S FUCKING USELESS entity smi is generic( clockdiv : integer := 64 - ); + ); port( - clk_i : in std_logic; - rst_i : in std_logic; - mdio_io : inout std_logic; - mdc_o : out std_logic; - busy_o : out std_logic; - data_o : out std_logic_vector(15 downto 0); - phyaddr_i : std_logic_vector(4 downto 0); - regaddr_i : std_logic_vector(4 downto 0); - data_i : in std_logic_vector(15 downto 0); - strb_i : in std_logic; - rw_i : in std_logic --Read/write. 0=write, 1=read - ); + clk_i : in std_logic; + rst_i : in std_logic; + mdio_io : inout std_logic; + mdc_o : out std_logic; + busy_o : out std_logic; + data_o : out std_logic_vector(15 downto 0); + data_o_strb : out std_logic; + phyaddr_i : std_logic_vector(4 downto 0); + regaddr_i : std_logic_vector(4 downto 0); + data_i : in std_logic_vector(15 downto 0); + strb_i : in std_logic; + rw_i : in std_logic --Read/write. 0=write, 1=read + ); end entity smi; architecture RTL of smi is type smistate_t is (IDLE, PRE, SOF, OPC, PHYADDR, REGADDR, TURN, DATA, CONCL); - signal state_s : smistate_t; + signal state_s : smistate_t; signal fedge_strb_s : std_logic; signal datashift_s : std_logic_vector(15 downto 0); signal regaddr_s : std_logic_vector(4 downto 0); signal phyaddr_s : std_logic_vector(4 downto 0); signal bitcounter_s : integer range 0 to 32; - signal mdc_o_s : std_logic; + signal mdc_o_s : std_logic; + signal rw_latched : std_logic; begin mdc_o <= mdc_o_s; - + div : process(clk_i, rst_i) is variable counter : integer := 0; begin if rst_i = '1' then fedge_strb_s <= '0'; - counter := 0; - mdc_o_s <= '0'; + counter := 0; + mdc_o_s <= '0'; elsif rising_edge(clk_i) then fedge_strb_s <= '0'; - counter := counter + 1; + counter := counter + 1; if counter = clockdiv then mdc_o_s <= not mdc_o_s; counter := 0; @@ -88,39 +88,49 @@ begin smishift : process(clk_i, rst_i) is begin if rst_i = '1' then - mdio_io <= '1'; - state_s <= IDLE; - - busy_o <= '1'; + mdio_io <= '1'; + state_s <= IDLE; + rw_latched <= '0'; + phyaddr_s <= (others => '0'); + regaddr_s <= (others => '0'); + datashift_s <= (others => '0'); + busy_o <= '1'; + data_o_strb <= '0'; elsif rising_edge(clk_i) then - busy_o <= '1'; + busy_o <= '1'; + data_o_strb <= '0'; if state_s = IDLE then - mdio_io <= '1'; - busy_o <= '0'; + mdio_io <= '1'; + busy_o <= '0'; bitcounter_s <= 0; if (strb_i = '1') then - state_s <= PRE; - busy_o <= '1'; + state_s <= PRE; + busy_o <= '1'; --Load data phyaddr_s <= phyaddr_i; regaddr_s <= regaddr_i; datashift_s <= data_i; + rw_latched <= rw_i; + end if; + elsif state_s = CONCL then -- Wait for falling edge to + -- force output high after + -- read + if fedge_strb_s = '1' then + mdio_io <= '1'; + busy_o <= '0'; + state_s <= IDLE; + bitcounter_s <= 0; end if; - elsif state_s = CONCL then - mdio_io <= '1'; - busy_o <= '0'; - state_s <= IDLE; - bitcounter_s <= 0; elsif fedge_strb_s = '1' then - mdio_io <= '1'; + mdio_io <= '1'; bitcounter_s <= bitcounter_s + 1; case state_s is when PRE => if fedge_strb_s = '1' then - --Mdio idle high for 32 cycles + --Mdio idle high for 32 cycles if (bitcounter_s = 31) then bitcounter_s <= 0; - state_s <= SOF; + state_s <= SOF; end if; end if; when SOF => @@ -128,19 +138,19 @@ begin mdio_io <= '0'; elsif bitcounter_s = 1 then bitcounter_s <= 0; - --Mdio idle high - state_s <= OPC; + --Mdio idle high + state_s <= OPC; end if; - when OPC => --Write OPCODE + when OPC => --Write OPCODE if bitcounter_s = 0 then - if rw_i = '1' then + if rw_latched = '1' then mdio_io <= '1'; else mdio_io <= '0'; end if; elsif bitcounter_s = 1 then bitcounter_s <= 0; - if rw_i = '1' then + if rw_latched = '1' then mdio_io <= '0'; else mdio_io <= '1'; @@ -150,44 +160,46 @@ begin when PHYADDR => if bitcounter_s = 4 then bitcounter_s <= 0; - state_s <= REGADDR; + state_s <= REGADDR; end if; - mdio_io <= phyaddr_s(4); + mdio_io <= phyaddr_s(4); phyaddr_s <= phyaddr_s(3 downto 0) & '0'; when REGADDR => if bitcounter_s = 4 then bitcounter_s <= 0; - state_s <= TURN; + state_s <= TURN; end if; - mdio_io <= regaddr_s(4); + mdio_io <= regaddr_s(4); regaddr_s <= regaddr_s(3 downto 0) & '0'; - when TURN => - if rw_i = '1' then + when TURN => -- Turn MDIO to input + if rw_latched = '1' then mdio_io <= 'Z'; end if; if bitcounter_s = 1 then bitcounter_s <= 0; - state_s <= DATA; + state_s <= DATA; end if; when DATA => if bitcounter_s = 15 then bitcounter_s <= 0; - state_s <= CONCL; + state_s <= CONCL; + if rw_latched = '1' then + data_o_strb <= '1'; + end if; end if; - if rw_i = '1' then - mdio_io <= 'Z'; - --Not implemented => => - else - mdio_io <= datashift_s(15); + if rw_latched = '1' then -- read data + mdio_io <= 'Z'; + datashift_s <= datashift_s(14 downto 0) & mdio_io; + else -- write data + mdio_io <= datashift_s(15); datashift_s <= datashift_s(14 downto 0) & '0'; end if; when others => - null; -- This should not happen + null; -- This should not happen end case; end if; end if; end process smishift; - data_o <= (others => '0'); end architecture RTL;