---------------------------------------------------------------------------------- -- Company: University of Connecticut -- Engineer: Igor Senderovich -- -- Create Date: 22:52:57 11/29/2007 -- Design Name: -- Module Name: MACaddrLoad - behavioral -- Description: Loads the factory-coded MAC address for this device from -- Flash memory on the ethernet controller chip and stores it -- in dynamic RAM, together with the ethernet broadcast address -- FF-FF-FF-FF-FF-FF in the format needed for the first 12 bytes -- of a transmit packet. It also loads the device address into -- the ethernet chip MAC registers so it can recognize incoming -- packets that were sent to this device, and capture them. ---------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; library FPGA_BasicComp; use FPGA_BasicComp.BasicComp.all; entity MACaddrLoad is port ( Clk : in std_logic; Go : in std_logic; Done : out std_logic; -- RAM block access lines RAM_EN : out std_logic; RAM_ADDR_tri : out std_logic_vector (9 downto 0); RAM_WE_tri : out std_logic_vector (1 downto 0); RAM_DI_tri : out std_logic_vector (15 downto 0); RAM_DO : in std_logic_vector (15 downto 0); -- MuxIntel parallel bus lines TxRx_Go : out std_logic; TxRx_Done : in std_logic; TxRx_A_tri : out std_logic_vector (7 downto 0); TxRx_D_tri : out std_logic_vector (7 downto 0); TxRx_Rd_tri : out std_logic; TxRx_Q : in std_logic_vector (7 downto 0)); end MACaddrLoad; architecture behavioral of MACaddrLoad is type Default_DestAddr_t is array (0 to 2) of std_logic_vector (15 downto 0); constant Default_DestAddr : Default_DestAddr_t := ( X"FFFF", X"FFFF", X"FFFF" ); -- ethernet broadcast type stage_t is (S0,S1,S2,S3,S4,S5,S6,S7,S8,S9,S10,S11,S12,S13); signal stage : stage_t := S0; signal counter_4b : std_logic_vector (3 downto 0); signal Done_reg : std_logic := '0'; signal RAM_EN_reg : std_logic := '0'; signal RAM_ADDR_reg : std_logic_vector (9 downto 0) := (others => '0'); signal RAM_WE_reg : std_logic_vector (1 downto 0) := (others => '0'); signal RAM_DI_reg : std_logic_vector (15 downto 0) := (others => '0'); signal TxRx_Go_reg : std_logic := '0'; signal TxRx_A_reg : std_logic_vector (7 downto 0) := (others => '0'); signal TxRx_D_reg : std_logic_vector (7 downto 0) := (others => '0'); signal TxRx_Rd_reg : std_logic := '0'; begin RAM_EN <= RAM_EN_reg; RAM_ADDR_tri <= RAM_ADDR_reg when (RAM_EN_reg = '1') else (others => 'Z'); RAM_WE_tri <= RAM_WE_reg when (RAM_EN_reg = '1') else (others => 'Z'); RAM_DI_tri <= RAM_DI_reg when (RAM_EN_reg = '1') else (others => 'Z'); TxRx_Go <= TxRx_Go_reg; TxRx_A_tri <= TxRx_A_reg when (TxRx_Go_reg = '1') else (others => 'Z'); TxRx_D_tri <= TxRx_D_reg when (TxRx_Go_reg = '1') else (others => 'Z'); TxRx_Rd_tri <= TxRx_Rd_reg when (TxRx_Go_reg = '1') else 'Z'; Sequencer : process (Clk) variable op_complete_var : std_logic; variable indirect_var : std_logic_vector (7 downto 0); variable loop0_var : std_logic_vector (1 downto 0); variable loop1_var : std_logic_vector (1 downto 0); begin if rising_edge(Clk) then stage <= stage; counter_4b <= (others => '0'); Done_reg <= '0'; -- disable RAM when not in use RAM_EN_reg <= '0'; RAM_ADDR_reg <= (others => '0'); RAM_WE_reg <= (others => '0'); RAM_DI_reg <= (others => '0'); -- disable MuxIntel bus when not in use TxRx_Go_reg <= '0'; TxRx_A_reg <= (others => '0'); TxRx_D_reg <= (others => '0'); TxRx_Rd_reg <= '0'; op_complete_var := TxRx_Go_reg and TxRx_Done; case stage is when S0 => if (Go = '1') then stage <= S1; end if; -------------------------------------------------- -- Load the default destination address into the -- first 6 bytes of the MAC address array in RAM. -------------------------------------------------- when S1 => RAM_EN_reg <= '1'; RAM_WE_reg <= "11"; RAM_ADDR_reg <= X"04" & "00"; RAM_DI_reg <= Default_DestAddr(0); stage <= S2; when S2 => RAM_EN_reg <= '1'; RAM_WE_reg <= "11"; RAM_ADDR_reg <= X"04" & "01"; RAM_DI_reg <= Default_DestAddr(1); stage <= S3; when S3 => RAM_EN_reg <= '1'; RAM_WE_reg <= "11"; RAM_ADDR_reg <= X"04" & "10"; RAM_DI_reg <= Default_DestAddr(2); stage <= S4; -------------------------------------------------------------- -- Set Flash memory pointer FLASHADDRH(0x69):FLASHADDRL(0x68) -- to the beginning of factory-stored MAC address: 0x1ffa -------------------------------------------------------------- when S4 => TxRx_A_reg <= X"69"; TxRx_D_reg <= X"1f"; TxRx_Rd_reg <= '0'; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= S5; end if; when S5 => TxRx_A_reg <= X"68"; TxRx_D_reg <= X"fa"; TxRx_Rd_reg <= '0'; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= S6; end if; ----------------------------------------------------------- -- Use FlashAutoRD interface to scroll through the 6 bytes -- of the MAC address 2 bytes at a time, storing in RAM. ----------------------------------------------------------- when S6 => RAM_EN_reg <= '1'; RAM_WE_reg <= "10"; RAM_ADDR_reg <= "0000010011"; RAM_DI_reg <= TxRx_Q & TxRx_Q; TxRx_A_reg <= X"05"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= S7; end if; when S7 => RAM_EN_reg <= '1'; RAM_WE_reg <= "01"; RAM_ADDR_reg <= "0000010011"; TxRx_A_reg <= X"05"; TxRx_Rd_reg <= '1'; RAM_DI_reg <= TxRx_Q & TxRx_Q; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= S8; end if; when S8 => RAM_EN_reg <= '1'; RAM_WE_reg <= "10"; RAM_ADDR_reg <= "0000010100"; RAM_DI_reg <= TxRx_Q & TxRx_Q; TxRx_A_reg <= X"05"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= S9; end if; when S9 => RAM_EN_reg <= '1'; RAM_WE_reg <= "01"; RAM_ADDR_reg <= "0000010100"; RAM_DI_reg <= TxRx_Q & TxRx_Q; TxRx_A_reg <= X"05"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= S10; end if; when S10 => RAM_EN_reg <= '1'; RAM_WE_reg <= "10"; RAM_ADDR_reg <= "0000010101"; RAM_DI_reg <= TxRx_Q & TxRx_Q; TxRx_A_reg <= X"05"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= S11; end if; when S11 => RAM_EN_reg <= '1'; RAM_WE_reg <= "01"; RAM_ADDR_reg <= "0000010101"; RAM_DI_reg <= TxRx_Q & TxRx_Q; TxRx_A_reg <= X"05"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= S12; end if; ---------------------------------------------------------- -- To set the MAC address in the MAC controller, first -- set MACADDR to the first indirect 16-bit register, -- load the first two bytes into MACDATAL:MACDATAH, and -- then write a 0 into MACRW. Repeat two more times. -- Warning: the MAC wants the address in reverse order -- from how it is stored in the Flash memory! ---------------------------------------------------------- when S12 => loop0_var := counter_4b(1 downto 0); loop1_var := counter_4b(3 downto 2); case loop1_var is when "00" => indirect_var := X"12"; RAM_ADDR_reg <= "0000010011"; when "01" => indirect_var := X"11"; RAM_ADDR_reg <= "0000010100"; when others => indirect_var := X"10"; RAM_ADDR_reg <= "0000010101"; end case; RAM_EN_reg <= '1'; RAM_WE_reg <= "00"; -- RAM_DO is only valid after second clock in S12, but -- that is ok because it is only used at second loop0 pass. case loop0_var is when "00" => TxRx_A_reg <= X"0A"; TxRx_D_reg <= indirect_var; when "01" => TxRx_A_reg <= X"0B"; TxRx_D_reg <= RAM_DO(7 downto 0); when "10" => TxRx_A_reg <= X"0C"; TxRx_D_reg <= RAM_DO(15 downto 8); when others => -- should not occurr TxRx_A_reg <= X"0D"; TxRx_D_reg <= X"00"; end case; TxRx_Rd_reg <= '0'; TxRx_Go_reg <= not TxRx_Done; counter_4b <= counter_4b; if (op_complete_var = '1') then counter_4b <= counter_4b + 1; if (counter_4b = "1011") then stage <= S13; end if; end if; ------------------------------------------------- -- MAC address is now set in the MAC controller -- registers in the required order LSB...MSB, -- and also stored in RAM in order MSB...LSB ------------------------------------------------- when S13 => if (Go = '1') then Done_reg <= '1'; else stage <= S0; end if; end case; else stage <= stage; Done_reg <= Done_reg; counter_4b <= counter_4b; RAM_EN_reg <= RAM_EN_reg; RAM_ADDR_reg <= RAM_ADDR_reg; RAM_WE_reg <= RAM_WE_reg; RAM_DI_reg <= RAM_DI_reg; TxRx_Go_reg <= TxRx_Go_reg; TxRx_A_reg <= TxRx_A_reg; TxRx_D_reg <= TxRx_D_reg; TxRx_Rd_reg <= TxRx_Rd_reg; end if; end process; Done <= Done_reg; end behavioral;