SURF  1.0
Pgp2bTxSched.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : Pgp2bTxSched.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2009-05-27
5 -- Last update: 2017-03-28
6 -------------------------------------------------------------------------------
7 -- Description:
8 -- Transmit scheduler interface module for the Pretty Good Protocol core.
9 -------------------------------------------------------------------------------
10 -- This file is part of 'SLAC Firmware Standard Library'.
11 -- It is subject to the license terms in the LICENSE.txt file found in the
12 -- top-level directory of this distribution and at:
13 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
14 -- No part of 'SLAC Firmware Standard Library', including this file,
15 -- may be copied, modified, propagated, or distributed except according to
16 -- the terms contained in the LICENSE.txt file.
17 -------------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.std_logic_arith.all;
22 use ieee.std_logic_unsigned.all;
23 use work.StdRtlPkg.all;
24 use work.Pgp2bPkg.all;
25 
26 --! @see entity
27  --! @ingroup protocols_pgp_pgp2b_core
28 entity Pgp2bTxSched is
29  generic (
30  TPD_G : time := 1 ns;
31  VC_INTERLEAVE_G : integer := 1; -- Interleave Frames
32  NUM_VC_EN_G : integer range 1 to 4 := 4
33  );
34  port (
35 
36  -- System clock, reset & control
37  pgpTxClkEn : in sl := '1'; -- Master clock Enable
38  pgpTxClk : in sl; -- Master clock
39  pgpTxClkRst : in sl; -- Synchronous reset input
40 
41  -- Link flush
42  pgpTxFlush : in sl; -- Flush the link
43 
44  -- Link is ready
45  pgpTxLinkReady : in sl; -- Local side has link
46 
47  -- Cell Transmit Interface
48  schTxSOF : in sl; -- Cell contained SOF
49  schTxEOF : in sl; -- Cell contained EOF
50  schTxIdle : out sl; -- Force IDLE transmit
51  schTxReq : out sl; -- Cell transmit request
52  schTxAck : in sl; -- Cell transmit acknowledge
53  schTxTimeout : out sl; -- Cell transmit timeout
54  schTxDataVc : out slv(1 downto 0); -- Cell transmit virtual channel
55 
56  -- VC Data Valid Signals
57  vc0FrameTxValid : in sl; -- User frame data is valid
58  vc1FrameTxValid : in sl; -- User frame data is valid
59  vc2FrameTxValid : in sl; -- User frame data is valid
60  vc3FrameTxValid : in sl; -- User frame data is valid
61 
62  -- VC Flow Control Signals
63  vc0RemAlmostFull : in sl; -- Remote flow control
64  vc1RemAlmostFull : in sl; -- Remote flow control
65  vc2RemAlmostFull : in sl; -- Remote flow control
66  vc3RemAlmostFull : in sl -- Remote flow control
67  );
68 
69 end Pgp2bTxSched;
70 
71 
72 -- Define architecture
73 architecture Pgp2bTxSched of Pgp2bTxSched is
74 
75  -- Local Signals
76  signal currValid : sl;
77  signal currVc : slv(1 downto 0);
78  signal nextVc : slv(1 downto 0);
79  signal arbVc : slv(1 downto 0);
80  signal arbValid : sl;
81  signal vcInFrame : slv(3 downto 0);
82  signal intTxReq : sl;
83  signal intTxIdle : sl;
84  signal nxtTxReq : sl;
85  signal nxtTxIdle : sl;
86  signal nxtTxTimeout : sl;
87  signal intTxTimeout : sl;
88  signal vcTimerA : slv(23 downto 0);
89  signal vcTimerB : slv(23 downto 0);
90  signal vcTimerC : slv(23 downto 0);
91  signal vcTimerD : slv(23 downto 0);
92  signal vcTimeout : slv(3 downto 0);
93  signal gateTxValid : slv(3 downto 0);
94 
95  -- Schedular state
96  constant ST_RST_C : slv(2 downto 0) := "001";
97  constant ST_ARB_C : slv(2 downto 0) := "010";
98  constant ST_CELL_C : slv(2 downto 0) := "011";
99  constant ST_GAP_A_C : slv(2 downto 0) := "100";
100  constant ST_GAP_B_C : slv(2 downto 0) := "101";
101  constant ST_GAP_C_C : slv(2 downto 0) := "110";
102  signal curState : slv(2 downto 0);
103  signal nxtState : slv(2 downto 0);
104 
105 begin
106 
107  -- Outgoing signals
108  schTxReq <= intTxReq;
109  schTxIdle <= intTxIdle;
110  schTxDataVc <= currVc;
112 
113 
114  -- State transition logic
115  process (pgpTxClk)
116  begin
117  if rising_edge(pgpTxClk) then
118  if pgpTxClkRst = '1' then
119  curState <= ST_ARB_C after TPD_G;
120  currVc <= "00" after TPD_G;
121  intTxReq <= '0' after TPD_G;
122  intTxIdle <= '0' after TPD_G;
123  intTxTimeout <= '0' after TPD_G;
124  elsif pgpTxClkEn = '1' then
125  -- Force state to select state when link goes down
126  if pgpTxLinkReady = '0' then
127  curState <= ST_RST_C after TPD_G;
128  else
129  curState <= nxtState after TPD_G;
130  end if;
131 
132  -- Control signals
133  currVc <= nextVc after TPD_G;
134  intTxReq <= nxtTxReq after TPD_G;
135  intTxIdle <= nxtTxIdle after TPD_G;
137 
138  end if;
139  end if;
140  end process;
141 
142 
143  -- Scheduler state machine
145  begin
146  case curState is
147 
148  -- Held in reset due to non-link
149  when ST_RST_C =>
150  nxtTxIdle <= '0';
151  nxtTxReq <= '0';
152  nxtTxTimeout <= '0';
153  nextVc <= (others => '0');
154  nxtState <= ST_ARB_C;
155 
156  -- IDLE, wait for ack receiver to be ready
157  when ST_ARB_C =>
158 
159  -- VC0 Timeout
160  if vcTimeout(0) = '1' then
161  nxtTxIdle <= '0';
162  nxtTxReq <= '1';
163  nxtTxTimeout <= '1';
164  nextVc <= "00";
165 
166  -- VC1 Timeout
167  elsif vcTimeout(1) = '1' and NUM_VC_EN_G > 1 then
168  nxtTxIdle <= '0';
169  nxtTxReq <= '1';
170  nxtTxTimeout <= '1';
171  nextVc <= "01";
172 
173  -- VC2 Timeout
174  elsif vcTimeout(2) = '1' and NUM_VC_EN_G > 2 then
175  nxtTxIdle <= '0';
176  nxtTxReq <= '1';
177  nxtTxTimeout <= '1';
178  nextVc <= "10";
179 
180  -- VC3 Timeout
181  elsif vcTimeout(3) = '1' and NUM_VC_EN_G > 3 then
182  nxtTxIdle <= '0';
183  nxtTxReq <= '1';
184  nxtTxTimeout <= '1';
185  nextVc <= "11";
186 
187  -- Non-interleave mode and current is in frame
188  elsif VC_INTERLEAVE_G = 0 and vcInFrame(conv_integer(currVc)) = '1' then
189  nxtTxIdle <= not currValid;
190  nxtTxReq <= currValid;
191  nextVc <= currVc;
192  nxtTxTimeout <= '0';
193 
194  -- Else use new arb winner if valid
195  else
196  nxtTxIdle <= not arbValid;
197  nxtTxReq <= arbValid;
198  nextVc <= arbVc;
199  nxtTxTimeout <= '0';
200  end if;
201  nxtState <= ST_CELL_C;
202 
203  -- Transmit Cell Data
204  when ST_CELL_C =>
205  nxtTxIdle <= '0';
206  nxtTxTimeout <= '0';
207  nxtTxReq <= '0';
208  nextVc <= currVc;
209 
210  -- Cell is done
211  if schTxAck = '1' then
212  nxtState <= ST_GAP_A_C;
213  else
214  nxtState <= curState;
215  end if;
216 
217  -- Wait between cells
218  when ST_GAP_A_C =>
219  nxtTxIdle <= '0';
220  nxtTxReq <= '0';
221  nxtTxTimeout <= '0';
222  nextVc <= currVc;
223  nxtState <= ST_GAP_B_C;
224 
225  -- Wait between cells
226  when ST_GAP_B_C =>
227  nxtTxIdle <= '0';
228  nxtTxReq <= '0';
229  nxtTxTimeout <= '0';
230  nextVc <= currVc;
231  nxtState <= ST_GAP_C_C;
232 
233  -- Wait between cells
234  when ST_GAP_C_C =>
235  nxtTxIdle <= '0';
236  nxtTxReq <= '0';
237  nxtTxTimeout <= '0';
238  nextVc <= currVc;
239  nxtState <= ST_ARB_C;
240 
241  -- Just in case
242  when others =>
243  nxtTxIdle <= '0';
244  nxtTxReq <= '0';
245  nxtTxTimeout <= '0';
246  nextVc <= (others => '0');
247  nxtState <= ST_ARB_C;
248  end case;
249  end process;
250 
251  -- Gate valid signals based upon flow control
252  gateTxValid(0) <= vc0FrameTxvalid and (not vc0RemAlmostFull);
253  gateTxValid(1) <= vc1FrameTxvalid and (not vc1RemAlmostFull);
254  gateTxValid(2) <= vc2FrameTxvalid and (not vc2RemAlmostFull);
255  gateTxValid(3) <= vc3FrameTxvalid and (not vc3RemAlmostFull);
256 
257  -- Current owner has valid asserted
258  currValid <= gateTxValid(0) when currVc = "00" else
259  gateTxValid(1) when currVc = "01" and NUM_VC_EN_G > 1 else
260  gateTxValid(2) when currVc = "10" and NUM_VC_EN_G > 2 else
261  gateTxValid(3) when currVc = "11" and NUM_VC_EN_G > 3 else
262  '0';
263 
264 
265  -- Arbitrate for the next VC value based upon current VC value and status of valid inputs
266  process (currVc, gateTxValid)
267  begin
268  case currVc is
269  when "00" =>
270  if gateTxValid(1) = '1' and NUM_VC_EN_G > 1 then arbVc <= "01"; arbValid <= '1';
271  elsif gateTxValid(2) = '1' and NUM_VC_EN_G > 2 then arbVc <= "10"; arbValid <= '1';
272  elsif gateTxValid(3) = '1' and NUM_VC_EN_G > 3 then arbVc <= "11"; arbValid <= '1';
273  elsif gateTxValid(0) = '1' then arbVc <= "00"; arbValid <= '1';
274  else arbVc <= "00"; arbValid <= '0'; end if;
275  when "01" =>
276  if gateTxValid(2) = '1' and NUM_VC_EN_G > 2 then arbVc <= "10"; arbValid <= '1';
277  elsif gateTxValid(3) = '1' and NUM_VC_EN_G > 3 then arbVc <= "11"; arbValid <= '1';
278  elsif gateTxValid(0) = '1' then arbVc <= "00"; arbValid <= '1';
279  elsif gateTxValid(1) = '1' and NUM_VC_EN_G > 1 then arbVc <= "01"; arbValid <= '1';
280  else arbVc <= "01"; arbValid <= '0'; end if;
281  when "10" =>
282  if gateTxValid(3) = '1' and NUM_VC_EN_G > 3 then arbVc <= "11"; arbValid <= '1';
283  elsif gateTxValid(0) = '1' then arbVc <= "00"; arbValid <= '1';
284  elsif gateTxvalid(1) = '1' and NUM_VC_EN_G > 1 then arbVc <= "01"; arbValid <= '1';
285  elsif gateTxvalid(2) = '1' and NUM_VC_EN_G > 2 then arbVc <= "10"; arbValid <= '1';
286  else arbVc <= "10"; arbValid <= '0'; end if;
287  when "11" =>
288  if gateTxValid(0) = '1' then arbVc <= "00"; arbValid <= '1';
289  elsif gateTxValid(1) = '1' and NUM_VC_EN_G > 1 then arbVc <= "01"; arbValid <= '1';
290  elsif gateTxValid(2) = '1' and NUM_VC_EN_G > 2 then arbVc <= "10"; arbValid <= '1';
291  elsif gateTxValid(3) = '1' and NUM_VC_EN_G > 3 then arbVc <= "11"; arbValid <= '1';
292  else arbVc <= "11"; arbValid <= '0'; end if;
293  when others =>
294  arbVc <= "00"; arbValid <= '0';
295  end case;
296  end process;
297 
298 
299  -- Lock in the status of the last cell transmitted
300  process (pgpTxClk)
301  begin
302  if rising_edge(pgpTxClk) then
303  if pgpTxClkRst = '1' then
304  vcInFrame <= "0000" after TPD_G;
305  elsif pgpTxClkEn = '1' then
306  -- Link is down or flush requested, reset status
307  if pgpTxLinkReady = '0' or pgpTxFlush = '1' then
308  vcInFrame <= "0000" after TPD_G;
309  else
310 
311  -- Update state of VC, track if VC is currently in frame or not
312  -- SOF transmitted
313  if schTxSOF = '1' then
314  vcInFrame(conv_integer(currVc)) <= '1' after TPD_G;
315 
316  -- EOF transmitted
317  elsif schTxEOF = '1' then
318  vcInFrame(conv_integer(currVc)) <= '0' after TPD_G;
319  end if;
320  end if;
321  end if;
322  end if;
323  end process;
324 
325  -- Detect frame transmit timeout, enabled only in VC non interleave mode
326  process (pgpTxClk)
327  begin
328  if rising_edge(pgpTxClk) then
329  if pgpTxClkRst = '1' or VC_INTERLEAVE_G = 1 then
330  vcTimerA <= (others => '0') after TPD_G;
331  vcTimerB <= (others => '0') after TPD_G;
332  vcTimerC <= (others => '0') after TPD_G;
333  vcTimerD <= (others => '0') after TPD_G;
334  vcTimeout <= (others => '0') after TPD_G;
335  elsif pgpTxClkEn = '1' then
336  if vcInFrame(0) = '0' or (currVc = 0 and intTxReq = '1') then
337  vcTimerA <= (others => '0') after TPD_G;
338  vcTimeout(0) <= '0' after TPD_G;
339  elsif vcTimerA /= x"FFFFFF" then
340  vcTimerA <= vcTimerA + 1 after TPD_G;
341  vcTimeout(0) <= '0' after TPD_G;
342  else
343  vcTimeout(0) <= '1' after TPD_G;
344  end if;
345 
346  if NUM_VC_EN_G > 1 then
347  if vcInFrame(1) = '0' or (currVc = 1 and intTxReq = '1') then
348  vcTimerB <= (others => '0') after TPD_G;
349  vcTimeout(1) <= '0' after TPD_G;
350  elsif vcTimerB /= x"FFFFFF" then
351  vcTimerB <= vcTimerB + 1 after TPD_G;
352  vcTimeout(1) <= '0' after TPD_G;
353  else
354  vcTimeout(1) <= '1' after TPD_G;
355  end if;
356  end if;
357 
358  if NUM_VC_EN_G > 2 then
359  if vcInFrame(2) = '0' or (currVc = 2 and intTxReq = '1') then
360  vcTimerC <= (others => '0') after TPD_G;
361  vcTimeout(2) <= '0' after TPD_G;
362  elsif vcTimerC /= x"FFFFFF" then
363  vcTimerC <= vcTimerC + 1 after TPD_G;
364  vcTimeout(2) <= '0' after TPD_G;
365  else
366  vcTimeout(2) <= '1' after TPD_G;
367  end if;
368  end if;
369 
370  if NUM_VC_EN_G > 3 then
371  if vcInFrame(3) = '0' or (currVc = 3 and intTxReq = '1') then
372  vcTimerD <= (others => '0') after TPD_G;
373  vcTimeout(3) <= '0' after TPD_G;
374  elsif vcTimerD /= x"FFFFFF" then
375  vcTimerD <= vcTimerD + 1 after TPD_G;
376  vcTimeout(3) <= '0' after TPD_G;
377  else
378  vcTimeout(3) <= '1' after TPD_G;
379  end if;
380  end if;
381  end if;
382  end if;
383  end process;
384 
385 end Pgp2bTxSched;
386 
out schTxTimeoutsl
in vc3RemAlmostFullsl
in pgpTxClkEnsl := '1'
std_logic sl
Definition: StdRtlPkg.vhd:28
_library_ ieeeieee
Definition: Pgp2bTxPhy.vhd:19
out schTxDataVcslv( 1 downto 0)
slv( 1 downto 0) currVc
slv( 2 downto 0) := "100" ST_GAP_A_C
slv( 3 downto 0) vcTimeout
in pgpTxLinkReadysl
slv( 23 downto 0) vcTimerD
slv( 2 downto 0) := "011" ST_CELL_C
slv( 2 downto 0) := "001" ST_RST_C
slv( 1 downto 0) arbVc
slv( 2 downto 0) := "110" ST_GAP_C_C
in vc2RemAlmostFullsl
out schTxReqsl
slv( 1 downto 0) nextVc
slv( 2 downto 0) := "101" ST_GAP_B_C
slv( 2 downto 0) := "010" ST_ARB_C
slv( 2 downto 0) curState
in vc0FrameTxValidsl
slv( 2 downto 0) nxtState
NUM_VC_EN_Ginteger range 1 to 4:= 4
slv( 23 downto 0) vcTimerC
VC_INTERLEAVE_Ginteger := 1
slv( 23 downto 0) vcTimerA
slv( 3 downto 0) vcInFrame
in vc0RemAlmostFullsl
in vc2FrameTxValidsl
in vc3FrameTxValidsl
in pgpTxClkRstsl
TPD_Gtime := 1 ns
slv( 3 downto 0) gateTxValid
in vc1FrameTxValidsl
slv( 23 downto 0) vcTimerB
in vc1RemAlmostFullsl
in pgpTxFlushsl
out schTxIdlesl
std_logic_vector slv
Definition: StdRtlPkg.vhd:29