SURF  1.0
AxiStreamMux.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiStreamMux.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2014-04-25
5 -- Last update: 2016-11-30
6 -------------------------------------------------------------------------------
7 -- Description:
8 -- Block to connect multiple incoming AXI streams into a single encoded
9 -- outbound stream. The destination field is updated accordingly.
10 -------------------------------------------------------------------------------
11 -- This file is part of 'SLAC Firmware Standard Library'.
12 -- It is subject to the license terms in the LICENSE.txt file found in the
13 -- top-level directory of this distribution and at:
14 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
15 -- No part of 'SLAC Firmware Standard Library', including this file,
16 -- may be copied, modified, propagated, or distributed except according to
17 -- the terms contained in the LICENSE.txt file.
18 -------------------------------------------------------------------------------
19 
20 library ieee;
21 use ieee.std_logic_1164.all;
22 use ieee.std_logic_arith.all;
23 use ieee.std_logic_unsigned.all;
24 
25 use work.StdRtlPkg.all;
26 use work.ArbiterPkg.all;
27 use work.AxiStreamPkg.all;
28 
29 --! @see entity
30  --! @ingroup axi
31 entity AxiStreamMux is
32  generic (
33  TPD_G : time := 1 ns;
34  NUM_SLAVES_G : integer range 1 to 32 := 4;
35  MODE_G : string := "INDEXED"; -- Or "ROUTED"
36  TDEST_ROUTES_G : Slv8Array := (0 => "--------"); -- Only used in ROUTED mode
37  PIPE_STAGES_G : integer range 0 to 16 := 0;
38  TDEST_LOW_G : integer range 0 to 7 := 0; -- LSB of updated tdest for INDEX
39  ILEAVE_EN_G : boolean := false; -- Set to true if interleaving dests, arbitrate on gaps
40  ILEAVE_REARB_G : natural := 0); -- Max number of transactions between arbitrations, 0 = unlimited
41  port (
42  -- Clock and reset
43  axisClk : in sl;
44  axisRst : in sl;
45  -- Slaves
48  disableSel : in slv(NUM_SLAVES_G-1 downto 0) := (others => '0');
49  -- Master
52 end AxiStreamMux;
53 
54 architecture structure of AxiStreamMux is
55 
56  constant DEST_SIZE_C : integer := bitSize(NUM_SLAVES_G-1);
57  constant ARB_BITS_C : integer := 2**DEST_SIZE_C;
58  constant ACNT_SIZE_G : integer := bitSize(ILEAVE_REARB_G);
59 
60  type StateType is (
61  IDLE_S,
62  MOVE_S);
63 
64  type RegType is record
66  acks : slv(ARB_BITS_C-1 downto 0);
67  ackNum : slv(DEST_SIZE_C-1 downto 0);
68  valid : sl;
69  arbCnt : slv(ACNT_SIZE_G-1 downto 0);
72  end record RegType;
73 
74  constant REG_INIT_C : RegType := (
75  state => IDLE_S,
76  acks => (others => '0'),
77  ackNum => toSlv(NUM_SLAVES_G-1, DEST_SIZE_C),
78  valid => '0',
79  arbCnt => (others=>'0'),
80  slaves => (others => AXI_STREAM_SLAVE_INIT_C),
82 
83  signal r : RegType := REG_INIT_C;
84  signal rin : RegType;
85 
89 
90 begin
91 
92  assert (MODE_G /= "INDEXED" or (7 - TDEST_LOW_G + 1 >= log2(NUM_SLAVES_G)))
93  report "In INDEXED mode, TDest range 7 downto " & integer'image(TDEST_LOW_G) &
94  " is too small for NUM_SLAVES_G=" & integer'image(NUM_SLAVES_G)
95  severity error;
96 
97  assert (MODE_G /= "ROUTED" or (TDEST_ROUTES_G'length = NUM_SLAVES_G))
98  report "In ROUTED mode, length of TDEST_ROUTES_G: " & integer'image(TDEST_ROUTES_G'length) &
99  " must equal NUM_SLAVES_G: " & integer'image(NUM_SLAVES_G)
100  severity error;
101 
102  -- Override tdests according to the routing table
103  TDEST_REMAP : process (sAxisMasters) is
104  variable tmp : AxiStreamMasterArray(NUM_SLAVES_G-1 downto 0);
105  variable i : natural;
106  variable j : natural;
107  begin
108  tmp := sAxisMasters;
109  if MODE_G = "ROUTED" then
110  for i in NUM_SLAVES_G-1 downto 0 loop
111  for j in 7 downto 0 loop
112  if (TDEST_ROUTES_G(i)(j) = '1') then
113  tmp(i).tDest(j) := '1';
114  elsif(TDEST_ROUTES_G(i)(j) = '0') then
115  tmp(i).tDest(j) := '0';
116  else
117  tmp(i).tDest(j) := sAxisMasters(i).tDest(j);
118  end if;
119  end loop;
120  end loop;
121  end if;
122  sAxisMastersTmp <= tmp;
123  end process;
124 
126  variable v : RegType;
127  variable requests : slv(ARB_BITS_C-1 downto 0);
128  variable selData : AxiStreamMasterType;
129  variable i : natural;
130  begin
131  -- Latch the current value
132  v := r;
133 
134  -- Reset the flags
135  for i in 0 to (NUM_SLAVES_G-1) loop
136  v.slaves(i).tReady := '0';
137  end loop;
138  if pipeAxisSlave.tReady = '1' then
139  v.master.tValid := '0';
140  end if;
141 
142  -- Select source
143  if NUM_SLAVES_G = 1 then
144  selData := sAxisMastersTmp(0);
145  else
146  selData := sAxisMastersTmp(conv_integer(r.ackNum));
147  end if;
148 
149  if MODE_G = "INDEXED" then
150  selData.tDest(7 downto TDEST_LOW_G) := (others => '0');
151  selData.tDest(DEST_SIZE_C+TDEST_LOW_G-1 downto TDEST_LOW_G) := r.ackNum;
152  end if;
153 
154  -- Format requests
155  requests := (others => '0');
156  for i in 0 to (NUM_SLAVES_G-1) loop
157  requests(i) := sAxisMastersTmp(i).tValid and not disableSel(i);
158  end loop;
159 
160  -- State machine
161  case r.state is
162  ----------------------------------------------------------------------
163  when IDLE_S =>
164  -- Arbitrate between requesters
165  if r.valid = '0' then
166  arbitrate(requests, r.ackNum, v.ackNum, v.valid, v.acks);
167  else
168  -- Reset the Arbitration flag
169  v.valid := '0';
170  -- Check if need to move data
171  if (v.master.tValid = '0') and (selData.tValid = '1') then
172  -- Accept the data
173  v.slaves(conv_integer(r.ackNum)).tReady := '1';
174  -- Move the AXIS data
175  v.master := selData;
176  -- Check for no-tLast
177  if selData.tLast = '0' then
178  -- Next state
179  v.state := MOVE_S;
180  end if;
181  else
182  -- Next state
183  v.state := MOVE_S;
184  end if;
185  end if;
186  v.arbCnt := (others=>'0');
187  ----------------------------------------------------------------------
188  when MOVE_S =>
189  -- Check if need to move data
190  if (v.master.tValid = '0') and (selData.tValid = '1') then
191  -- Accept the data
192  v.slaves(conv_integer(r.ackNum)).tReady := '1';
193  -- Move the AXIS data
194  v.master := selData;
195  v.arbCnt := r.arbCnt + 1;
196  -- Check for tLast
197  if selData.tLast = '1' then
198  -- Next state
199  v.state := IDLE_S;
200 
201  -- Rearbitrate after n transactions if enabled
202  elsif (ILEAVE_EN_G = true) and (ILEAVE_REARB_G /= 0) and (r.arbCnt = (ILEAVE_REARB_G-1)) then
203  v.state := IDLE_S;
204  end if;
205 
206  -- RE-arbitrate on gaps if interleaving frames
207  elsif (v.master.tValid = '0') and (selData.tValid = '0') and (ILEAVE_EN_G = true) then
208  v.state := IDLE_S;
209  end if;
210  ----------------------------------------------------------------------
211  end case;
212 
213  -- Reset
214  if (axisRst = '1') then
215  v := REG_INIT_C;
216  end if;
217 
218  -- Register the variable for next clock cycle
219  rin <= v;
220 
221  -- Outputs
222  sAxisSlaves <= v.slaves;
224 
225  end process comb;
226 
227  AxiStreamPipeline_1 : entity work.AxiStreamPipeline
228  generic map (
229  TPD_G => TPD_G,
231  port map (
232  axisClk => axisClk,
233  axisRst => axisRst,
238 
239  seq : process (axisClk) is
240  begin
241  if (rising_edge(axisClk)) then
242  r <= rin after TPD_G;
243  end if;
244  end process seq;
245 
246 end structure;
PIPE_STAGES_Gnatural range 0 to 16:= 0
TPD_Gtime := 1 ns
array(natural range <> ) of AxiStreamSlaveType AxiStreamSlaveArray
_library_ ieeeieee
slv( ARB_BITS_C- 1 downto 0) acks
AxiStreamSlaveArray( NUM_SLAVES_G- 1 downto 0) slaves
slv( DEST_SIZE_C- 1 downto 0) ackNum
integer := bitSize( NUM_SLAVES_G- 1) DEST_SIZE_C
std_logic sl
Definition: StdRtlPkg.vhd:28
AxiStreamMasterType :=(tValid => '0',tData =>( others => '0'),tStrb =>( others => '1'),tKeep =>( others => '1'),tLast => '0',tDest =>( others => '0'),tId =>( others => '0'),tUser =>( others => '0')) AXI_STREAM_MASTER_INIT_C
TDEST_ROUTES_GSlv8Array :=( 0=> "--------")
out sAxisSlaveAxiStreamSlaveType
AxiStreamMasterType master
TDEST_LOW_Ginteger range 0 to 7:= 0
in mAxisSlaveAxiStreamSlaveType
AxiStreamMasterType pipeAxisMaster
integer := bitSize(ILEAVE_REARB_G ) ACNT_SIZE_G
RegType :=(state => IDLE_S,acks =>( others => '0'),ackNum => toSlv( NUM_SLAVES_G- 1, DEST_SIZE_C),valid => '0',arbCnt =>( others => '0'),slaves =>( others => AXI_STREAM_SLAVE_INIT_C),master => AXI_STREAM_MASTER_INIT_C) REG_INIT_C
MODE_Gstring := "INDEXED"
ILEAVE_REARB_Gnatural := 0
ILEAVE_EN_Gboolean := false
out mAxisMasterAxiStreamMasterType
NUM_SLAVES_Ginteger range 1 to 32:= 4
in sAxisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
in sAxisMastersAxiStreamMasterArray( NUM_SLAVES_G- 1 downto 0)
integer := 2** DEST_SIZE_C ARB_BITS_C
AxiStreamMasterArray( NUM_SLAVES_G- 1 downto 0) sAxisMastersTmp
RegType := REG_INIT_C r
array(natural range <> ) of AxiStreamMasterType AxiStreamMasterArray
out sAxisSlavesAxiStreamSlaveArray( NUM_SLAVES_G- 1 downto 0)
AxiStreamSlaveType pipeAxisSlave
out mAxisMasterAxiStreamMasterType
in disableSelslv( NUM_SLAVES_G- 1 downto 0) :=( others => '0')
slv( 7 downto 0) tDest
slv( ACNT_SIZE_G- 1 downto 0) arbCnt
array(natural range <> ) of slv( 7 downto 0) Slv8Array
Definition: StdRtlPkg.vhd:403
in mAxisSlaveAxiStreamSlaveType
(IDLE_S,MOVE_S) StateType
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
PIPE_STAGES_Ginteger range 0 to 16:= 0