SURF  1.0
SaltRx.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SaltRx.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-09-01
5 -- Last update: 2015-09-04
6 -------------------------------------------------------------------------------
7 -- Description: SALT RX 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 SaltRx is
31  generic (
32  TPD_G : time := 1 ns;
33  COMMON_RX_CLK_G : boolean := false; -- Set to true if mAxisClk and clk are the same clock
34  MASTER_AXI_CONFIG_G : AxiStreamConfigType := ssiAxiStreamConfig(4));
35  port (
36  -- Master Port
37  mAxisClk : in sl;
38  mAxisRst : in sl;
41  -- GMII Interface
42  rxEn : in sl;
43  rxErr : in sl;
44  rxData : in slv(7 downto 0);
45  clk : in sl;
46  rst : in sl);
47 end SaltRx;
48 
49 architecture rtl of SaltRx is
50 
51  type StateType is (
52  IDLE_S,
53  LENGTH_S,
54  MOVE_S,
55  CHECKSUM_S,
56  DONE_S);
57 
58  type RegType is record
59  sof : sl;
60  eofe : sl;
61  align : sl;
62  seqCnt : slv(7 downto 0);
63  tDest : slv(7 downto 0);
64  length : slv(15 downto 0);
65  cnt : slv(15 downto 0);
66  checksum : slv(31 downto 0);
67  alignCnt : natural range 0 to 3;
68  dly : AxiStreamMasterArray(1 downto 0);
69  rxMaster : AxiStreamMasterType;
70  txMaster : AxiStreamMasterType;
71  state : StateType;
72  end record RegType;
73  constant REG_INIT_C : RegType := (
74  sof => '1',
75  eofe => '0',
76  align => '0',
77  seqCnt => (others => '0'),
78  tDest => (others => '0'),
79  length => (others => '0'),
80  cnt => (others => '0'),
81  checksum => (others => '0'),
82  alignCnt => 0,
83  dly => (others => AXI_STREAM_MASTER_INIT_C),
84  txMaster => AXI_STREAM_MASTER_INIT_C,
85  rxMaster => AXI_STREAM_MASTER_INIT_C,
86  state => IDLE_S);
87 
88  signal r : RegType := REG_INIT_C;
89  signal rin : RegType;
90 
91  signal txMaster : AxiStreamMasterType;
92  signal txSlave : AxiStreamSlaveType;
93 
94 begin
95 
96  comb : process (r, rst, rxData, rxEn, rxErr, txSlave) is
97  variable v : RegType;
98  begin
99  -- Latch the current value
100  v := r;
101 
102  -- Reset the flags
103  v.rxMaster.tValid := '0';
104  if txSlave.tReady = '1' then
105  v.txMaster.tValid := '0';
106  v.txMaster.tLast := '0';
107  v.txMaster.tUser := (others => '0');
108  end if;
109 
110  -- Set the error flag
111  v.rxMaster.tUser(SSI_EOFE_C) := rxErr;
112 
113  -- Check for valid inbound
114  if rxEn = '1' then
115  -- Shift the data
116  v.rxMaster.tData(31 downto 24) := rxData;
117  v.rxMaster.tData(23 downto 0) := r.rxMaster.tData(31 downto 8);
118  -- Check if we are phase aligning
119  if (r.align = '1') then
120  -- Check for preamble and SFD
121  if v.rxMaster.tData(31 downto 0) = SFD_C then
122  -- Reset the flag
123  v.align := '0';
124  -- Reset the counter
125  v.alignCnt := 0;
126  end if;
127  else
128  -- Check the counter
129  if r.alignCnt = 3 then
130  -- Reset the counter
131  v.alignCnt := 0;
132  -- Forward the word
133  v.rxMaster.tValid := '1';
134  else
135  -- Increment the counter
136  v.alignCnt := r.alignCnt + 1;
137  end if;
138  end if;
139  else
140  -- Need to re-align
141  v.align := '1';
142  v.rxMaster.tData := (others => '0');
143  end if;
144 
145  -- State Machine
146  case r.state is
147  ----------------------------------------------------------------------
148  when IDLE_S =>
149  -- Check for valid data
150  if r.rxMaster.tValid = '1' then
151  -- Reset the flags
152  v.dly(0).tValid := '0';
153  v.dly(1).tValid := '0';
154  -- Check for SOF header
155  if r.rxMaster.tData(31 downto 0) = SOF_C then
156  -- Set the flag
157  v.sof := '1';
158  v.eofe := '0';
159  -- Reset the counter
160  v.seqCnt := x"00";
161  -- Next state
162  v.state := LENGTH_S;
163  elsif (r.rxMaster.tData(31 downto 0) = SOC_C) and (r.eofe = '0') then
164  -- Increment the counter
165  v.seqCnt := r.seqCnt + 1;
166  -- Next state
167  v.state := LENGTH_S;
168  end if;
169  end if;
170  ----------------------------------------------------------------------
171  when LENGTH_S =>
172  -- Check for valid data
173  if r.rxMaster.tValid = '1' then
174  -- Latch the length and tDest
175  v.length := r.rxMaster.tData(15 downto 0);
176  v.tDest := r.rxMaster.tData(23 downto 16);
177  -- Update checksum
178  v.checksum := r.rxMaster.tData(31 downto 0);
179  -- Check for invalid lengths or invalid sequence counter
180  if (v.length = 0) or (v.length > SALT_MAX_WORDS_C) or (r.rxMaster.tData(31 downto 24) /= r.seqCnt) then
181  -- Set the error flag
182  v.eofe := '1';
183  -- Next state
184  v.state := IDLE_S;
185  else
186  -- Next state
187  v.state := MOVE_S;
188  end if;
189  end if;
190  ----------------------------------------------------------------------
191  when MOVE_S =>
192  -- Check for valid data
193  if (r.rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then
194  -- Move the delay data
195  v.txMaster.tValid := r.dly(1).tValid;
196  v.txMaster.tData := r.dly(1).tData;
197  v.dly(1).tValid := r.dly(0).tValid;
198  v.dly(1).tData := r.dly(0).tData;
199  -- Create the delayed data
200  v.dly(0).tValid := '1';
201  v.dly(0).tData(31 downto 0) := r.rxMaster.tData(31 downto 0);
202  -- Check for SOF bit
203  if r.sof = '1' then
204  -- Reset the flag
205  v.sof := '0';
206  -- Set the SOF bit
207  ssiSetUserSof(SSI_SALT_CONFIG_C, v.txMaster, '1');
208  end if;
209  -- Check the length
210  if r.cnt = r.length then
211  -- Reset the counter
212  v.cnt := (others => '0');
213  -- Next state
214  v.state := CHECKSUM_S;
215  else
216  -- Increment the counter
217  v.cnt := r.cnt + 1;
218  -- Update checksum
219  v.checksum := r.checksum + r.rxMaster.tData(31 downto 0);
220  end if;
221  end if;
222  ----------------------------------------------------------------------
223  when CHECKSUM_S =>
224  -- Check for valid checksum
225  if r.dly(0).tData(31 downto 0) = not(r.checksum) then
226  -- Next state
227  v.state := DONE_S;
228  else
229  -- Set the error flag
230  v.eofe := '1';
231  -- Next state
232  v.state := IDLE_S;
233  end if;
234  ----------------------------------------------------------------------
235  when DONE_S =>
236  -- Check for valid data
237  if (r.rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then
238  -- Move the delay data
239  v.txMaster.tValid := r.dly(1).tValid;
240  v.txMaster.tData := r.dly(1).tData;
241  -- Check for EOC footer
242  if r.rxMaster.tData(31 downto 0) = EOC_C then
243  -- No operation
244  null;
245  elsif r.rxMaster.tData(31 downto 0) = EOF_C then
246  -- Set EOF flag
247  v.txMaster.tLast := '1';
248  -- Set EOFE
249  ssiSetUserEofe(SSI_SALT_CONFIG_C, v.txMaster, r.eofe);
250  elsif r.rxMaster.tData(31 downto 0) = EOFE_C then
251  -- Set EOF flag
252  v.txMaster.tLast := '1';
253  -- Set EOFE
254  ssiSetUserEofe(SSI_SALT_CONFIG_C, v.txMaster, '1');
255  else
256  -- Set the error flag
257  v.eofe := '1';
258  end if;
259  -- Next state
260  v.state := IDLE_S;
261  end if;
262  ----------------------------------------------------------------------
263  end case;
264 
265  -- Check for GMII frame error
266  if (r.rxMaster.tValid = '1') and (r.rxMaster.tUser(SSI_EOFE_C) = '1') then
267  -- Set the error flag
268  v.eofe := '1';
269  end if;
270 
271  -- Overwrite the destination field
272  v.txMaster.tDest := r.tDest;
273 
274  -- Reset
275  if (rst = '1') then
276  v := REG_INIT_C;
277  end if;
278 
279  -- Register the variable for next clock cycle
280  rin <= v;
281 
282  -- Outputs
283  txMaster <= r.txMaster;
284 
285  end process comb;
286 
287  seq : process (clk) is
288  begin
289  if rising_edge(clk) then
290  r <= rin after TPD_G;
291  end if;
292  end process seq;
293 
294  FIFO_TX : entity work.SsiFifo
295  generic map (
296  -- General Configurations
297  TPD_G => TPD_G,
298  PIPE_STAGES_G => 0,
299  VALID_THOLD_G => 1,
300  EN_FRAME_FILTER_G => true,
301  -- FIFO configurations
302  BRAM_EN_G => true,
303  USE_BUILT_IN_G => false,
305  CASCADE_SIZE_G => 1,
306  FIFO_ADDR_WIDTH_G => 9,
307  -- AXI Stream Port Configurations
310  port map (
311  -- Slave Port
312  sAxisClk => clk,
313  sAxisRst => rst,
314  sAxisMaster => txMaster,
315  sAxisSlave => txSlave,
316  -- Master Port
317  mAxisClk => mAxisClk,
318  mAxisRst => mAxisRst,
320  mAxisSlave => mAxisSlave);
321 
322 end rtl;
in mAxisSlaveAxiStreamSlaveType
Definition: SaltRx.vhd:40
out mAxisMasterAxiStreamMasterType
Definition: SaltRx.vhd:39
in rxEnsl
Definition: SaltRx.vhd:42
sl sof
Definition: SsiPkg.vhd:72
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
out mAxisMasterAxiStreamMasterType
Definition: SsiFifo.vhd:69
integer := 0 SSI_EOFE_C
Definition: SsiPkg.vhd:30
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
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
Definition: SsiFifo.vhd:50
in rstsl
Definition: SaltRx.vhd:46
MASTER_AXI_CONFIG_GAxiStreamConfigType := ssiAxiStreamConfig( 4)
Definition: SaltRx.vhd:34
in clksl
Definition: SaltRx.vhd:45
in sAxisClksl
Definition: SsiFifo.vhd:58
in rxErrsl
Definition: SaltRx.vhd:43
GEN_SYNC_FIFO_Gboolean := false
Definition: SsiFifo.vhd:45
VALID_THOLD_Gnatural := 1
Definition: SsiFifo.vhd:39
_library_ ieeeieee
Definition: SaltPkg.vhd:18
slv( 31 downto 0) := x"DDDDDDDD" EOC_C
Definition: SaltPkg.vhd:35
slv( 127 downto 0) tData
in mAxisRstsl
Definition: SaltRx.vhd:38
in rxDataslv( 7 downto 0)
Definition: SaltRx.vhd:44
TPD_Gtime := 1 ns
Definition: SaltRx.vhd:32
in mAxisClksl
Definition: SsiFifo.vhd:67
BRAM_EN_Gboolean := true
Definition: SsiFifo.vhd:42
USE_BUILT_IN_Gboolean := false
Definition: SsiFifo.vhd:44
in sAxisRstsl
Definition: SsiFifo.vhd:59
slv( 127 downto 0) tUser
slv( 31 downto 0) := x"FFFFFFFF" EOFE_C
Definition: SaltPkg.vhd:37
TPD_Gtime := 1 ns
Definition: SsiFifo.vhd:33
array(natural range <> ) of AxiStreamMasterType AxiStreamMasterArray
in mAxisClksl
Definition: SaltRx.vhd:37
in mAxisSlaveAxiStreamSlaveType
Definition: SsiFifo.vhd:70
slv( 7 downto 0) tDest
EN_FRAME_FILTER_Gboolean := true
Definition: SsiFifo.vhd:37
slv( 31 downto 0) := x"BBBBBBBB" SOF_C
Definition: SaltPkg.vhd:33
SLAVE_AXI_CONFIG_GAxiStreamConfigType := SSI_CONFIG_INIT_C
Definition: SsiFifo.vhd:54
COMMON_RX_CLK_Gboolean := false
Definition: SaltRx.vhd:33
CASCADE_SIZE_Gpositive := 1
Definition: SsiFifo.vhd:48
PIPE_STAGES_Gnatural := 1
Definition: SsiFifo.vhd:35
MASTER_AXI_CONFIG_GAxiStreamConfigType := SSI_CONFIG_INIT_C
Definition: SsiFifo.vhd:55
in mAxisRstsl
Definition: SsiFifo.vhd:68
slv( 31 downto 0) := x"EEEEEEEE" EOF_C
Definition: SaltPkg.vhd:36
out sAxisSlaveAxiStreamSlaveType
Definition: SsiFifo.vhd:61
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
natural :=( 1500/ 4) SALT_MAX_WORDS_C
Definition: SaltPkg.vhd:30
in sAxisMasterAxiStreamMasterType
Definition: SsiFifo.vhd:60