SURF  1.0
ConnFSM.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : ConnFSM.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-08-09
5 -- Last update: 2016-06-23
6 -------------------------------------------------------------------------------
7 -- Description: Connection establishment mechanism:
8 -- - Connection open/close request,
9 -- - Parameter negotiation,
10 -- - Server-client mode (More comments below).
11 -------------------------------------------------------------------------------
12 -- This file is part of 'SLAC Firmware Standard Library'.
13 -- It is subject to the license terms in the LICENSE.txt file found in the
14 -- top-level directory of this distribution and at:
15 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
16 -- No part of 'SLAC Firmware Standard Library', including this file,
17 -- may be copied, modified, propagated, or distributed except according to
18 -- the terms contained in the LICENSE.txt file.
19 -------------------------------------------------------------------------------
20 
21 library ieee;
22 use ieee.std_logic_1164.all;
23 use ieee.std_logic_unsigned.all;
24 use ieee.std_logic_arith.all;
25 
26 use work.StdRtlPkg.all;
27 use work.RssiPkg.all;
28 
29 --! @see entity
30  --! @ingroup protocols_rssi
31 entity ConnFSM is
32  generic (
33  TPD_G : time := 1 ns;
34  SERVER_G : boolean := true;
35  --
36  TIMEOUT_UNIT_G : real := 1.0E-6; -- us
37  CLK_FREQUENCY_G : real := 100.0E6;
38  -- Time the module waits for the response until it retransmits SYN segment
39  RETRANS_TOUT_G : positive := 50;
40  MAX_RETRANS_CNT_G : positive := 2;
41  --
42  WINDOW_ADDR_SIZE_G : positive := 3;
43  SEGMENT_ADDR_SIZE_G : positive := 7 -- 2^SEGMENT_ADDR_SIZE_G = Number of 64 bit wide data words
44  );
45  port (
46  clk_i : in sl;
47  rst_i : in sl;
48 
49  -- Connection request (open/close)
50  connRq_i : in sl;
51  closeRq_i : in sl;
52 
53  -- Parameters received from peer (Server)
55 
56  -- Parameters set by high level App or generic (Client)
58 
59  -- Negotiated parameters
61 
62  -- Flags from Rx module
63  rxFlags_i : in FlagsType;
64 
65  -- Valid received packet
66  rxValid_i : in sl;
67 
70  rstHeadSt_i : in sl;
71 
72  --
73  -- Connection FSM indicating active connection
75 
76  -- FSM in closed state (indicating when to initialize seqN)
77  closed_o : out sl;
78 
79  --
80  sndSyn_o : out sl;
81  sndAck_o : out sl;
82  sndRst_o : out sl;
83  txAckF_o : out sl;
84  --
85 
86  -- Window size and buffer size different for Rx and Tx
87  rxBufferSize_o : out integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_G);
88  rxWindowSize_o : out integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G);
89  --
90  txBufferSize_o : out integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_G);
91  txWindowSize_o : out integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G);
92 
93  -- Status signals
94  peerTout_o : out sl;
95  paramReject_o : out sl
96  );
97 end entity ConnFSM;
98 
99 architecture rtl of ConnFSM is
100  --
101  constant SAMPLES_PER_TIME_C : integer := integer(TIMEOUT_UNIT_G * CLK_FREQUENCY_G);
102  --
103  type StateType is (
104  CLOSED_S,
105  SEND_SYN_S,
106  WAIT_SYN_S,
107  LISTEN_S,
108  SEND_ACK_S,
109  SEND_SYN_ACK_S,
110  WAIT_ACK_S,
111  SEND_RST_S,
112  OPEN_S
113  );
114 
115  type RegType is record
116  connActive : sl;
117  closed : sl;
118  sndSyn : sl;
119  sndAck : sl;
120  sndRst : sl;
121  txAckF : sl;
122  peerTout : sl;
123  paramReject : sl;
124 
125  rssiParam : RssiParamType;
126 
127  --
128  txBufferSize : integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_G);
129  txWindowSize : integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G);
130  --
131  timeoutCntr : integer range 0 to RETRANS_TOUT_G * SAMPLES_PER_TIME_C;
132  resendCntr : integer range 0 to MAX_RETRANS_CNT_G+1;
133 
134  ---
135  state : StateType;
136 
137  end record RegType;
138 
139  constant REG_INIT_C : RegType := (
140  connActive => '0',
141  closed => '1',
142  sndSyn => '0',
143  sndAck => '0',
144  sndRst => '0',
145  txAckF => '0',
146  peerTout => '0',
147  paramReject => '0',
148 
149  rssiParam => RSSI_PARAM_INIT_C,
150 
151  timeoutCntr => 0,
152  resendCntr => 0,
153  --
154  txBufferSize=> 1,
155  txWindowSize=> 1,
156 
157  ---
158  state => CLOSED_S
159 
160  );
161 
162  signal r : RegType := REG_INIT_C;
163  signal rin : RegType;
164 
165 
166 
167 begin
168 
169  comb : process (r, rst_i, connRq_i, rxRssiParam_i, synHeadSt_i, rxFlags_i,
171  variable v : RegType;
172  begin
173  v := r;
174 
175  -- /////////////////////////////////////////////////////////
176  ------------------------------------------------------------
177  -- Connection FSM
178  -- Synchronization and parameter negotiation
179  ------------------------------------------------------------
180  -- /////////////////////////////////////////////////////////
181 
182  case r.state is
183  ----------------------------------------------------------------------
184  when CLOSED_S =>
185 
186  -- Initialize parameters
187  v := REG_INIT_C;
188 
189  -- Next state condition
190  -- Initiated by high level App and depends on whether it is a
191  -- server or client.
192  if (connRq_i = '1' and SERVER_G = true) then
193  v.state := LISTEN_S; -- Server Passive open
194  elsif (connRq_i = '1' and SERVER_G = false) then
195  v.state := SEND_SYN_S;-- Client Active open
196  end if;
197  ----------------------------------------------------------------------
198  -- Client
199  -- Actively open connection
200  -- Propose parameters
201  -- Accept parameters from server or close connection
202  ----------------------------------------------------------------------
203  when SEND_SYN_S =>
204 
205  v.connActive := '0';
206  v.closed := '0';
207  v.sndSyn := '1';
208  v.sndAck := '0';
209  v.sndRst := '0';
210  v.txAckF := '0';
211  v.peerTout := '0';
212  v.paramReject := '0';
213  v.timeoutCntr := 0;
214 
215  -- Send the Client proposed parameters
216  v.rssiParam := appRssiParam_i;
217 
218  if (synHeadSt_i = '1') then
219  v.state := WAIT_SYN_S;
220  end if;
221 
222  ----------------------------------------------------------------------
223  when WAIT_SYN_S =>
224 
225  v.connActive := '0';
226  v.sndSyn := '0';
227  v.sndAck := '0';
228  v.sndRst := '0';
229  v.txAckF := '0';
230  v.timeoutCntr := r.timeoutCntr + 1;
231  --
232  if (rxValid_i = '1' and rxFlags_i.syn = '1' and rxFlags_i.ack = '1') then
233  -- Check parameters
234  if (
235  rxRssiParam_i.version = appRssiParam_i.version and -- Version match
236  rxRssiParam_i.chksumEn = appRssiParam_i.chksumEn and -- Checksum match
237  rxRssiParam_i.timeoutUnit= appRssiParam_i.timeoutUnit -- Timeout unit match
238  ) then
239  -- Accept the parameters from the server
240  v.rssiParam := rxRssiParam_i;
241  v.txBufferSize := conv_integer(rxRssiParam_i.maxSegSize(15 downto 3)); -- Divide by 8
242  v.txWindowSize := conv_integer(rxRssiParam_i.maxOutsSeg);
243 
244  -- Check the sizes and saturate to MAX if bigger
245  if(rxRssiParam_i.maxOutsSeg > (2**WINDOW_ADDR_SIZE_G)) then -- Number of segments in a window
246  v.rssiParam.maxOutsSeg := toSlv((2**WINDOW_ADDR_SIZE_G), v.rssiParam.maxOutsSeg'length);
247  v.txWindowSize := (2**WINDOW_ADDR_SIZE_G);
248  end if;
249 
250  if(rxRssiParam_i.maxSegSize > (2**SEGMENT_ADDR_SIZE_G)*8) then -- Number of bytes in a segment
251  v.rssiParam.maxSegSize := toSlv((2**SEGMENT_ADDR_SIZE_G)*8, v.rssiParam.maxSegSize'length);
252  v.txBufferSize := (2**SEGMENT_ADDR_SIZE_G); -- Divide by 8
253  end if;
254  --
255  v.state := SEND_ACK_S;
256  else
257  -- Reject parameters and reset the connection
258  v.paramReject := '1';
259  v.rssiParam := r.rssiParam;
260  --
261  v.state := SEND_RST_S;
262  end if;
263  elsif (rxValid_i = '1' and rxFlags_i.rst = '1') then
264  v.state := CLOSED_S;
265  elsif (r.timeoutCntr = RETRANS_TOUT_G * SAMPLES_PER_TIME_C) then
266  if (r.resendCntr >= MAX_RETRANS_CNT_G) then
267  v.peerTout := '1';
268  v.state := CLOSED_S;
269  else
270  v.closed := '1'; -- Signal closed to reset seqN (Resend SYN with the initial seqN)
271  v.resendCntr := r.resendCntr + 1;
272  v.state := SEND_SYN_S;
273  end if;
274  end if;
275  ----------------------------------------------------------------------
276  when SEND_ACK_S =>
277  --
278  v.connActive := '0';
279  v.sndSyn := '0';
280  v.sndAck := '1';
281  v.sndRst := '0';
282  v.txAckF := '1';
283  v.timeoutCntr := 0;
284  v.resendCntr := 0;
285  v.paramReject := '0';
286  --
287  v.rssiParam := r.rssiParam;
288 
289  --
290  if (ackHeadSt_i = '1') then
291  v.state := OPEN_S;
292  end if;
293 
294  ----------------------------------------------------------------------
295  -- Server
296  -- Passively open connection. Go to listen state and wait for SYN.
297  -- Check clients parameters:
298  -- If valid accept parameters,
299  -- If not valid propose new parameters.
300  ----------------------------------------------------------------------
301  when LISTEN_S =>
302  --
303  v.connActive := '0';
304  v.closed := '0';
305  v.sndSyn := '0';
306  v.sndAck := '0';
307  v.sndRst := '0';
308  v.txAckF := '0';
309  v.peerTout := '0';
310  v.timeoutCntr := 0;
311  --
312  if (rxValid_i = '1' and rxFlags_i.syn = '1') then
313  -- Accept the parameters from the client
314  v.rssiParam := rxRssiParam_i;
315  v.txWindowSize := conv_integer(rxRssiParam_i.maxOutsSeg);
316  v.txBufferSize := conv_integer(rxRssiParam_i.maxSegSize(15 downto 3)); -- Divide by 8
317  -- Set the receiver side information to be sent
318  v.rssiParam.maxOutsSeg := appRssiParam_i.maxOutsSeg;
319  v.rssiParam.maxSegSize := appRssiParam_i.maxSegSize;
320 
321  -- Check the sizes and saturate to MAX if bigger
322  if(rxRssiParam_i.maxOutsSeg > (2**WINDOW_ADDR_SIZE_G)) then -- Number of segments in a window
323  v.txWindowSize := (2**WINDOW_ADDR_SIZE_G);
324  end if;
325 
326  if(rxRssiParam_i.maxSegSize > (2**SEGMENT_ADDR_SIZE_G)*8) then -- Number of bytes in a segment
327  v.txBufferSize := (2**SEGMENT_ADDR_SIZE_G); -- Divide by 8
328  end if;
329 
330  --
331  v.paramReject := '0';
332 
333  -- Check parameters that have to match
334  if (
335  rxRssiParam_i.version /= appRssiParam_i.version or -- Version equality
336  rxRssiParam_i.chksumEn /= appRssiParam_i.chksumEn or -- Checksum match
337  rxRssiParam_i.timeoutUnit/= appRssiParam_i.timeoutUnit -- Timeout unit match
338  ) then
339 
340  -- Propose different parameters (overwrite)
341  v.rssiParam.version := appRssiParam_i.version;
342  v.rssiParam.timeoutUnit := appRssiParam_i.timeoutUnit;
343  v.rssiParam.chksumEn := appRssiParam_i.chksumEn;
344  --
345  v.paramReject := '1';
346  end if;
347  -- Go to ACK state
348  v.state := SEND_SYN_ACK_S;
349  end if;
350  ---------------------------------------------------------------------
351  when SEND_SYN_ACK_S =>
352 
353  v.connActive := '0';
354  v.closed := '0';
355  v.sndSyn := '1';
356  v.sndAck := '0';
357  v.sndRst := '0';
358  v.txAckF := '1';
359  v.paramReject := '0';
360  v.timeoutCntr := 0;
361 
362  -- Send the Server parameters
363  v.rssiParam := r.rssiParam;
364 
365  if (synHeadSt_i = '1') then
366  v.state := WAIT_ACK_S;
367  end if;
368 
369  when WAIT_ACK_S =>
370 
371  v.connActive := '0';
372  v.sndSyn := '0';
373  v.sndAck := '0';
374  v.sndRst := '0';
375  v.txAckF := '0';
376  v.paramReject := '0';
377  --
378  v.timeoutCntr := r.timeoutCntr+1;
379 
380  --
381  v.rssiParam := r.rssiParam;
382 
383  if (rxValid_i = '1' and rxFlags_i.ack = '1') then
384  v.state := OPEN_S;
385  elsif (rxValid_i = '1' and rxFlags_i.rst = '1') then
386  v.state := CLOSED_S;
387  elsif (r.timeoutCntr = RETRANS_TOUT_G * SAMPLES_PER_TIME_C) then
388  if (r.resendCntr >= MAX_RETRANS_CNT_G) then
389  v.peerTout := '1';
390  v.state := CLOSED_S;
391  else
392  v.closed := '1'; -- Signal closed to reset seqN (Resend SYN with the initial seqN)
393  v.resendCntr := r.resendCntr + 1;
394  v.state := SEND_SYN_ACK_S;
395  end if;
396  end if;
397 
398  ----------------------------------------------------------------------
399  -- Open connection
400  --
401  --
402  ----------------------------------------------------------------------
403  when OPEN_S =>
404  --
405  v.connActive := '1';
406  v.sndSyn := '0';
407  v.sndAck := '0';
408  v.sndRst := '0';
409  v.txAckF := '1';
410  v.paramReject := '0';
411  --
412  v.timeoutCntr := 0;
413  v.resendCntr := 0;
414  --
415  v.rssiParam := r.rssiParam;
416 
417  --
418  if (rxValid_i = '1' and rxFlags_i.rst = '1') then
419  v.state := SEND_RST_S;
420  elsif (closeRq_i = '1') then
421  v.state := SEND_RST_S;
422  end if;
423 
424  ----------------------------------------------------------------------
425  -- Reset the connection
426  -- - Send Rst segment
427  -- - Go to Closed
428  ----------------------------------------------------------------------
429  when SEND_RST_S =>
430  --
431  v.connActive := r.connActive;
432  v.sndSyn := '0';
433  v.sndAck := '0';
434  v.sndRst := '1';
435  v.txAckF := '0';
436  v.paramReject := '0';
437  --
438  v.rssiParam := r.rssiParam;
439 
440  --
441  if (rstHeadSt_i = '1') then
442  v.state := CLOSED_S;
443  end if;
444 
445  ----------------------------------------------------------------------
446  when others =>
447  v := REG_INIT_C;
448  ----------------------------------------------------------------------
449  end case;
450 
451  if (rst_i = '1') then
452  v := REG_INIT_C;
453  end if;
454 
455  rin <= v;
456  -----------------------------------------------------------
457  end process comb;
458 
459  seq : process (clk_i) is
460  begin
461  if (rising_edge(clk_i)) then
462  r <= rin after TPD_G;
463  end if;
464  end process seq;
465 
466  ------------------------------------------------------------------------------
467  -- Output assignment
468  rssiParam_o <= r.rssiParam;
469  connActive_o <= r.connActive;
470  sndSyn_o <= r.sndSyn;
471  sndAck_o <= r.sndAck;
472  sndRst_o <= r.sndRst;
473  txAckF_o <= r.txAckF;
474 
475  -- Parameters for receiver (have to be correctly set by the app)
476  rxBufferSize_o <= conv_integer(appRssiParam_i.maxSegSize(15 downto 3)); -- Divide by 8
477  rxWindowSize_o <= conv_integer(appRssiParam_i.maxOutsSeg);
478  -- Parameters for transmitter are received by the peer and checked by FSM
479  txBufferSize_o <= r.txBufferSize;
480  txWindowSize_o <= r.txWindowSize;
481  closed_o <= r.closed;
482  --
483  peerTout_o <= r.peerTout;
484  paramReject_o <= r.paramReject;
485  ---------------------------------------------------------------------
486 end architecture rtl;
out rssiParam_oRssiParamType
Definition: ConnFSM.vhd:60
out sndRst_osl
Definition: ConnFSM.vhd:82
_library_ ieeeieee
Definition: Chksum.vhd:20
out rxBufferSize_ointeger range 1 to 2**( SEGMENT_ADDR_SIZE_G)
Definition: ConnFSM.vhd:87
out sndSyn_osl
Definition: ConnFSM.vhd:80
std_logic sl
Definition: StdRtlPkg.vhd:28
CLK_FREQUENCY_Greal := 100.0E6
Definition: ConnFSM.vhd:37
slv( 3 downto 0) version
Definition: RssiPkg.vhd:53
out connActive_osl
Definition: ConnFSM.vhd:74
in connRq_isl
Definition: ConnFSM.vhd:50
in appRssiParam_iRssiParamType
Definition: ConnFSM.vhd:57
TIMEOUT_UNIT_Greal := 1.0E-6
Definition: ConnFSM.vhd:36
in ackHeadSt_isl
Definition: ConnFSM.vhd:69
out txWindowSize_ointeger range 1 to 2**( WINDOW_ADDR_SIZE_G)
Definition: ConnFSM.vhd:91
sl rst
Definition: RssiPkg.vhd:90
sl syn
Definition: RssiPkg.vhd:87
RssiParamType :=(version =>( others => '0'),chksumEn =>( others => '0'),timeoutUnit =>( others => '0'),maxOutsSeg =>( others => '0'),maxSegSize =>( others => '0'),retransTout =>( others => '0'),cumulAckTout =>( others => '0'),nullSegTout =>( others => '0'),maxRetrans =>( others => '0'),maxCumAck =>( others => '0'),maxOutofseq =>( others => '0'),connectionId =>( others => '0')) RSSI_PARAM_INIT_C
Definition: RssiPkg.vhd:72
in synHeadSt_isl
Definition: ConnFSM.vhd:68
out sndAck_osl
Definition: ConnFSM.vhd:81
SERVER_Gboolean := true
Definition: ConnFSM.vhd:34
in rxFlags_iFlagsType
Definition: ConnFSM.vhd:63
in rxValid_isl
Definition: ConnFSM.vhd:66
out rxWindowSize_ointeger range 1 to 2**( WINDOW_ADDR_SIZE_G)
Definition: ConnFSM.vhd:88
in rxRssiParam_iRssiParamType
Definition: ConnFSM.vhd:54
in clk_isl
Definition: ConnFSM.vhd:46
out peerTout_osl
Definition: ConnFSM.vhd:94
SEGMENT_ADDR_SIZE_Gpositive := 7
Definition: ConnFSM.vhd:44
slv( 7 downto 0) maxOutsSeg
Definition: RssiPkg.vhd:57
sl ack
Definition: RssiPkg.vhd:88
WINDOW_ADDR_SIZE_Gpositive := 3
Definition: ConnFSM.vhd:42
slv( 15 downto 0) maxSegSize
Definition: RssiPkg.vhd:58
MAX_RETRANS_CNT_Gpositive := 2
Definition: ConnFSM.vhd:40
out closed_osl
Definition: ConnFSM.vhd:77
RssiParamType
Definition: RssiPkg.vhd:52
slv( 0 downto 0) chksumEn
Definition: RssiPkg.vhd:54
in rst_isl
Definition: ConnFSM.vhd:47
out paramReject_osl
Definition: ConnFSM.vhd:96
in closeRq_isl
Definition: ConnFSM.vhd:51
out txBufferSize_ointeger range 1 to 2**( SEGMENT_ADDR_SIZE_G)
Definition: ConnFSM.vhd:90
in rstHeadSt_isl
Definition: ConnFSM.vhd:70
out txAckF_osl
Definition: ConnFSM.vhd:83
RETRANS_TOUT_Gpositive := 50
Definition: ConnFSM.vhd:39
TPD_Gtime := 1 ns
Definition: ConnFSM.vhd:33
slv( 7 downto 0) timeoutUnit
Definition: RssiPkg.vhd:55