SURF  1.0
SaltTx.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SaltTx.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-09-01
5 -- Last update: 2015-09-22
6 -------------------------------------------------------------------------------
7 -- Description: SALT TX Engine Module
8 -------------------------------------------------------------------------------
9 -- This file is part of 'SLAC Firmware Standard Library'.
10 -- It is subject to the license terms in the LICENSE.txt file found in the
11 -- top-level directory of this distribution and at:
12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
13 -- No part of 'SLAC Firmware Standard Library', including this file,
14 -- may be copied, modified, propagated, or distributed except according to
15 -- the terms contained in the LICENSE.txt file.
16 -------------------------------------------------------------------------------
17 
18 library ieee;
19 use ieee.std_logic_1164.all;
20 use ieee.std_logic_unsigned.all;
21 use ieee.std_logic_arith.all;
22 
23 use work.StdRtlPkg.all;
24 use work.AxiStreamPkg.all;
25 use work.SsiPkg.all;
26 use work.SaltPkg.all;
27 
28 --! @see entity
29  --! @ingroup protocols_salt_core
30 entity SaltTx is
31  generic (
32  TPD_G : time := 1 ns;
33  COMMON_TX_CLK_G : boolean := false; -- Set to true if sAxisClk and clk are the same clock
34  SLAVE_AXI_CONFIG_G : AxiStreamConfigType := ssiAxiStreamConfig(4));
35  port (
36  -- Slave Port
37  sAxisClk : in sl;
38  sAxisRst : in sl;
41  -- GMII Interface
42  txEn : out sl;
43  txData : out slv(7 downto 0);
44  clk : in sl;
45  rst : in sl);
46 end SaltTx;
47 
48 architecture rtl of SaltTx is
49 
50  type StateType is (
51  IDLE_S,
52  BUFFER_S,
53  PREAMBLE_S,
54  SFD_S,
55  HEADER_S,
56  LENGTH_S,
57  MOVE_S,
58  CHECKSUM_S,
59  FOOTER_S);
60 
61  type RegType is record
62  flushBuffer : sl;
63  sof : sl;
64  eof : sl;
65  eofe : sl;
66  gapCnt : natural range 0 to INTER_GAP_SIZE_C;
67  seqCnt : slv(7 downto 0);
68  tDest : slv(7 downto 0);
69  cnt : slv(15 downto 0);
70  length : slv(15 downto 0);
71  checksum : slv(31 downto 0);
72  txMaster : AxiStreamMasterType;
73  rxSlave : AxiStreamSlaveType;
74  sMaster : AxiStreamMasterType;
75  mSlave : AxiStreamSlaveType;
76  gmiiSlave : AxiStreamSlaveType;
77  state : StateType;
78  end record RegType;
79  constant REG_INIT_C : RegType := (
80  flushBuffer => '1',
81  sof => '0',
82  eof => '0',
83  eofe => '0',
84  gapCnt => 0,
85  seqCnt => (others => '0'),
86  tDest => (others => '0'),
87  cnt => (others => '0'),
88  length => (others => '0'),
89  checksum => (others => '0'),
90  txMaster => AXI_STREAM_MASTER_INIT_C,
91  rxSlave => AXI_STREAM_SLAVE_INIT_C,
92  sMaster => AXI_STREAM_MASTER_INIT_C,
93  mSlave => AXI_STREAM_SLAVE_INIT_C,
94  gmiiSlave => AXI_STREAM_SLAVE_INIT_C,
95  state => IDLE_S);
96 
97  signal r : RegType := REG_INIT_C;
98  signal rin : RegType;
99 
100  signal rxMaster : AxiStreamMasterType;
101  signal rxSlave : AxiStreamSlaveType;
102  signal sMaster : AxiStreamMasterType;
103  signal sSlave : AxiStreamSlaveType;
104  signal mMaster : AxiStreamMasterType;
105  signal mSlave : AxiStreamSlaveType;
106  signal txMaster : AxiStreamMasterType;
107  signal txSlave : AxiStreamSlaveType;
108  signal gmiiMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C;
109  signal gmiiSlave : AxiStreamSlaveType;
110 
111 begin
112 
113  FIFO_RX : entity work.AxiStreamFifoV2
114  generic map (
115  -- General Configurations
116  TPD_G => TPD_G,
117  PIPE_STAGES_G => 0,
118  SLAVE_READY_EN_G => true,
119  VALID_THOLD_G => 1,
120  -- FIFO configurations
121  BRAM_EN_G => false,
122  USE_BUILT_IN_G => false,
124  CASCADE_SIZE_G => 1,
125  FIFO_ADDR_WIDTH_G => 4,
126  FIFO_PAUSE_THRESH_G => ((2**4)-2),
127  -- AXI Stream Port Configurations
130  port map (
131  -- Slave Port
132  sAxisClk => sAxisClk,
133  sAxisRst => sAxisRst,
136  -- Master Port
137  mAxisClk => clk,
138  mAxisRst => rst,
139  mAxisMaster => rxMaster,
140  mAxisSlave => rxSlave);
141 
142  DATAGRAM_BUFFER : entity work.AxiStreamFifoV2
143  generic map (
144  -- General Configurations
145  TPD_G => TPD_G,
146  PIPE_STAGES_G => 0,
147  SLAVE_READY_EN_G => true,
148  VALID_THOLD_G => 1,
149  -- FIFO configurations
150  BRAM_EN_G => true,
151  USE_BUILT_IN_G => false,
152  GEN_SYNC_FIFO_G => true,
153  CASCADE_SIZE_G => 1,
154  FIFO_ADDR_WIDTH_G => 9,
155  -- AXI Stream Port Configurations
158  port map (
159  -- Slave Port
160  sAxisClk => clk,
161  sAxisRst => r.flushBuffer,
162  sAxisMaster => sMaster,
163  sAxisSlave => sSlave,
164  -- Master Port
165  mAxisClk => clk,
166  mAxisRst => r.flushBuffer,
167  mAxisMaster => mMaster,
168  mAxisSlave => mSlave);
169 
170 
171  comb : process (gmiiMaster, mMaster, r, rst, rxMaster, sSlave, txSlave) is
172  variable v : RegType;
173  begin
174  -- Latch the current value
175  v := r;
176 
177  -- Reset the flags
178  v.flushBuffer := '0';
179  v.rxSlave := AXI_STREAM_SLAVE_INIT_C;
180  if txSlave.tReady = '1' then
181  v.txMaster.tValid := '0';
182  v.txMaster.tLast := '0';
183  v.txMaster.tUser := (others => '0');
184  end if;
185  v.mSlave := AXI_STREAM_SLAVE_INIT_C;
186  if sSlave.tReady = '1' then
187  v.sMaster.tValid := '0';
188  v.sMaster.tLast := '0';
189  v.sMaster.tUser := (others => '0');
190  end if;
191 
192  -- State Machine
193  case r.state is
194  ----------------------------------------------------------------------
195  when IDLE_S =>
196  -- Reset flags/accumulators
197  v.flushBuffer := '1';
198  v.sof := '0';
199  v.eof := '0';
200  v.eofe := '0';
201  v.length := (others => '0');
202  v.checksum := (others => '0');
203  v.cnt := (others => '0');
204  -- Check for data
205  if (rxMaster.tValid = '1') then
206  -- Check for SOF
207  if ssiGetUserSof(SSI_SALT_CONFIG_C, rxMaster) = '1' then
208  -- Set the flag
209  v.sof := '1';
210  -- Reset the counter
211  v.seqCnt := x"00";
212  -- Latch the destination
213  v.tDest := rxMaster.tDest;
214  else
215  -- Increment the counter
216  v.seqCnt := r.seqCnt + 1;
217  end if;
218  -- Next state
219  v.state := BUFFER_S;
220  end if;
221  ----------------------------------------------------------------------
222  when BUFFER_S =>
223  -- Check if ready to move data
224  if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') then
225  -- Accept the data
226  v.rxSlave.tReady := '1';
227  -- Move the data
228  v.sMaster := rxMaster;
229  -- Mask off tLast for intergap monitoring
230  v.sMaster.tLast := '0';
231  -- Increment the counter
232  v.length := r.length + 1;
233  -- Check for EOF
234  if rxMaster.tLast = '1' then
235  -- Set the flags
236  v.eof := '1';
237  v.eofe := ssiGetUserEofe(SSI_SALT_CONFIG_C, rxMaster);
238  -- Next state
239  v.state := PREAMBLE_S;
240  elsif v.length = SALT_MAX_WORDS_C then
241  -- Next state
242  v.state := PREAMBLE_S;
243  end if;
244  end if;
245  ----------------------------------------------------------------------
246  when PREAMBLE_S =>
247  -- Check if ready to move data
248  if (v.txMaster.tValid = '0') then
249  -- Write the preamble
250  v.txMaster.tValid := '1';
251  v.txMaster.tData(31 downto 0) := PREAMBLE_C;
252  -- Next state
253  v.state := SFD_S;
254  end if;
255  ----------------------------------------------------------------------
256  when SFD_S =>
257  -- Check if ready to move data
258  if (v.txMaster.tValid = '0') then
259  -- Write the preamble
260  v.txMaster.tValid := '1';
261  v.txMaster.tData(31 downto 0) := SFD_C;
262  -- Next state
263  v.state := HEADER_S;
264  end if;
265  ----------------------------------------------------------------------
266  when HEADER_S =>
267  -- Check if ready to move data
268  if (v.txMaster.tValid = '0') then
269  -- Write the header
270  v.txMaster.tValid := '1';
271  if r.sof = '1' then
272  v.txMaster.tData(31 downto 0) := SOF_C;
273  else
274  v.txMaster.tData(31 downto 0) := SOC_C;
275  end if;
276  -- Next state
277  v.state := LENGTH_S;
278  end if;
279  ----------------------------------------------------------------------
280  when LENGTH_S =>
281  -- Check if ready to move data
282  if (v.txMaster.tValid = '0') then
283  -- Move the data
284  v.txMaster.tValid := '1';
285  v.txMaster.tData(15 downto 0) := r.length;
286  v.txMaster.tData(23 downto 16) := r.tDest;
287  v.txMaster.tData(31 downto 24) := r.seqCnt;
288  -- Update checksum
289  v.checksum := v.txMaster.tData(31 downto 0);
290  -- Next state
291  v.state := MOVE_S;
292  end if;
293  ----------------------------------------------------------------------
294  when MOVE_S =>
295  -- Check for valid data
296  if (mMaster.tValid = '1') and (v.txMaster.tValid = '0') then
297  -- Accept the data
298  v.mSlave.tReady := '1';
299  -- Move the data
300  v.txMaster := mMaster;
301  -- Update checksum
302  v.checksum := r.checksum + mMaster.tData(31 downto 0);
303  -- Increment the counter
304  v.cnt := r.cnt + 1;
305  -- Check the length
306  if v.cnt = r.length then
307  -- Flush the buffer
308  v.flushBuffer := '1';
309  -- Next state
310  v.state := CHECKSUM_S;
311  end if;
312  end if;
313  ----------------------------------------------------------------------
314  when CHECKSUM_S =>
315  -- Check if ready to move data
316  if (v.txMaster.tValid = '0') then
317  -- Move the data
318  v.txMaster.tValid := '1';
319  v.txMaster.tData(31 downto 0) := not(r.checksum); -- one's complement
320  -- Next state
321  v.state := FOOTER_S;
322  end if;
323  ----------------------------------------------------------------------
324  when FOOTER_S =>
325  -- Check if ready to move data
326  if (v.txMaster.tValid = '0') then
327  -- Write the footer
328  v.txMaster.tValid := '1';
329  -- Insert tLast for intergap monitoring
330  v.txMaster.tLast := '1';
331  -- Check for EOF
332  if r.eof = '0' then
333  v.txMaster.tData(31 downto 0) := EOC_C;
334  else
335  if r.eofe = '0' then
336  v.txMaster.tData(31 downto 0) := EOF_C;
337  else
338  v.txMaster.tData(31 downto 0) := EOFE_C;
339  end if;
340  end if;
341  -- Next state
342  v.state := IDLE_S;
343  end if;
344  ----------------------------------------------------------------------
345  end case;
346 
347  -- Check the current state of gmiiSlave
348  if r.gmiiSlave.tReady = '0' then
349  -- Check the intergap counter
350  if r.gapCnt = INTER_GAP_SIZE_C then
351  -- Set the flag
352  v.gmiiSlave.tReady := '1';
353  else
354  v.gapCnt := r.gapCnt + 1;
355  end if;
356  else
357  -- Check for GMII tLast
358  if (gmiiMaster.tValid = '1') and (gmiiMaster.tLast = '1') then
359  -- Reset the flag and counter
360  v.gmiiSlave.tReady := '0';
361  v.gapCnt := 0;
362  end if;
363  end if;
364 
365  -- Reset
366  if (rst = '1') then
367  v := REG_INIT_C;
368  end if;
369 
370  -- Register the variable for next clock cycle
371  rin <= v;
372 
373  -- Outputs
374  mSlave <= v.mSlave;
375  sMaster <= r.sMaster;
376  rxSlave <= v.rxSlave;
377  txMaster <= r.txMaster;
378  gmiiSlave <= r.gmiiSlave;
379 
380  end process comb;
381 
382  seq : process (clk) is
383  begin
384  if rising_edge(clk) then
385  r <= rin after TPD_G;
386  end if;
387  end process seq;
388 
389  FIFO_TX : entity work.AxiStreamFifoV2
390  generic map (
391  -- General Configurations
392  TPD_G => TPD_G,
393  PIPE_STAGES_G => 0,
394  SLAVE_READY_EN_G => true,
395  VALID_THOLD_G => 1,
396  -- FIFO configurations
397  BRAM_EN_G => true,
398  USE_BUILT_IN_G => false,
399  GEN_SYNC_FIFO_G => true,
400  CASCADE_SIZE_G => 1,
401  FIFO_ADDR_WIDTH_G => 9,
402  -- AXI Stream Port Configurations
405  port map (
406  -- Slave Port
407  sAxisClk => clk,
408  sAxisRst => rst,
409  sAxisMaster => txMaster,
410  sAxisSlave => txSlave,
411  -- Master Port
412  mAxisClk => clk,
413  mAxisRst => rst,
414  mAxisMaster => gmiiMaster,
415  mAxisSlave => gmiiSlave);
416 
417  txEn <= gmiiMaster.tValid and gmiiSlave.tReady;
418  txData <= gmiiMaster.tData(7 downto 0);
419 
420 end rtl;
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
in sAxisClksl
Definition: SaltTx.vhd:37
sl sof
Definition: SsiPkg.vhd:72
PIPE_STAGES_Gnatural range 0 to 16:= 1
_library_ ieeeieee
Definition: SaltRx.vhd:18
slv( 31 downto 0) := x"CCCCCCCC" SOC_C
Definition: SaltPkg.vhd:34
slv( 31 downto 0) := x"D5555555" SFD_C
Definition: SaltPkg.vhd:40
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
AxiStreamConfigType := ssiAxiStreamConfig( 4, TKEEP_COMP_C, TUSER_FIRST_LAST_C, 8) SSI_SALT_CONFIG_C
Definition: SaltPkg.vhd:29
sl eofe
Definition: SsiPkg.vhd:74
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
SLAVE_AXI_CONFIG_GAxiStreamConfigType := ssiAxiStreamConfig( 4)
Definition: SaltTx.vhd:34
in sAxisMasterAxiStreamMasterType
Definition: SaltTx.vhd:39
SLAVE_READY_EN_Gboolean := true
in sAxisRstsl
Definition: SaltTx.vhd:38
out sAxisSlaveAxiStreamSlaveType
Definition: SaltTx.vhd:40
GEN_SYNC_FIFO_Gboolean := false
in rstsl
Definition: SaltTx.vhd:45
AxiStreamConfigType := ssiAxiStreamConfig( 1, TKEEP_COMP_C, TUSER_FIRST_LAST_C, 0) SSI_GMII_CONFIG_C
Definition: SaltPkg.vhd:28
in clksl
Definition: SaltTx.vhd:44
TPD_Gtime := 1 ns
Definition: SaltTx.vhd:32
slv( 31 downto 0) := x"DDDDDDDD" EOC_C
Definition: SaltPkg.vhd:35
slv( 127 downto 0) tData
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
BRAM_EN_Gboolean := true
slv( 127 downto 0) tUser
slv( 31 downto 0) := x"FFFFFFFF" EOFE_C
Definition: SaltPkg.vhd:37
TPD_Gtime := 1 ns
COMMON_TX_CLK_Gboolean := false
Definition: SaltTx.vhd:33
out sAxisSlaveAxiStreamSlaveType
slv( 7 downto 0) tDest
slv( 31 downto 0) := x"BBBBBBBB" SOF_C
Definition: SaltPkg.vhd:33
in sAxisMasterAxiStreamMasterType
out mAxisMasterAxiStreamMasterType
out txDataslv( 7 downto 0)
Definition: SaltTx.vhd:43
natural := 12 INTER_GAP_SIZE_C
Definition: SaltPkg.vhd:31
out txEnsl
Definition: SaltTx.vhd:42
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
USE_BUILT_IN_Gboolean := false
FIFO_PAUSE_THRESH_Ginteger range 1 to ( 2** 24):= 1
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
slv( 31 downto 0) := x"55555555" PREAMBLE_C
Definition: SaltPkg.vhd:39
sl eof
Definition: SsiPkg.vhd:73
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
slv( 31 downto 0) := x"EEEEEEEE" EOF_C
Definition: SaltPkg.vhd:36
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
natural :=( 1500/ 4) SALT_MAX_WORDS_C
Definition: SaltPkg.vhd:30