From 643d40c1c4d154e0ac922402663349521c372e3a Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 2 Aug 2010 11:00:08 +0200 Subject: Add packages needed for TSE MAC --- lib/ethernet/components/mdio_interface.vhd | 349 +++++++++++++++++ .../components/mii_management_transmit.vhd | 178 +++++++++ lib/ethernet/components/rmii_in_out.vhd | 339 ++++++++++++++++ lib/ethernet/components/rmii_phy_to_mii_mac.vhd | 217 +++++++++++ lib/misc/components/bibuf_async.vhd | 69 ++++ lib/misc/ines_vhdl_lib_base_pkg.vhd | 129 +++++++ lib/misc/reduce_pkg.vhd | 424 +++++++++++++++++++++ 7 files changed, 1705 insertions(+) create mode 100644 lib/ethernet/components/mdio_interface.vhd create mode 100644 lib/ethernet/components/mii_management_transmit.vhd create mode 100644 lib/ethernet/components/rmii_in_out.vhd create mode 100644 lib/ethernet/components/rmii_phy_to_mii_mac.vhd create mode 100644 lib/misc/components/bibuf_async.vhd create mode 100644 lib/misc/ines_vhdl_lib_base_pkg.vhd create mode 100644 lib/misc/reduce_pkg.vhd (limited to 'lib') diff --git a/lib/ethernet/components/mdio_interface.vhd b/lib/ethernet/components/mdio_interface.vhd new file mode 100644 index 0000000..483dcf1 --- /dev/null +++ b/lib/ethernet/components/mdio_interface.vhd @@ -0,0 +1,349 @@ +------------------------------------------------------------------ +-- _____ ______ _____ - +-- |_ _| | ____|/ ____| Institute of Embedded Systems - +-- | | _ __ | |__ | (___ Zuercher Hochschule fuer - +-- | | | '_ \| __| \___ \ angewandte Wissenschaften - +-- _| |_| | | | |____ ____) | (University of Applied Sciences) - +-- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - +------------------------------------------------------------------ +-- +-- Project : SInet +-- Module : +-- Description : MDIO Interface and Link status check +-- +-- $LastChangedDate: 2010-03-02 12:22:00 +0100 (Tue, 02 Mar 2010) $ +-- $Rev: 3094 $ +-- $Author: beut $ +----------------------------------------------------------------- +-- +-- Change History +-- Date |Name |Modification +------------|----------|----------------------------------------- +-- 2.05.07 | GLC | file created +----------------------------------------------------------------- +-- 02.11.07 | ffar | adaptation for SInet +----------------------------------------------------------------- +-- 01.03.10 | ffar | add state write Mode (RMII/MII selectabel) +----------------------------------------------------------------- + +library ieee; + use ieee.numeric_std.all; + use ieee.std_logic_1164.all; +library ines_ethernet; + use ines_ethernet.mii_management_transmit_pkg.all; +library ines_misc; + use ines_misc.ines_vhdl_lib_base_pkg.all; + use ines_misc.reduce_pack.all; + +package mdio_interface_pkg is + component mdio_interface + generic( + C_SET_TO_MII : boolean := false; + CLK_DIVIDER : natural := 10; -- divider for MDC + CHK_INTERVAL : natural := 50e6; -- link check interval in clk_i cycles + NO_OF_PORTS : natural := 1; -- number of ports to poll => max 4 + ADDR_PORT_1 : natural := 1; + ADDR_PORT_2 : natural := 2; + ADDR_PORT_3 : natural := 3; + ADDR_PORT_4 : natural := 4 + ); + port( + clk_i : in std_logic; + reset_n_i : in std_logic; + -- manual access + phy_addr_i : in std_logic_vector(4 downto 0); + phy_reg_i : in std_logic_vector(4 downto 0); + phy_data_i : in std_logic_vector(15 downto 0); + phy_data_o : out std_logic_vector(15 downto 0); + send_i : in std_logic; + read_i : in std_logic; + busy_n_o : out std_logic; + -- Status out + link_o : out std_logic_vector(3 downto 0); -- 1= link OK + reset_phy_i : in std_logic_vector(3 downto 0); -- 1= reset phy + -- MDIO + mdio_i : in std_logic; + mdio_o : out std_logic; + mdio_oe_o : out std_logic; + mdc_o : out std_logic + ); + end component; +end package mdio_interface_pkg; + + + + +library ieee; + use ieee.numeric_std.all; + use ieee.std_logic_1164.all; +library ines_ethernet; + use ines_ethernet.mii_management_transmit_pkg.all; +library ines_misc; + use ines_misc.ines_vhdl_lib_base_pkg.all; + use ines_misc.reduce_pack.all; + + +entity mdio_interface is + generic( + C_SET_TO_MII : boolean := false;-- set to mii mode (otherwise mii mode, otherwise rmii is enabled) + CLK_DIVIDER : natural := 10; -- divider for MDC + CHK_INTERVAL : natural := 50e6; -- link check interval in clk_i cycles + NO_OF_PORTS : natural := 1; -- number of ports to poll => max 4 + ADDR_PORT_1 : natural := 1; + ADDR_PORT_2 : natural := 2; + ADDR_PORT_3 : natural := 3; + ADDR_PORT_4 : natural := 4 + ); + port( + clk_i : in std_logic; + reset_n_i : in std_logic; + -- manual access + phy_addr_i : in std_logic_vector(4 downto 0); + phy_reg_i : in std_logic_vector(4 downto 0); + phy_data_i : in std_logic_vector(15 downto 0); + phy_data_o : out std_logic_vector(15 downto 0); + send_i : in std_logic; + read_i : in std_logic; + busy_n_o : out std_logic; + -- Status out + link_o : out std_logic_vector(3 downto 0); -- 1= link OK + reset_phy_i : in std_logic_vector(3 downto 0); -- 1= reset phy + -- MDIO + mdio_i : in std_logic; + mdio_o : out std_logic; + mdio_oe_o : out std_logic; + mdc_o : out std_logic + ); +end mdio_interface; + + + +architecture rtl of mdio_interface is + + type states is (S_IDLE, S_WAIT, S_RESET, S_RESTART, S_GETLINK, S_WAIT_GETLINK, + S_RMII_READ, S_RMII_READ_WAIT, S_RMII_WRITE, S_RMII_WRITE_WAIT, S_READ, S_WRITE); + signal current_state : states; + + signal interval_cnt : integer range 0 to CHK_INTERVAL; + signal chk_link : std_logic; + signal write_mode : std_logic; + + signal curr_phy_no : integer range 1 to NO_OF_PORTS; + + signal phy_addr : std_logic_vector(4 downto 0); + signal phy_reg : std_logic_vector(4 downto 0); + signal phy_dat_i : std_logic_vector(15 downto 0); + signal phy_dat_o : std_logic_vector(15 downto 0); + signal rmii_reg_dat : std_logic_vector(15 downto 0); + signal phy_write : std_logic; + signal phy_read : std_logic; + signal phy_done : std_logic; + signal done_f : std_logic; + + constant CONTROL_REG : std_logic_vector(4 downto 0) := "00000"; -- 0x00 + constant STATUS_REG : std_logic_vector(4 downto 0) := "10000"; -- 0x10 + constant RMII_REG : std_logic_vector(4 downto 0) := "10111"; -- 0x17 + + constant C_RMII_MII_BITMASK : std_logic_vector(15 downto 0) := "0000000000010000"; -- 0x10 + + constant MII_ADDR : std_logic_array_5(1 to 4) := (std_logic_vector(to_unsigned(ADDR_PORT_1,5)), + std_logic_vector(to_unsigned(ADDR_PORT_2,5)), + std_logic_vector(to_unsigned(ADDR_PORT_3,5)), + std_logic_vector(to_unsigned(ADDR_PORT_4,5))); + +begin + + phy_data_o <= phy_dat_o; + busy_n_o <= phy_done; + + sm_proc : process (clk_i, reset_n_i, current_state, chk_link, reset_phy_i, send_i, read_i, phy_done, curr_phy_no) + begin + if reset_n_i = '0' then + phy_addr <= (others => '0'); + phy_reg <= (others => '0'); + phy_dat_o <= (others => '0'); + phy_write <= '0'; + phy_read <= '0'; + current_state <= S_IDLE; + link_o <= (others => '0'); + curr_phy_no <= 1; + done_f <= '0'; + elsif clk_i'event and clk_i = '1' then + + phy_write <= '0'; + phy_read <= '0'; + + case current_state is + + when S_IDLE => + if chk_link = '1' then + current_state <= S_GETLINK; + elsif write_mode = '1' then + current_state <= S_RMII_READ; + elsif or_reduce(reset_phy_i) = '1' then -- /= "0000" then + current_state <= S_RESET; + elsif send_i = '1' then + current_state <= S_WRITE; + elsif read_i = '1' then + current_state <= S_READ; + end if; + + + when S_GETLINK => + phy_addr <= MII_ADDR(curr_phy_no); + phy_reg <= STATUS_REG; + phy_read <= '1'; + + current_state <= S_WAIT_GETLINK; + + + when S_WAIT_GETLINK => + if phy_done = '1' and done_f = '0' and curr_phy_no < NO_OF_PORTS then + link_o(curr_phy_no-1) <= phy_dat_i(0); + curr_phy_no <= curr_phy_no + 1; + current_state <= S_GETLINK; + elsif phy_done = '1' and done_f = '0' then + link_o(curr_phy_no-1) <= phy_dat_i(0); + curr_phy_no <= 1; + current_state <= S_IDLE; + end if; + + + when S_RMII_READ => + phy_addr <= MII_ADDR(curr_phy_no); + phy_reg <= RMII_REG; + phy_read <= '1'; + + current_state <= S_RMII_READ_WAIT; + + + when S_RMII_READ_WAIT => + if phy_done = '1' and done_f = '0' then + rmii_reg_dat <= phy_dat_i; + current_state <= S_RMII_WRITE; + end if; + + + when S_RMII_WRITE => + phy_addr <= MII_ADDR(curr_phy_no); + phy_reg <= RMII_REG; + if C_SET_TO_MII = true then + -- Clear Bit Nr 5 and set PHY in MII MODE + phy_dat_o <= rmii_reg_dat and (not C_RMII_MII_BITMASK); + else + -- Set Bit Nr 5 and set PHY in RMII MODE + phy_dat_o <= rmii_reg_dat or C_RMII_MII_BITMASK; + end if; + phy_write <= '1'; + + current_state <= S_RMII_WRITE_WAIT; + + + when S_RMII_WRITE_WAIT => + if phy_done = '1' and done_f = '0' and curr_phy_no < NO_OF_PORTS then + curr_phy_no <= curr_phy_no + 1; + -- Start Read and Write for other PHY's + current_state <= S_RMII_READ; + elsif phy_done = '1' and done_f = '0' then + curr_phy_no <= 1; + current_state <= S_IDLE; + end if; + + + when S_READ => + phy_addr <= phy_addr_i; + phy_reg <= phy_reg_i; + phy_read <= '1'; + + current_state <= S_WAIT; + + + when S_WRITE => + phy_addr <= phy_addr_i; + phy_reg <= phy_reg_i; + phy_dat_o <= phy_data_i; + phy_write <= '1'; + + current_state <= S_WAIT; + + + when S_RESET => + if reset_phy_i(0) = '1' then + phy_addr <= MII_ADDR(1); + elsif reset_phy_i(1) = '1' then + phy_addr <= MII_ADDR(2); + elsif reset_phy_i(2) = '1' then + phy_addr <= MII_ADDR(3); + elsif reset_phy_i(3) = '1' then + phy_addr <= MII_ADDR(4); + end if; + phy_reg <= CONTROL_REG; + phy_dat_o <= X"8000"; + phy_write <= '1'; + + current_state <= S_WAIT; + + + when S_RESTART => + current_state <= S_IDLE; + + + when S_WAIT => + if phy_done = '1' and done_f = '0' then + current_state <= S_IDLE; + end if; + + end case; + done_f <= phy_done; + end if; + end process; + + interval_proc : process (clk_i, reset_n_i) + begin + if reset_n_i = '0' then + interval_cnt <= 0; + chk_link <= '0'; + write_mode <= '0'; + elsif clk_i'event and clk_i = '1' then + chk_link <= '0'; + write_mode <= '0'; + + if interval_cnt < CHK_INTERVAL then + interval_cnt <= interval_cnt + 1; + else + interval_cnt <= 0; + chk_link <= '1'; + end if; + + if interval_cnt = CHK_INTERVAL - 10000 then + write_mode <= '1'; + end if; + + end if; + end process; + + + mdio_transceiver : mii_management_transmit + generic map( + G_CLK_DIVIDER => CLK_DIVIDER + ) + port map( + clk => clk_i, + reset_n => reset_n_i, + + phy_addr_i => phy_addr, + phy_reg_i => phy_reg, + phy_data_i => phy_dat_o, + phy_data_o => phy_dat_i, + send_i => phy_write, + read_i => phy_read, + done_o => phy_done, + + mdc_pad_o => mdc_o, + md_pad_i => mdio_i, + md_pad_o => mdio_o, + md_padoe_o => mdio_oe_o + ); + +end rtl; + diff --git a/lib/ethernet/components/mii_management_transmit.vhd b/lib/ethernet/components/mii_management_transmit.vhd new file mode 100644 index 0000000..4a81d8f --- /dev/null +++ b/lib/ethernet/components/mii_management_transmit.vhd @@ -0,0 +1,178 @@ +------------------------------------------------------------------ +-- _____ ______ _____ - +-- |_ _| | ____|/ ____| Institute of Embedded Systems - +-- | | _ __ | |__ | (___ Zuercher Hochschule fuer - +-- | | | '_ \| __| \___ \ angewandte Wissenschaften - +-- _| |_| | | | |____ ____) | (University of Applied Sciences) - +-- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - +------------------------------------------------------------------ +-- +-- Project : SInet +-- Module : +-- Description : MDIO low level protocol +-- +-- $LastChangedDate: 2008-10-31 12:06:00 +0100 (Fri, 31 Oct 2008) $ +-- $Rev: 1905 $ +-- $Author: ffar $ +----------------------------------------------------------------- +-- +-- Change History +-- Date |Name |Modification +----------------------------------------------------------------- +-- 02.11.07 | ffar | file created based on library component +-- | | from glc (27.09.05) +----------------------------------------------------------------- + + +library ieee; + use ieee.numeric_std.all; + use ieee.std_logic_1164.all; + +package mii_management_transmit_pkg is + component mii_management_transmit + generic( + G_CLK_DIVIDER : in integer + ); + port( + clk : in std_logic; + reset_n : in std_logic; + + phy_addr_i : in std_logic_vector(4 downto 0); + phy_reg_i : in std_logic_vector(4 downto 0); + phy_data_i : in std_logic_vector(15 downto 0); + phy_data_o : out std_logic_vector(15 downto 0); + send_i : in std_logic; + read_i : in std_logic; + done_o : out std_logic; + + mdc_pad_o : out std_logic; + md_pad_i : in std_logic; + md_pad_o : out std_logic; + md_padoe_o : out std_logic + ); + end component mii_management_transmit; +end package mii_management_transmit_pkg; + + + +library ieee; + use ieee.numeric_std.all; + use ieee.std_logic_1164.all; + +entity mii_management_transmit is + generic( + G_CLK_DIVIDER : in integer + ); + port( + clk : in std_logic; + reset_n : in std_logic; + + phy_addr_i : in std_logic_vector(4 downto 0); + phy_reg_i : in std_logic_vector(4 downto 0); + phy_data_i : in std_logic_vector(15 downto 0); + phy_data_o : out std_logic_vector(15 downto 0); + send_i : in std_logic; + read_i : in std_logic; + done_o : out std_logic; + + mdc_pad_o : out std_logic; + md_pad_i : in std_logic; + md_pad_o : out std_logic; + md_padoe_o : out std_logic + ); +end mii_management_transmit; + +architecture rtl of mii_management_transmit is + + + signal confdata : std_logic_vector(32 downto 0) := (others => '0'); + signal rec_data : std_logic_vector(15 downto 0); + signal conf_v : integer range 0 to 64; + signal cnt_v : integer range 0 to G_CLK_DIVIDER; + signal mdc : std_logic; + signal send : std_logic; + +begin + + phy_data_o <= rec_data; + + phy_config : process(clk, reset_n, mdc, send_i, read_i, phy_addr_i, phy_reg_i, phy_data_i, md_pad_i, conf_v) + begin + if reset_n = '0' then + conf_v <= 0; + md_pad_o <= '0'; + md_padoe_o <= '0'; + done_o <= '1'; + confdata <= (others => '0'); + rec_data <= (others => '0'); + send <= '0'; + elsif clk'event and clk = '1' then + if conf_v > 32 then -- send preamble + done_o <= '0'; + md_pad_o <= '1'; + if mdc = '1' then + conf_v <= conf_v - 1; + end if; + elsif conf_v > 0 and send = '1' then -- send data + if mdc = '1' then + md_pad_o <= confdata(conf_v); + conf_v <= conf_v - 1; + end if; + elsif conf_v > 16 and send = '0' then -- receive data + if mdc = '1' then + md_pad_o <= confdata(conf_v); + conf_v <= conf_v - 1; + end if; + elsif conf_v > 0 and send = '0' then -- store data + if mdc = '1' then + rec_data(15 downto 1) <= rec_data(14 downto 0); + rec_data(0) <= md_pad_i; + conf_v <= conf_v - 1; + end if; + elsif send_i = '1' then + confdata <= "0101" & phy_addr_i & phy_reg_i & "10" & phy_data_i & "0"; + conf_v <= 64; + send <= '1'; + done_o <= '0'; + elsif read_i = '1' then + confdata <= "0110" & phy_addr_i & phy_reg_i & X"0000" & "000"; + conf_v <= 64; + send <= '0'; + done_o <= '0'; + else + send <= '0'; + md_pad_o <= '0'; + done_o <= '1'; + end if; + + if send = '1' OR conf_v >= 18 then + md_padoe_o <= '1'; + else + md_padoe_o <= '0'; + end if; + + end if; + end process; + + clk_div : process(clk, reset_n, cnt_v) + begin + if reset_n = '0' then + cnt_v <= 0; + mdc_pad_o <= '0'; + mdc <= '0'; + elsif clk'event and clk = '1' then + mdc <= '0'; + if cnt_v = G_CLK_DIVIDER/2+1 then + mdc_pad_o <= '0'; + mdc <= '1'; + cnt_v <= cnt_v - 1; + elsif cnt_v <= 1 then + mdc_pad_o <= '1'; + cnt_v <= G_CLK_DIVIDER; + else + cnt_v <= cnt_v - 1; + end if; + end if; + end process; + +end rtl; \ No newline at end of file diff --git a/lib/ethernet/components/rmii_in_out.vhd b/lib/ethernet/components/rmii_in_out.vhd new file mode 100644 index 0000000..13db067 --- /dev/null +++ b/lib/ethernet/components/rmii_in_out.vhd @@ -0,0 +1,339 @@ +------------------------------------------------------------------ +-- _____ ______ _____ - +-- |_ _| | ____|/ ____| Institute of Embedded Systems - +-- | | _ __ | |__ | (___ Zuercher Hochschule fuer - +-- | | | '_ \| __| \___ \ angewandte Wissenschaften - +-- _| |_| | | | |____ ____) | (University of Applied Sciences) - +-- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - +------------------------------------------------------------------ +-- +-- Project : SInet +-- Module : synthesis library ines_ethernet +--! \file +--! \brief RMII to byte stream converter +-- +-- $LastChangedDate: 2010-04-14 15:27:24 +0200 (Wed, 14 Apr 2010) $ +-- $Rev: 3244 $ +-- $Author: beut $ +----------------------------------------------------------------- +-- +-- Change History +-- Date |Name |Modification +----------------------------------------------------------------- +-- 13.02.07 | GLC | file created +----------------------------------------------------------------- +-- 02.11.07 | ffar | adaptation for SInet +----------------------------------------------------------------- +-- 20.06.08 | beut | preambel and SFD Generator added +----------------------------------------------------------------- +-- 14.04.10 | beut | Interframe gap counter added +----------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +--! \brief This packages provides an interface to an RMII 100BaseTX phy +package rmii_in_out_pkg is + component rmii_in_out + generic( + G_AMOUNT_OF_PREAMBEL_AND_SFD_BYTES : natural := 4; + G_IFG_CLOCKS : natural := 48 -- 96 Bit ==> 960ns @ 100Mbit ==> IFG = 48 @ 20ns Clockperiode + ); + port ( + clk_i : in std_logic; -- 50 Mhz + reset_n_i : in std_logic; + -- RMII in + rxd_i : in std_logic_vector(1 downto 0); + rx_dv_i : in std_logic; + crs_dv_i : in std_logic; + col_i : in std_logic; + -- RMII out + txd_o : out std_logic_vector(1 downto 0); + tx_en_o : out std_logic; + -- Data out + rx_data_o : out std_logic_vector(7 downto 0); + rx_stb_o : out std_logic; + rx_dv_o : out std_logic; + -- Data in + tx_data_i : in std_logic_vector(7 downto 0); + tx_en_i : in std_logic; + tx_ack_o : out std_logic; + -- Other + get_time_o : out std_logic; + frame_start_o : out std_logic; + frame_end_o : out std_logic + ); + end component rmii_in_out; +end package rmii_in_out_pkg; + + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + + +--! \brief Interface to RMII 100BaseTX phy +--! \details This interface is a bidirectional converter between byte stream +--! interface and RMII. It also provides start of frame and end of +--! frame signals. +--! Because of generic byte stream interface it can be easily +--! replaced by coresponding MII interface. +entity rmii_in_out is + generic( + G_AMOUNT_OF_PREAMBEL_AND_SFD_BYTES : natural := 4; --! number of preamble bytes which are sent + G_IFG_CLOCKS : natural := 48 -- 96 Bit ==> 960ns @ 100Mbit ==> IFG = 48 @ 20ns Clockperiode + ); + port ( + --!@name Clock and reset inputs + --@{ + clk_i : in std_logic; --! This clock must run at 50 Mhz + reset_n_i : in std_logic; --! negative, asynchronous reset + --!@} + + --!@name RMII input (from Network) + --@{ + rxd_i : in std_logic_vector(1 downto 0); --! Data input + rx_dv_i : in std_logic; --! Receive data valid + crs_dv_i : in std_logic; --! carrier sense (not used) + col_i : in std_logic; --! collision detected (not used) + --!@} + + --!@name RMII out (to Network) + --@{ + txd_o : out std_logic_vector(1 downto 0); --! Transmit data out + tx_en_o : out std_logic; --! Transmit data enable + --!@} + + --!@name Data out to FPGA + --@{ + rx_data_o : out std_logic_vector(7 downto 0); --! Receive data + rx_stb_o : out std_logic; --! Receive data strobe + rx_dv_o : out std_logic; --! Receive data valid + --!@} + + --!@name Data in from FPGA + --@{ + tx_data_i : in std_logic_vector(7 downto 0); --! Transmit data out + tx_en_i : in std_logic; --! Transmit data enable + tx_ack_o : out std_logic; --! Transmit data acknowledge + --!@} + + --!@name Additional information signals + --@{ + get_time_o : out std_logic; --! Frame start in preamble detected --> take 1588 time stamp + frame_start_o : out std_logic; --! Pulse at frame start, after preamble + frame_end_o : out std_logic --! Pulse at frame end + --!@} + ); +end rmii_in_out; + +--! \brief The pincount optimised RMII interface is converted to 8 Bit byte stream interface +--! \details Data are received at 50MHz from phy. There is no separate clock signal between +--! phy and FPGA. Instead of using a separate clock signal, both chips are connected to +--! the same clock source. The output data stream which is delivered to the FPGA internal +--! components is 8 Bit wide, with clock signal. The send path does the oposite. +architecture rtl of rmii_in_out is + + --! \name Receive signals + --!@{ + --! receive fsm states enumeration + type states is (Wait_For_Start_Of_Frame, Wait_For_End_Of_Frame, + Preamble, Sfd, Frame, Toggle_Or_End_Of_Frame); + --! receive fsm states + signal state : states; + --! Used for edge detection at end of frame + signal rx_dv_i_f : std_logic; + --! shows active frame stream (same as rx_dv_o) + signal frame_in : std_logic; + --! frame_in edge pulse + signal frame_in_f : std_logic; + --! parallelise the 2 bit input stream to 8 bit + signal data_buffer : std_logic_vector(7 downto 0); + --! pointer to data_buffer + signal data_i_position : integer range 0 to 3; + --!@} + + --! \name Transmit signals + --!@{ + --! pointer to tx_data + signal nibble_cnt : integer range 0 to 3 := 3; + --! transmit data + signal tx_data : std_logic_vector(7 downto 0); + --! transmit enable + signal tx_en : std_logic; + --! transmit enable one clock delayed + signal tx_en_f : std_logic; + --! preamble byte counter + signal preamble_cnt : integer range 0 to 7; + --!@} + + --! \name IFG signals + --!@{ + --! counts the IFG + signal ifg_cnt : natural range 0 to G_IFG_CLOCKS; + --!@} + +begin + + rx_dv_o <= frame_in; + + frame_start_o <= frame_in and (not frame_in_f); + frame_end_o <= (not frame_in) and frame_in_f; + tx_en_o <= tx_en; + + --! receive frames and cut off pramble + rmii_in_out_proc : process (reset_n_i, clk_i) + begin + if (reset_n_i = '0') then + get_time_o <= '0'; + rx_dv_i_f <= '0'; + frame_in <= '0'; + state <= Wait_For_Start_Of_Frame; + elsif (clk_i'event and clk_i = '1') then + + rx_dv_i_f <= rx_dv_i; + + case state is + when Wait_For_Start_Of_Frame => + get_time_o <= '0'; + if rx_dv_i = '1' then + state <= Preamble; + else + state <= Wait_For_Start_Of_Frame; + end if; + + when Preamble => + if rx_dv_i /= '1' then + state <= Wait_For_End_Of_Frame; + elsif rxd_i = "01" then -- preamble detected + state <= Sfd; + else + state <= Preamble; + end if; + + when Sfd => + if rx_dv_i /= '1' then + state <= Wait_For_End_Of_Frame; + elsif rxd_i = "11" then -- SFD detected + get_time_o <= '1'; + state <= Frame; + else + state <= Sfd; + end if; + + when Frame => + frame_in <= '1'; + if rx_dv_i /= '1' then + state <= Wait_For_End_Of_Frame; + else + state <= Frame; + end if; + + when Wait_For_End_Of_Frame => + if (rx_dv_i /= '1' and rx_dv_i_f /= '1') then + get_time_o <= '0'; + frame_in <= '0'; + state <= Wait_For_Start_Of_Frame; + else + state <= Wait_For_End_Of_Frame; + end if; + + when others => + state <= Wait_For_End_Of_Frame; + + end case; + end if; + end process; + + --! converts 2 bit RMII data to bytes + conv_2_to_8bit_proc : process (reset_n_i, clk_i) + begin + + if (reset_n_i = '0') then + rx_stb_o <= '0'; + rx_data_o <= (others => '0'); + data_buffer <= (others => '0'); + data_i_position <= 0; + frame_in_f <= '0'; + elsif (clk_i'event and clk_i = '1') then + + rx_stb_o <= '0'; + frame_in_f <= frame_in; + + data_buffer(5 downto 0) <= data_buffer(7 downto 2); + data_buffer(7 downto 6) <= rxd_i; + + if rx_dv_i = '1' and rx_dv_i_f = '0' then -- reset at start of frame + data_i_position <= 0; + rx_data_o <= (others => '0'); + elsif frame_in = '1' then -- store data + + if data_i_position < 3 then + data_i_position <= data_i_position + 1; + else + data_i_position <= 0; + rx_data_o <= data_buffer; + rx_stb_o <= '1'; -- indicates a valid byte + end if; + + end if; + end if; + end process; + + txd_o <= tx_data(1 downto 0); + + --! send frames and generate preamble + rmii_out_proc : process (reset_n_i, clk_i) + begin + if (reset_n_i = '0') then + tx_data <= (others => '0'); + tx_en <= '0'; + tx_ack_o <= '0'; + nibble_cnt <= 3; + preamble_cnt <= 0; + elsif (clk_i'event and clk_i = '1') then + tx_ack_o <= '0'; + if (tx_en_i = '1' or nibble_cnt < 3) and ifg_cnt = 0 then -- framestart or send last nibble + tx_en <= '1'; -- start + if nibble_cnt < 3 then -- continute byte + tx_data(5 downto 0) <= tx_data(7 downto 2); + tx_data(7 downto 6) <= "00"; + nibble_cnt <= nibble_cnt + 1; + elsif preamble_cnt + 1 < G_AMOUNT_OF_PREAMBEL_AND_SFD_BYTES then -- send preamble + tx_data <= b"0101_0101"; + preamble_cnt <= preamble_cnt + 1; + nibble_cnt <= 0; + elsif preamble_cnt + 1 = G_AMOUNT_OF_PREAMBEL_AND_SFD_BYTES then -- send sfd + tx_data <= b"1101_0101"; + preamble_cnt <= preamble_cnt + 1; + nibble_cnt <= 0; + else -- send data + tx_data <= tx_data_i; + tx_ack_o <= '1'; + nibble_cnt <= 0; + end if; + else -- stop + tx_en <= '0'; + preamble_cnt <= 0; + nibble_cnt <= 3; + end if; + end if; + end process; + + --! Interframe Gap Counter + ifg_counter : process(clk_i, reset_n_i) + begin + if reset_n_i = '0' then + ifg_cnt <= 0; + tx_en_f <= '0'; + elsif clk_i'event and clk_i = '1' then + tx_en_f <= tx_en; -- tx_en one clock delayed + if tx_en = '0' and tx_en_f = '1' then -- end of frame + ifg_cnt <= G_IFG_CLOCKS; + elsif ifg_cnt > 0 then + ifg_cnt <= ifg_cnt -1; + end if; + end if; + end process ifg_counter; + +end rtl; \ No newline at end of file diff --git a/lib/ethernet/components/rmii_phy_to_mii_mac.vhd b/lib/ethernet/components/rmii_phy_to_mii_mac.vhd new file mode 100644 index 0000000..09227c6 --- /dev/null +++ b/lib/ethernet/components/rmii_phy_to_mii_mac.vhd @@ -0,0 +1,217 @@ +------------------------------------------------------------------ +-- _____ ______ _____ - +-- |_ _| | ____|/ ____| - +-- | | _ __ | |__ | (___ Institute of Embedded Systems - +-- | | | '_ \| __| \___ \ Zuercher Hochschule Winterthur - +-- _| |_| | | | |____ ____) | (University of Applied Sciences) - +-- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - +------------------------------------------------------------------ +-- +-- Project : SInet +-- Description : Connects the data interface of a PHY in RMMI Mode and a MAC +-- in MII Mode +-- $LastChangedDate: 2006-11-14 12:14:54 +0100 (Tue, 14 Nov 2006) $ +-- $Rev: 1358 $ +-- $Author: beut $ +----------------------------------------------------------------- +-- +-- Change History +-- Date |Name |Modification +------------|----------|----------------------------------------- +-- 20.02.09 | beut | file ceated +----------------------------------------------------------------- +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package rmii_phy_to_mii_mac_pkg is + component rmii_phy_to_mii_mac + port ( + reset_n_i : in std_logic; + clk_25_i : in std_logic; + clk_50_i : in std_logic; + rmii_crs_i : in std_logic; + + -- Transmit Path + mii_tx_en_i : in std_logic; + mii_txd_i : in std_logic_vector(3 downto 0); + rmii_tx_en_o : out std_logic; + rmii_txd_o : out std_logic_vector(1 downto 0); + + -- Receive Path + rmii_rx_dv_i : in std_logic; + rmii_rxd_i : in std_logic_vector(1 downto 0); + mii_rx_dv_o : out std_logic; + mii_rxd_o : out std_logic_vector(3 downto 0) + ); + end component rmii_phy_to_mii_mac; +end package rmii_phy_to_mii_mac_pkg; + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity rmii_phy_to_mii_mac is + port ( + reset_n_i : in std_logic; + clk_25_i : in std_logic; + clk_50_i : in std_logic; + rmii_crs_i : in std_logic; + + -- Transmit Path + mii_tx_en_i : in std_logic; + mii_txd_i : in std_logic_vector(3 downto 0); + rmii_tx_en_o : out std_logic; + rmii_txd_o : out std_logic_vector(1 downto 0); + + -- Receive Path + rmii_rx_dv_i : in std_logic; + rmii_rxd_i : in std_logic_vector(1 downto 0); + mii_rx_dv_o : out std_logic; + mii_rxd_o : out std_logic_vector(3 downto 0) + ); +end rmii_phy_to_mii_mac; + + +architecture behavior of rmii_phy_to_mii_mac is + + signal rmii_txd_next, rmii_txd_curr : std_logic; + signal clk_25_sync_to_data : std_logic; + signal clk_25_toggle, clk_50_toggle : std_logic; + signal rmii_rxd_buffer : std_logic_vector(5 downto 0); + signal mii_txd_buffer : std_logic_vector(3 downto 0); + signal buffer_cnt : integer range 0 to 1; + signal clk_50_en : std_logic; + signal rmii_rx_dv_f : std_logic; + signal mii_rx_dv_f : std_logic; + signal mii_rx_dv_ff : std_logic; + signal rmii_valid_sof : std_logic; + +begin + + ----------------------------------------------------------------- + -- Clock 50 Enable Gnerating (is high if clock 25Mhz and Clock 50 MHz are rising + ----------------------------------------------------------------- + + clock_25_proc: process (clk_25_i) + begin + if rising_edge(clk_25_i) then + clk_25_toggle <= not clk_25_toggle; + end if; + end process; + + -- The clock enable muxes data in 25MHz freqency and has the same timing like data and not the clock! + clock_50_proc: process (reset_n_i, clk_50_i) + begin + if reset_n_i = '0' then + clk_50_toggle <= '0'; + clk_50_en <= '0'; + elsif rising_edge(clk_50_i) then + clk_50_toggle <= clk_25_toggle; + -- edge detection + clk_50_en <= clk_25_toggle xor clk_50_toggle; --25 MHz clk sync to data of 50MHz + end if; + end process; + ----------------------------------------------------------------- + + + ----------------------------------------------------------------- + -- Data Muxing from MAC to PHY + ----------------------------------------------------------------- + mii_to_rmii_proc : process (clk_50_en, mii_txd_i, mii_txd_buffer) + begin + if clk_50_en = '0' then + rmii_txd_o <= mii_txd_buffer(1 downto 0); + else + rmii_txd_o <= mii_txd_buffer(3 downto 2); + end if; + end process; + + rmii_tx_en_proc: process (reset_n_i, clk_50_i) + begin + if reset_n_i = '0' then + rmii_tx_en_o <= '0'; + elsif rising_edge(clk_50_i) then + if clk_50_en = '1' then -- data changes after a beginning of 25MHz cycle + mii_txd_buffer <= mii_txd_i; + rmii_tx_en_o <= mii_tx_en_i; + end if; + end if; + end process; + + ----------------------------------------------------------------- + + + ----------------------------------------------------------------- + -- Data Muxing from PHY to MAC + ----------------------------------------------------------------- + + -- Data buffern + buffer_proc: process (reset_n_i, clk_50_i) + begin + if reset_n_i = '0' then + rmii_rxd_buffer <= (others => '0'); + elsif rising_edge(clk_50_i) then + rmii_rxd_buffer(1 downto 0) <= rmii_rxd_buffer(3 downto 2); + rmii_rxd_buffer(3 downto 2) <= rmii_rxd_buffer(5 downto 4); + rmii_rxd_buffer(5 downto 4) <= rmii_rxd_i; + end if; + end process; + + rmii_rx_dv_proc: process (reset_n_i, clk_50_i) + begin + if reset_n_i = '0' then + mii_rx_dv_f <= '0'; + mii_rx_dv_ff <= '0'; + mii_rxd_o <= (others => '0'); + elsif rising_edge(clk_50_i) then + if clk_50_en = '1' then + + if rmii_valid_sof = '1' then --only valid if the packet from phy is valid + mii_rx_dv_f <= rmii_rx_dv_i; + mii_rx_dv_ff <= mii_rx_dv_f; -- valid is two 25 MHz clockcycles later + end if; + + if buffer_cnt = 1 then -- depends on the rmii dv signal + mii_rxd_o <= rmii_rxd_buffer(3 downto 0); -- Three step buffer + else + mii_rxd_o <= rmii_rxd_buffer(5 downto 2); -- Two step buffer + end if; + end if; + end if; + end process; + mii_rx_dv_o <= mii_rx_dv_ff ; + + -- counts the 50MHz clocks before rmii dv signal goes high before a 25MHZ Clock + buffer_cnt_proc: process (reset_n_i, clk_50_i) + begin + if reset_n_i = '0' then + buffer_cnt <= 0; + elsif rising_edge(clk_50_i) then + if (rmii_rx_dv_i = '1' and rmii_rx_dv_f = '0') and clk_50_en = '0' then + buffer_cnt <= 1; + elsif (rmii_rx_dv_i = '1' and rmii_rx_dv_f = '0') and clk_50_en = '1' then + buffer_cnt <= 0; + end if; + end if; + end process; + + rmii_valid_sof_proc: process (reset_n_i, clk_50_i) + begin + if reset_n_i = '0' then + rmii_valid_sof <= '0'; + rmii_rx_dv_f <= '0'; + elsif rising_edge(clk_50_i) then + rmii_rx_dv_f <= rmii_rx_dv_i; + if rmii_crs_i = '1' and rmii_rx_dv_f = '0' and rmii_rx_dv_i = '1' then -- start of a valid frame + rmii_valid_sof <= '1'; + end if; + end if; + end process; + + + + + + +end behavior; diff --git a/lib/misc/components/bibuf_async.vhd b/lib/misc/components/bibuf_async.vhd new file mode 100644 index 0000000..915bae9 --- /dev/null +++ b/lib/misc/components/bibuf_async.vhd @@ -0,0 +1,69 @@ +------------------------------------------------------------------ +-- _____ ______ _____ - +-- |_ _| | ____|/ ____| Institute of Embedded Systems - +-- | | _ __ | |__ | (___ Zuercher Hochschule fuer - +-- | | | '_ \| __| \___ \ angewandte Wissenschaften - +-- _| |_| | | | |____ ____) | (University of Applied Sciences) - +-- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - +------------------------------------------------------------------ +-- +-- Project : InES library +-- Module : library ines_misc +-- Description : bidirectional port buffer without syncronisation +-- +-- $LastChangedDate: 2008-10-31 12:06:00 +0100 (Fri, 31 Oct 2008) $ +-- $Rev: 1905 $ +-- $Author: ffar $ +----------------------------------------------------------------- +-- +-- Change History +-- Date |Name |Modification +------------|----------|----------------------------------------- +-- 02.11.06 | ffar |file created +----------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +package bibuf_async_pkg is + component bibuf_async + port( + oe : in std_logic; + io : inout std_logic; + inp : in std_logic; + outp : out std_logic + ); + end component bibuf_async; +end package bibuf_async_pkg; + + + +library ieee; + use ieee.std_logic_1164.all; + + +entity bibuf_async is + port( + oe : in std_logic; + io : inout std_logic; + inp : in std_logic; + outp : out std_logic + ); + end bibuf_async; + +architecture rtl of bibuf_async is + +begin + + process(oe, io, inp) -- Behavioral representation + begin -- of tri-states. + if oe = '1' then + io <= inp; + outp <= inp; + else + io <= 'Z'; + outp <= io; + end if; + end process; + +end rtl; \ No newline at end of file diff --git a/lib/misc/ines_vhdl_lib_base_pkg.vhd b/lib/misc/ines_vhdl_lib_base_pkg.vhd new file mode 100644 index 0000000..e9cd602 --- /dev/null +++ b/lib/misc/ines_vhdl_lib_base_pkg.vhd @@ -0,0 +1,129 @@ +------------------------------------------------------------------ +-- _____ ______ _____ - +-- |_ _| | ____|/ ____| Institute of Embedded Systems - +-- | | _ __ | |__ | (___ Zuercher Hochschule fuer - +-- | | | '_ \| __| \___ \ angewandte Wissenschaften - +-- _| |_| | | | |____ ____) | (University of Applied Sciences) - +-- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - +------------------------------------------------------------------ +-- +-- Project : SInet +-- Module : library ines_misc +-- Description : Base package of ines misc library +-- +-- $LastChangedDate: 2007-11-02 14:43:24 +0100 (Fri, 02 Nov 2007) $ +-- $Rev: 403 $ +-- $Author: ffar $ +----------------------------------------------------------------- +-- +-- Change History +-- Date |Name |Modification +------------|----------|----------------------------------------- +-- 02.11.07 | ffar |file created +----------------------------------------------------------------- + + +library ieee; + use ieee.std_logic_1164.all; + + + +package ines_vhdl_lib_base_pkg is + + -- constants + + -- types + subtype std_logic_vector_1 is std_logic_vector(0 downto 0); + type std_logic_array_1 is array(natural range <>) of std_logic_vector_1; + subtype std_logic_vector_2 is std_logic_vector(1 downto 0); + type std_logic_array_2 is array(natural range <>) of std_logic_vector_2; + subtype std_logic_vector_3 is std_logic_vector(2 downto 0); + type std_logic_array_3 is array(natural range <>) of std_logic_vector_3; + subtype std_logic_vector_4 is std_logic_vector(3 downto 0); + type std_logic_array_4 is array(natural range <>) of std_logic_vector_4; + subtype std_logic_vector_5 is std_logic_vector(4 downto 0); + type std_logic_array_5 is array(natural range <>) of std_logic_vector_5; + subtype std_logic_vector_6 is std_logic_vector(5 downto 0); + type std_logic_array_6 is array(natural range <>) of std_logic_vector_6; + subtype std_logic_vector_7 is std_logic_vector(6 downto 0); + type std_logic_array_7 is array(natural range <>) of std_logic_vector_7; + subtype std_logic_vector_8 is std_logic_vector(7 downto 0); + type std_logic_array_8 is array(natural range <>) of std_logic_vector_8; + subtype std_logic_vector_9 is std_logic_vector(8 downto 0); + type std_logic_array_9 is array(natural range <>) of std_logic_vector_9; + subtype std_logic_vector_10 is std_logic_vector(9 downto 0); + type std_logic_array_10 is array(natural range <>) of std_logic_vector_10; + subtype std_logic_vector_11 is std_logic_vector(10 downto 0); + type std_logic_array_11 is array(natural range <>) of std_logic_vector_11; + subtype std_logic_vector_12 is std_logic_vector(11 downto 0); + type std_logic_array_12 is array(natural range <>) of std_logic_vector_12; + subtype std_logic_vector_13 is std_logic_vector(12 downto 0); + type std_logic_array_13 is array(natural range <>) of std_logic_vector_13; + subtype std_logic_vector_14 is std_logic_vector(13 downto 0); + type std_logic_array_14 is array(natural range <>) of std_logic_vector_14; + subtype std_logic_vector_15 is std_logic_vector(14 downto 0); + type std_logic_array_15 is array(natural range <>) of std_logic_vector_15; + subtype std_logic_vector_16 is std_logic_vector(15 downto 0); + type std_logic_array_16 is array(natural range <>) of std_logic_vector_16; + subtype std_logic_vector_17 is std_logic_vector(16 downto 0); + type std_logic_array_17 is array(natural range <>) of std_logic_vector_17; + subtype std_logic_vector_18 is std_logic_vector(17 downto 0); + type std_logic_array_18 is array(natural range <>) of std_logic_vector_18; + subtype std_logic_vector_19 is std_logic_vector(18 downto 0); + type std_logic_array_19 is array(natural range <>) of std_logic_vector_19; + subtype std_logic_vector_20 is std_logic_vector(19 downto 0); + type std_logic_array_20 is array(natural range <>) of std_logic_vector_20; + subtype std_logic_vector_21 is std_logic_vector(20 downto 0); + type std_logic_array_21 is array(natural range <>) of std_logic_vector_21; + subtype std_logic_vector_22 is std_logic_vector(21 downto 0); + type std_logic_array_22 is array(natural range <>) of std_logic_vector_22; + subtype std_logic_vector_23 is std_logic_vector(22 downto 0); + type std_logic_array_23 is array(natural range <>) of std_logic_vector_23; + subtype std_logic_vector_24 is std_logic_vector(23 downto 0); + type std_logic_array_24 is array(natural range <>) of std_logic_vector_24; + subtype std_logic_vector_25 is std_logic_vector(24 downto 0); + type std_logic_array_25 is array(natural range <>) of std_logic_vector_25; + subtype std_logic_vector_26 is std_logic_vector(25 downto 0); + type std_logic_array_26 is array(natural range <>) of std_logic_vector_26; + subtype std_logic_vector_27 is std_logic_vector(26 downto 0); + type std_logic_array_27 is array(natural range <>) of std_logic_vector_27; + subtype std_logic_vector_28 is std_logic_vector(27 downto 0); + type std_logic_array_28 is array(natural range <>) of std_logic_vector_28; + subtype std_logic_vector_29 is std_logic_vector(28 downto 0); + type std_logic_array_29 is array(natural range <>) of std_logic_vector_29; + subtype std_logic_vector_30 is std_logic_vector(29 downto 0); + type std_logic_array_30 is array(natural range <>) of std_logic_vector_30; + subtype std_logic_vector_31 is std_logic_vector(30 downto 0); + type std_logic_array_31 is array(natural range <>) of std_logic_vector_31; + subtype std_logic_vector_32 is std_logic_vector(31 downto 0); + type std_logic_array_32 is array(natural range <>) of std_logic_vector_32; + subtype std_logic_vector_34 is std_logic_vector(33 downto 0); + type std_logic_array_34 is array(natural range <>) of std_logic_vector_34; + subtype std_logic_vector_36 is std_logic_vector(35 downto 0); + type std_logic_array_36 is array(natural range <>) of std_logic_vector_36; + subtype std_logic_vector_64 is std_logic_vector(63 downto 0); + type std_logic_array_64 is array(natural range <>) of std_logic_vector_64; + subtype std_logic_vector_72 is std_logic_vector(71 downto 0); + type std_logic_array_72 is array(natural range <>) of std_logic_vector_72; + + -- functions + function zeros (n:natural) return std_logic_vector; + + +end package ines_vhdl_lib_base_pkg; + + + +package body ines_vhdl_lib_base_pkg is + + function zeros (n:natural) return std_logic_vector is + variable result: std_logic_vector(n-1 downto 0); + begin + for i in 0 to n-1 loop + result(i) := '0'; + end loop; + return result; + end; + +end package body ines_vhdl_lib_base_pkg; + diff --git a/lib/misc/reduce_pkg.vhd b/lib/misc/reduce_pkg.vhd new file mode 100644 index 0000000..8a4d80b --- /dev/null +++ b/lib/misc/reduce_pkg.vhd @@ -0,0 +1,424 @@ +-- -------------------------------------------------------------------- +-- +-- Copyright 2002 by IEEE. All rights reserved. +-- +-- This source file is an essential part of IEEE [Draft] Standard 1076.3 +-- reduce_pkg +-- This source file may not be copied, sold, or included +-- with software that is sold without written permission from the IEEE +-- Standards Department. This source file may be used to implement this +-- [draft] standard and may be distributed in compiled form in any manner so +-- long as the compiled form does not allow direct decompilation of the +-- original source file. This source file may be copied for individaul use +-- between licensed users. +-- +-- The IEEE disclaims any responsibility or liability for damages resulting +-- from misinterpretation or misue of said information by the user. +-- +-- [This source file represents a portion of the IEEE Draft Standard and is +-- unapproved and subject to change.] +-- +-- < statement about permission to modify > +-- +-- Title : REDUCE_PKG < IEEE std # 1076.3 > +-- +-- Library : This package shall be compiled into a library +-- symbolically named IEEE. +-- +-- Developers: IEEE DASC VHDL/Synthesis, PAR 1076.3 +-- +-- Purpose : Reduction operations. This allows a vector to +-- be collapsed into a signle bit. Similar to the built +-- in functions in Verilog. +-- +-- Limitation: +-- +-- -------------------------------------------------------------------- +-- modification history : +-- -------------------------------------------------------------------- +-- Version: 1.3 +-- Date : 8 July 2002 +-- Added "to_x01" on all inputs. +-- Made "and_reduce" return a "1" in the NULL case. +-- ------------------------------------------------------------------------- +-- Version: 1.2 +-- Date : 21 June 2002 +-- Fixed some basic logic errors. +-- ------------------------------------------------------------------------- +-- Version: 1.1 +-- Date : 13 May 2002 +-- Modified to deal with null arrays, added IEEE header. +-- ------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.numeric_std.all; + +-- Package definition +package reduce_pack is + FUNCTION and_reduce(arg : STD_LOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of and'ing all of the bits of the vector. + + FUNCTION nand_reduce(arg : STD_LOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nand'ing all of the bits of the vector. + + FUNCTION or_reduce(arg : STD_LOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of or'ing all of the bits of the vector. + + FUNCTION nor_reduce(arg : STD_LOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nor'ing all of the bits of the vector. + + FUNCTION xor_reduce(arg : STD_LOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xor'ing all of the bits of the vector. + + FUNCTION xnor_reduce(arg : STD_LOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xnor'ing all of the bits of the vector. + + FUNCTION and_reduce(arg : STD_ULOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of and'ing all of the bits of the vector. + + FUNCTION nand_reduce(arg : STD_ULOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nand'ing all of the bits of the vector. + + FUNCTION or_reduce(arg : STD_ULOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of or'ing all of the bits of the vector. + + FUNCTION nor_reduce(arg : STD_ULOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nor'ing all of the bits of the vector. + + FUNCTION xor_reduce(arg : STD_ULOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xor'ing all of the bits of the vector. + + FUNCTION xnor_reduce(arg : STD_ULOGIC_VECTOR) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xnor'ing all of the bits of the vector. + + FUNCTION and_reduce(arg : SIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of and'ing all of the bits of the vector. + + FUNCTION nand_reduce(arg : SIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nand'ing all of the bits of the vector. + + FUNCTION or_reduce(arg : SIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of or'ing all of the bits of the vector. + + FUNCTION nor_reduce(arg : SIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nor'ing all of the bits of the vector. + + FUNCTION xor_reduce(arg : SIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xor'ing all of the bits of the vector. + + FUNCTION xnor_reduce(arg : SIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xnor'ing all of the bits of the vector. + + FUNCTION and_reduce(arg : UNSIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of and'ing all of the bits of the vector. + + FUNCTION nand_reduce(arg : UNSIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nand'ing all of the bits of the vector. + + FUNCTION or_reduce(arg : UNSIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of or'ing all of the bits of the vector. + + FUNCTION nor_reduce(arg : UNSIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nor'ing all of the bits of the vector. + + FUNCTION xor_reduce(arg : UNSIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xor'ing all of the bits of the vector. + + FUNCTION xnor_reduce(arg : UNSIGNED) RETURN STD_LOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xnor'ing all of the bits of the vector. + + -- bit_vector versions + FUNCTION and_reduce(arg : BIT_VECTOR) RETURN BIT; + -- Result subtype: BIT. + -- Result: Result of and'ing all of the bits of the vector. + + FUNCTION nand_reduce(arg : BIT_VECTOR) RETURN BIT; + -- Result subtype: BIT. + -- Result: Result of nand'ing all of the bits of the vector. + + FUNCTION or_reduce(arg : BIT_VECTOR) RETURN BIT; + -- Result subtype: BIT. + -- Result: Result of or'ing all of the bits of the vector. + + FUNCTION nor_reduce(arg : BIT_VECTOR) RETURN BIT; + -- Result subtype: BIT. + -- Result: Result of nor'ing all of the bits of the vector. + + FUNCTION xor_reduce(arg : BIT_VECTOR) RETURN BIT; + -- Result subtype: BIT. + -- Result: Result of xor'ing all of the bits of the vector. + + FUNCTION xnor_reduce(arg : BIT_VECTOR) RETURN BIT; + -- Result subtype: BIT. + -- Result: Result of xnor'ing all of the bits of the vector. + +end reduce_Pack; + +-- Package body. +package body reduce_Pack is + +-- done in a recursively called function. + function and_reduce (arg : std_logic_vector ) + return std_logic is + variable Upper, Lower : std_logic; + variable Half : integer; + variable BUS_int : std_logic_vector ( arg'length - 1 downto 0 ); + variable Result : std_logic; + begin + if (arg'LENGTH < 1) then -- In the case of a NULL range + Result := '1'; -- Change for version 1.3 + else + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := BUS_int ( BUS_int'right ) and BUS_int ( BUS_int'left ); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := and_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := and_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := Upper and Lower; + end if; + end if; + return Result; + end; + + function nand_reduce (arg : std_logic_vector ) + return std_logic is + begin + return not and_reduce (arg); + end; + + function or_reduce (arg : std_logic_vector ) + return std_logic is + variable Upper, Lower : std_logic; + variable Half : integer; + variable BUS_int : std_logic_vector ( arg'length - 1 downto 0 ); + variable Result : std_logic; + begin + if (arg'LENGTH < 1) then -- In the case of a NULL range + Result := '0'; + else + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := BUS_int ( BUS_int'right ) or BUS_int ( BUS_int'left ); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := or_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := or_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := Upper or Lower; + end if; + end if; + return Result; + end; + + function nor_reduce (arg : std_logic_vector ) + return std_logic is + begin + return not or_reduce ( arg ); + end; + + function xor_reduce (arg : std_logic_vector ) + return std_logic is + variable Upper, Lower : std_logic; + variable Half : integer; + variable BUS_int : std_logic_vector ( arg'length - 1 downto 0 ); + variable Result : std_logic; + begin + if (arg'LENGTH < 1) then -- In the case of a NULL range + Result := '0'; + else + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := BUS_int ( BUS_int'right ) xor BUS_int ( BUS_int'left ); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := xor_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := xor_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := Upper xor Lower; + end if; + end if; + return Result; + end; + + function xnor_reduce (arg : std_logic_vector ) + return std_logic is + begin + return not xor_reduce ( arg ); + end; + + function and_reduce (arg : std_ulogic_vector ) + return std_logic is + begin + return and_reduce (std_logic_vector ( arg )); + end; + + function and_reduce (arg : SIGNED ) + return std_logic is + begin + return and_reduce (std_logic_vector ( arg )); + end; + + function and_reduce (arg : UNSIGNED ) + return std_logic is + begin + return and_reduce (std_logic_vector ( arg )); + end; + + function nand_reduce (arg : std_ulogic_vector ) + return std_logic is + begin + return nand_reduce (std_logic_vector ( arg )); + end; + + function nand_reduce (arg : SIGNED ) + return std_logic is + begin + return nand_reduce (std_logic_vector ( arg )); + end; + + function nand_reduce (arg : UNSIGNED ) + return std_logic is + begin + return nand_reduce (std_logic_vector ( arg )); + end; + + function or_reduce (arg : std_ulogic_vector ) + return std_logic is + begin + return or_reduce (std_logic_vector ( arg )); + end; + + function or_reduce (arg : SIGNED ) + return std_logic is + begin + return or_reduce (std_logic_vector ( arg )); + end; + + function or_reduce (arg : UNSIGNED ) + return std_logic is + begin + return or_reduce (std_logic_vector ( arg )); + end; + + function nor_reduce (arg : std_ulogic_vector ) + return std_logic is + begin + return nor_reduce (std_logic_vector ( arg )); + end; + + function nor_reduce (arg : SIGNED ) + return std_logic is + begin + return nor_reduce (std_logic_vector ( arg )); + end; + + function nor_reduce (arg : UNSIGNED ) + return std_logic is + begin + return nor_reduce (std_logic_vector ( arg )); + end; + + function xor_reduce (arg : std_ulogic_vector ) + return std_logic is + begin + return xor_reduce (std_logic_vector ( arg )); + end; + + function xor_reduce (arg : SIGNED ) + return std_logic is + begin + return xor_reduce (std_logic_vector ( arg )); + end; + + function xor_reduce (arg : UNSIGNED ) + return std_logic is + begin + return xor_reduce (std_logic_vector ( arg )); + end; + + function xnor_reduce (arg : std_ulogic_vector ) + return std_logic is + begin + return xnor_reduce (std_logic_vector ( arg )); + end; + + function xnor_reduce (arg : SIGNED ) + return std_logic is + begin + return xnor_reduce (std_logic_vector ( arg )); + end; + + function xnor_reduce (arg : UNSIGNED ) + return std_logic is + begin + return xnor_reduce (std_logic_vector ( arg )); + end; + + function and_reduce (arg : bit_vector ) + return bit is + begin + return to_bit (and_reduce (to_stdlogicvector ( arg ))); + end; + + function nand_reduce (arg : bit_vector ) + return bit is + begin + return to_bit (nand_reduce (to_stdlogicvector ( arg ))); + end; + + function or_reduce (arg : bit_vector ) + return bit is + begin + return to_bit (or_reduce (to_stdlogicvector ( arg ))); + end; + + function nor_reduce (arg : bit_vector ) + return bit is + begin + return to_bit (nor_reduce (to_stdlogicvector ( arg ))); + end; + + function xor_reduce (arg : bit_vector ) + return bit is + begin + return to_bit (xor_reduce (to_stdlogicvector ( arg ))); + end; + + function xnor_reduce (arg : bit_vector ) + return bit is + begin + return to_bit (xnor_reduce (to_stdlogicvector ( arg ))); + end; + +end reduce_pack; + + -- cgit v1.2.3-54-g00ecf