1------------------------------------------------------------------------------- 2-- Title : Simple Pipelined Wishbone MUX/DEMUX for WRPC 3-- Project : WhiteRabbit 4------------------------------------------------------------------------------- 5-- File : xwrf_mux.vhd 6-- Author : Grzegorz Daniluk 7-- Company : CERN BE-CO-HT 8-- Created : 2011-08-11 9-- Last update: 2017-02-03 10-- Platform : FPGA-generics 11-- Standard : VHDL 12------------------------------------------------------------------------------- 13-- Description: 14-- This is the simple multiplexer/demultiplexer for WR Fabric interface 15-- (Pipelined Wishbone interface). It forwards ethernet frames between 16-- WR endpoint, Mini-NIC and external Fabric interface in both directions. 17-- In the direction 'from' WR endpoint it also decides whether the packet 18-- has to be forwarded to Mini-NIC (if it is the PTP message) or to the 19-- external interface (others). 20------------------------------------------------------------------------------- 21-- Copyright (c) 2012-2017 CERN 22-- 23-- This source file is free software; you can redistribute it 24-- and/or modify it under the terms of the GNU Lesser General 25-- Public License as published by the Free Software Foundation; 26-- either version 2.1 of the License, or (at your option) any 27-- later version. 28-- 29-- This source is distributed in the hope that it will be 30-- useful, but WITHOUT ANY WARRANTY; without even the implied 31-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 32-- PURPOSE. See the GNU Lesser General Public License for more 33-- details. 34-- 35-- You should have received a copy of the GNU Lesser General 36-- Public License along with this source; if not, download it 37-- from http://www.gnu.org/licenses/lgpl-2.1.html 38-- 39------------------------------------------------------------------------------- 40-- Revisions : 41-- Date Version Author Description 42-- 2011-08-11 1.0 greg.d Created 43-- 2012-10-16 2.0 greg.d generic number of ports 44------------------------------------------------------------------------------- 45library ieee; 46use ieee.std_logic_1164.all; 47use ieee.std_logic_misc.all; 48 49use ieee.numeric_std.all; 50 51library work; 52use work.wr_fabric_pkg.all; 53use work.genram_pkg.all; 54 55entity xwrf_mux is 56 generic( 57 g_muxed_ports : integer := 2); 58 port( 59 clk_sys_i : in std_logic; 60 rst_n_i : in std_logic; 61 --ENDPOINT 62 ep_src_o : out t_wrf_source_out; 63 ep_src_i : in t_wrf_source_in; 64 ep_snk_o : out t_wrf_sink_out; 65 ep_snk_i : in t_wrf_sink_in; 66 --Muxed ports 67 mux_src_o : out t_wrf_source_out_array(g_muxed_ports-1 downto 0); 68 mux_src_i : in t_wrf_source_in_array(g_muxed_ports-1 downto 0); 69 mux_snk_o : out t_wrf_sink_out_array(g_muxed_ports-1 downto 0); 70 mux_snk_i : in t_wrf_sink_in_array(g_muxed_ports-1 downto 0); 71 -- 72 mux_class_i : in t_wrf_mux_class(g_muxed_ports-1 downto 0) 73 ); 74end xwrf_mux; 75 76architecture behaviour of xwrf_mux is 77 78 function f_hot_to_bin(x : std_logic_vector(g_muxed_ports-1 downto 0)) 79 return integer is 80 variable rv : integer; 81 begin 82 rv := 0; 83 -- if there are few ones set in _x_ then the least significant will be 84 -- translated to bin 85 for i in g_muxed_ports-1 downto 0 loop 86 if x(i) = '1' then 87 rv := i; 88 end if; 89 end loop; 90 return rv; 91 end function; 92 93 function f_match_class(port_mask, pkt_mask : std_logic_vector(7 downto 0)) return std_logic is 94 variable ret : std_logic; 95 begin 96 if((port_mask and pkt_mask) /= x"00") then 97 return '1'; 98 else 99 return '0'; 100 end if; 101 end function; 102 103 --==================================-- 104 -- Masters to Endpoint mux signals -- 105 --==================================-- 106 type t_mux is (MUX_SEL, MUX_TRANSFER); 107 signal mux : t_mux; 108 signal mux_cycs : std_logic_vector(g_muxed_ports-1 downto 0); 109 signal mux_rrobin : std_logic_vector(g_muxed_ports-1 downto 0); 110 signal mux_select : std_logic_vector(g_muxed_ports-1 downto 0); 111 112 --==================================-- 113 -- Endpoint to Slaves demux signals -- 114 --==================================-- 115 type t_demux is (DMUX_WAIT, DMUX_STATUS, DMUX_PAYLOAD); 116 signal demux : t_demux; 117 signal dmux_sel : std_logic_vector(g_muxed_ports-1 downto 0); 118 signal dmux_status_reg : std_logic_vector(15 downto 0); 119 signal dmux_select : std_logic_vector(g_muxed_ports-1 downto 0); 120 signal dmux_others : std_logic_vector(g_muxed_ports-1 downto 0); 121 signal dmux_sel_zero : std_logic; 122 signal dmux_snd_stat : std_logic_vector(g_muxed_ports-1 downto 0); 123 signal ep_stall_mask : std_logic; 124 signal ep_snk_out_stall : std_logic; 125 126begin 127 128 --=============================================-- 129 -- -- 130 -- Many Fabric Masters talking to ENDPOINT -- 131 -- -- 132 --=============================================-- 133 GEN_MUX_CYCS_REG : for I in 0 to g_muxed_ports-1 generate 134 mux_cycs(I) <= mux_snk_i(I).cyc; 135 end generate; 136 137 p_mux : process(clk_sys_i) 138 begin 139 if rising_edge(clk_sys_i) then 140 if (rst_n_i = '0') then 141 mux_rrobin(0) <= '1'; 142 mux_rrobin(g_muxed_ports-1 downto 1) <= (others => '0'); 143 mux <= MUX_SEL; 144 else 145 case mux is 146 when MUX_SEL => 147 if (unsigned(mux_cycs and mux_rrobin) /= 0)then 148 mux_select <= mux_cycs and mux_rrobin; 149 mux <= MUX_TRANSFER; 150 else 151 mux_select <= (others => '0'); 152 mux_rrobin <= mux_rrobin(0) & mux_rrobin(g_muxed_ports-1 downto 1); 153 end if; 154 155 when MUX_TRANSFER => 156 if(unsigned(mux_cycs and mux_select) = 0) then --cycle end 157 mux_rrobin <= mux_rrobin(0) & mux_rrobin(g_muxed_ports-1 downto 1); 158 mux <= MUX_SEL; 159 end if; 160 end case; 161 162 end if; 163 end if; 164 end process; 165 166 167 GEN_MUX_CONNS : for J in 0 to g_muxed_ports-1 generate 168 mux_snk_o(J).ack <= ep_src_i.ack when(mux /= MUX_SEL and mux_select(J) = '1') else 169 '0'; 170 mux_snk_o(J).stall <= ep_src_i.stall when(mux /= MUX_SEL and mux_select(J) = '1') else 171 '1'; 172 mux_snk_o(J).err <= ep_src_i.err when(mux /= MUX_SEL and mux_select(J) = '1') else 173 '0'; 174 mux_snk_o(J).rty <= '0'; 175 end generate; 176 177 ep_src_o.cyc <= mux_snk_i(f_hot_to_bin(mux_select)).cyc when(mux /= MUX_SEL) else 178 '0'; 179 ep_src_o.stb <= mux_snk_i(f_hot_to_bin(mux_select)).stb when(mux /= MUX_SEL) else 180 '0'; 181 ep_src_o.adr <= mux_snk_i(f_hot_to_bin(mux_select)).adr; 182 ep_src_o.dat <= mux_snk_i(f_hot_to_bin(mux_select)).dat; 183 ep_src_o.sel <= mux_snk_i(f_hot_to_bin(mux_select)).sel; 184 ep_src_o.we <= '1'; 185 186 187 --=============================================-- 188 -- -- 189 -- ENDPOINT talking to many Fabric Slaves -- 190 -- -- 191 --=============================================-- 192 193 CLASS_MATCH : for I in 0 to g_muxed_ports-1 generate 194 dmux_sel(I) <= f_match_class(mux_class_i(I), f_unmarshall_wrf_status(dmux_status_reg).match_class); 195 end generate; 196 197 DMUX_FSM : process(clk_sys_i) 198 variable sel : integer range 0 to g_muxed_ports-1; 199 begin 200 if rising_edge(clk_sys_i) then 201 if(rst_n_i = '0') then 202 dmux_select <= (others => '0'); 203 dmux_snd_stat <= (others => '0'); 204 dmux_status_reg <= (others => '0'); 205 ep_stall_mask <= '0'; 206 demux <= DMUX_WAIT; 207 else 208 case demux is 209 --------------------------------------------------------------- 210 --State DMUX_WAIT: Wait for the WRF cycle to start and then 211 -- wait for the STATUS word 212 --------------------------------------------------------------- 213 when DMUX_WAIT => 214 dmux_select <= (others => '0'); 215 dmux_snd_stat <= (others => '0'); 216 dmux_status_reg <= (others => '0'); 217 ep_stall_mask <= '0'; 218 if(ep_snk_i.cyc = '1' and ep_snk_i.stb = '1' and ep_snk_i.adr = c_WRF_STATUS) then 219 ep_stall_mask <= '1'; 220 dmux_status_reg <= ep_snk_i.dat; 221 demux <= DMUX_STATUS; 222 end if; 223 224 --------------------------------------------------------------- 225 --State DMUX_STATUS: Send Status word to appropriate interface 226 --------------------------------------------------------------- 227 when DMUX_STATUS => 228 ep_stall_mask <= '1'; 229 230 if(to_integer(unsigned(dmux_sel)) = 0) then --class not matched to anything, pass pkt to last port 231 dmux_select(g_muxed_ports-1) <= '1'; 232 dmux_snd_stat(g_muxed_ports-1) <= '1'; 233 sel := g_muxed_ports-1; 234 else 235 dmux_select <= dmux_sel; 236 dmux_snd_stat <= dmux_sel; 237 sel := f_hot_to_bin(dmux_sel); 238 end if; 239 if(mux_src_i(sel).stall = '0') then 240 demux <= DMUX_PAYLOAD; 241 end if; 242 243 --------------------------------------------------------------- 244 --State DMUX_PAYLOAD: Just wait here till the end of the 245 -- current transfer 246 --------------------------------------------------------------- 247 when DMUX_PAYLOAD => 248 dmux_snd_stat <= (others => '0'); 249 ep_stall_mask <= '0'; 250 251 if(ep_snk_i.cyc = '0') then 252 demux <= DMUX_WAIT; 253 end if; 254 255 when others => 256 demux <= DMUX_WAIT; 257 end case; 258 end if; 259 end if; 260 end process; 261 262 dmux_sel_zero <= '1' when(to_integer(unsigned(dmux_select)) = 0) else 263 '0'; 264 265 -- dmux_others signal says for given interface I if any other interface was 266 -- also matched to packet class 267 dmux_others(0) <= '0'; 268 GEN_DMUX_OTHERS : for I in 1 to g_muxed_ports-1 generate 269 dmux_others(I) <= or_reduce(dmux_select(I-1 downto 0)); 270 end generate; 271 272 273 GEN_DMUX_CONN : for I in 0 to g_muxed_ports-1 generate 274 mux_src_o(I).cyc <= ep_snk_i.cyc when(dmux_select(I) = '1' and dmux_others(I) = '0') else 275 '0'; 276 mux_src_o(I).stb <= '1' when(dmux_snd_stat(I) = '1' and dmux_others(I) = '0') else 277 ep_snk_i.stb when(dmux_select(I) = '1' and dmux_others(I) = '0') else 278 '0'; 279 mux_src_o(I).adr <= c_WRF_STATUS when(dmux_snd_stat(I) = '1' and dmux_others(I) = '0') else 280 ep_snk_i.adr when(dmux_select(I) = '1' and dmux_others(I) = '0') else 281 (others => '0'); 282 mux_src_o(I).dat <= dmux_status_reg when(dmux_snd_stat(I) = '1' and dmux_others(I) = '0') else 283 ep_snk_i.dat when(dmux_select(I) = '1' and dmux_others(I) = '0') else 284 (others => '0'); 285 mux_src_o(I).sel <= (others => '1') when(dmux_snd_stat(I) = '1' and dmux_others(I) = '0') else 286 ep_snk_i.sel when(dmux_select(I) = '1' and dmux_others(I) = '0') else 287 (others => '1'); 288 mux_src_o(I).we <= '1'; 289 end generate; 290 291 292 ep_snk_o.ack <= ep_snk_i.cyc and ep_snk_i.stb and not ep_snk_out_stall when(dmux_sel_zero = '1') else 293 mux_src_i(f_hot_to_bin(dmux_select)).ack; 294 295 ep_snk_o.err <= '0' when(dmux_sel_zero = '1') else 296 mux_src_i(f_hot_to_bin(dmux_select)).err; 297 298 ep_snk_out_stall <= '1' when(ep_stall_mask = '1') else 299 '0' when(dmux_sel_zero = '1') else 300 mux_src_i(f_hot_to_bin(dmux_select)).stall; 301 302 ep_snk_o.stall <= ep_snk_out_stall; 303 304 ep_snk_o.rty <= '0'; 305 306end behaviour; 307 308