SURF  1.0
RawEthFramerTx.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : RawEthFramerTx.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2016-05-23
5 -- Last update: 2016-05-26
6 -------------------------------------------------------------------------------
7 -- Description: Raw L2 Ethernet Framer's TX Engine
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.RawEthFramerPkg.all;
27 
28 --! @see entity
29  --! @ingroup ethernet_RawEthFramer
30 entity RawEthFramerTx is
31  generic (
32  TPD_G : time := 1 ns;
33  ETH_TYPE_G : slv(15 downto 0) := x"0010"); -- 0x1000 (big-Endian configuration)
34  port (
35  -- Local Configurations
36  localMac : in slv(47 downto 0); -- big-Endian configuration
37  remoteMac : in slv(47 downto 0); -- big-Endian configuration
38  tDest : out slv(7 downto 0);
39  req : out sl;
40  ack : in sl;
41  -- Interface to Ethernet Media Access Controller (MAC)
44  -- Interface to Application engine(s)
47  -- Clock and Reset
48  clk : in sl;
49  rst : in sl);
50 end RawEthFramerTx;
51 
52 architecture rtl of RawEthFramerTx is
53 
54  type StateType is (
55  IDLE_S,
56  TDEST_S,
57  CACHE_S,
58  MOVE_S);
59 
60  type RegType is record
61  bcf : sl;
62  req : sl;
63  tDest : slv(7 downto 0);
64  wen : sl;
65  wrAddr : slv(2 downto 0);
66  wrData : slv(63 downto 0);
67  rdAddr : slv(15 downto 0);
68  minByteCnt : natural range 0 to 64;
69  eof : sl;
70  eofe : sl;
73  state : StateType;
74  end record RegType;
75  constant REG_INIT_C : RegType := (
76  bcf => '0',
77  req => '0',
78  tDest => (others => '0'),
79  wen => '0',
80  wrAddr => (others => '0'),
81  wrData => (others => '0'),
82  rdAddr => (others => '0'),
83  minByteCnt => 0,
84  eof => '0',
85  eofe => '0',
88  state => IDLE_S);
89 
90  signal r : RegType := REG_INIT_C;
91  signal rin : RegType;
92 
93  signal rdData : slv(63 downto 0);
94 
95  -- attribute dont_touch : string;
96  -- attribute dont_touch of r : signal is "TRUE";
97  -- attribute dont_touch of rdData : signal is "TRUE";
98 
99 begin
100 
101  U_MinEthCache : entity work.QuadPortRam
102  generic map (
103  TPD_G => TPD_G,
104  REG_EN_G => false, -- 1 cycle read
105  DATA_WIDTH_G => 64,
106  ADDR_WIDTH_G => 3)
107  port map (
108  -- Port A (Read/Write)
109  clka => clk,
110  wea => r.wen,
111  addra => r.wrAddr,
112  dina => r.wrData,
113  -- Port B (Read Only)
114  clkb => clk,
115  addrb => r.rdAddr(2 downto 0),
116  doutb => rdData);
117 
118  comb : process (ack, ibMacSlave, localMac, obAppMaster, r, rdData, remoteMac, rst) is
119  variable v : RegType;
120  variable i : natural;
121  variable tKeep : slv(15 downto 0);
122  begin
123  -- Latch the current value
124  v := r;
125 
126  -- Reset the flags
127  v.wen := '0';
129  if ibMacSlave.tReady = '1' then
130  v.ibMacMaster.tValid := '0';
131  v.ibMacMaster.tLast := '0';
132  v.ibMacMaster.tUser := (others => '0');
133  v.ibMacMaster.tKeep := x"00FF";
134  end if;
135 
136  -- Update variables
137  tKeep := x"00" & obAppMaster.tKeep(7 downto 0);
138 
139  -- State Machine
140  case r.state is
141  ----------------------------------------------------------------------
142  when IDLE_S =>
143  -- Check if ready to move data
144  if (obAppMaster.tValid = '1') and (v.ibMacMaster.tValid = '0') then
145  -- Check for SOF
146  if (ssiGetUserSof(RAW_ETH_CONFIG_INIT_C, obAppMaster) = '1') then
147  -- Latch the routing information
148  v.bcf := ssiGetUserBcf(RAW_ETH_CONFIG_INIT_C, obAppMaster);
149  v.tDest := obAppMaster.tDest;
150  -- Set the flag
151  v.req := not(v.bcf);
152  -- Next state
153  v.state := TDEST_S;
154  else
155  -- Accept the data
156  v.obAppSlave.tReady := '1';
157  end if;
158  end if;
159  ----------------------------------------------------------------------
160  when TDEST_S =>
161  if (ack = '1') or (r.bcf = '1') then
162  -- Accept the data
163  v.obAppSlave.tReady := '1';
164  -- Reset the flag
165  v.req := '0';
166  -- Check for valid DST MAC or broadcast
167  if (remoteMac /= 0) or (r.bcf = '1') then
168  -- Write to cache
169  v.wen := '1';
170  v.wrAddr := toSlv(2, 3);
171  for i in 7 downto 0 loop
172  if tKeep(i) = '1' then
173  v.wrData(7+(8*i) downto (8*i)) := obAppMaster.tData(7+(8*i) downto (8*i));
174  else
175  v.wrData(7+(8*i) downto (8*i)) := x"00"; -- zero padding
176  end if;
177  end loop;
178  -- Update the min. ETH Byte counter
179  v.minByteCnt := 16 + getTKeep(tKeep); -- include header offset
180  -- Check for tLast
181  if obAppMaster.tLast = '1' then
182  -- Set EOF
183  v.eof := '1';
184  -- Get EOFE
185  v.eofe := ssiGetUserEofe(RAW_ETH_CONFIG_INIT_C, obAppMaster);
186  -- Next state
187  v.state := MOVE_S;
188  else
189  -- Next state
190  v.state := CACHE_S;
191  end if;
192  ------------------
193  -- Write HDR[0] --
194  ------------------
195  -- Set the SOF
196  ssiSetUserSof(RAW_ETH_CONFIG_INIT_C, v.ibMacMaster, '1');
197  -- Move the data
198  v.ibMacMaster.tValid := '1';
199  -- Check for broadcast message
200  if (r.bcf = '1') then
201  v.ibMacMaster.tData(47 downto 0) := (others => '1');
202  else
203  v.ibMacMaster.tData(47 downto 0) := remoteMac;
204  end if;
205  v.ibMacMaster.tData(63 downto 48) := localMac(15 downto 0);
206  -- Preset the address
207  v.rdAddr := toSlv(1, 16);
208  else
209  -- Next state
210  v.state := IDLE_S;
211  end if;
212  end if;
213  ----------------------------------------------------------------------
214  when CACHE_S =>
215  -- Check if ready to move data
216  if (obAppMaster.tValid = '1') and (v.ibMacMaster.tValid = '0') then
217  -- Accept the data
218  v.obAppSlave.tReady := '1';
219  -- Write to cache
220  v.wen := '1';
221  v.wrAddr := r.wrAddr + 1;
222  for i in 7 downto 0 loop
223  if tKeep(i) = '1' then
224  v.wrData(7+(8*i) downto (8*i)) := obAppMaster.tData(7+(8*i) downto (8*i));
225  else
226  v.wrData(7+(8*i) downto (8*i)) := x"00"; -- zero padding
227  end if;
228  end loop;
229  -- Update the min. ETH Byte counter
230  v.minByteCnt := r.minByteCnt + getTKeep(tKeep);
231  -- Check for tLast
232  if obAppMaster.tLast = '1' then
233  -- Set EOF
234  v.eof := '1';
235  -- Get EOFE
236  v.eofe := ssiGetUserEofe(RAW_ETH_CONFIG_INIT_C, obAppMaster);
237  -- Next state
238  v.state := MOVE_S;
239  elsif r.wrAddr = 6 then
240  -- Reset EOF
241  v.eof := '0';
242  -- Next state
243  v.state := MOVE_S;
244  end if;
245  -- Check if next state is MOVE_S
246  if v.state = MOVE_S then
247  ------------------
248  -- Write HDR[1] --
249  ------------------
250  -- Move the data
251  v.ibMacMaster.tValid := '1';
252  v.ibMacMaster.tData(31 downto 0) := localMac(47 downto 16);
253  v.ibMacMaster.tData(47 downto 32) := ETH_TYPE_G;
254  -- Check for eof during caching
255  if v.eof = '0' then
256  v.ibMacMaster.tData(54 downto 48) := (others => '0');
257  else
258  v.ibMacMaster.tData(54 downto 48) := toSlv(v.minByteCnt, 7);
259  end if;
260  -- Check for broadcast message
261  if (r.bcf = '1') then
262  v.ibMacMaster.tData(63 downto 55) := (others => '1');
263  else
264  v.ibMacMaster.tData(63 downto 55) := r.tDest & '0';
265  end if;
266  -- Preset the address
267  v.rdAddr := toSlv(2, 16);
268  end if;
269  end if;
270  ----------------------------------------------------------------------
271  when MOVE_S =>
272  -- Check if ready to move data
273  if (v.ibMacMaster.tValid = '0') then
274  -- Increment the counter
275  v.rdAddr := r.rdAddr + 1;
276  -- Check for HDR[1]
277  if r.rdAddr = 1 then
278  -- Move the data
279  v.ibMacMaster.tValid := '1';
280  v.ibMacMaster.tData(31 downto 0) := localMac(47 downto 16);
281  v.ibMacMaster.tData(47 downto 32) := ETH_TYPE_G;
282  -- Check for eof during caching
283  if r.eof = '0' then
284  v.ibMacMaster.tData(54 downto 48) := (others => '0');
285  else
286  v.ibMacMaster.tData(54 downto 48) := toSlv(r.minByteCnt, 7);
287  end if;
288  -- Check for broadcast message
289  if (r.bcf = '1') then
290  v.ibMacMaster.tData(63 downto 55) := (others => '1');
291  else
292  v.ibMacMaster.tData(63 downto 55) := r.tDest & '0';
293  end if;
294  elsif r.rdAddr(15 downto 3) = 0 then
295  -- Move the data
296  v.ibMacMaster.tValid := '1';
297  v.ibMacMaster.tData(63 downto 0) := rdData;
298  -- Check for eof during caching
299  if r.eof = '1' then
300  -- Check for last transfer
301  if r.rdAddr(2 downto 0) = r.wrAddr then
302  -- Set EOF
303  v.ibMacMaster.tLast := '1';
304  -- Set the EOFE
305  ssiSetUserEofe(RAW_ETH_CONFIG_INIT_C, v.ibMacMaster, r.eofe);
306  -- Next state
307  v.state := IDLE_S;
308  end if;
309  end if;
310  elsif (obAppMaster.tValid = '1') then
311  -- Accept the data
312  v.obAppSlave.tReady := '1';
313  -- Move the data
314  v.ibMacMaster.tValid := '1';
315  v.ibMacMaster.tData(63 downto 0) := obAppMaster.tData(63 downto 0);
316  v.ibMacMaster.tKeep(7 downto 0) := obAppMaster.tKeep(7 downto 0);
317  -- Check for tLast
318  if obAppMaster.tLast = '1' then
319  -- Set EOF
320  v.ibMacMaster.tLast := '1';
321  -- Get the EOFE
322  v.eofe := ssiGetUserEofe(RAW_ETH_CONFIG_INIT_C, obAppMaster);
323  -- Set the EOFE
324  ssiSetUserEofe(RAW_ETH_CONFIG_INIT_C, v.ibMacMaster, v.eofe);
325  -- Next state
326  v.state := IDLE_S;
327  end if;
328  end if;
329  end if;
330  ----------------------------------------------------------------------
331  end case;
332 
333  -- Reset
334  if (rst = '1') then
335  v := REG_INIT_C;
336  end if;
337 
338  -- Register the variable for next clock cycle
339  rin <= v;
340 
341  -- Outputs
342  obAppSlave <= v.obAppSlave;
344  tDest <= v.tDest;
345  req <= v.req;
346 
347  end process comb;
348 
349  seq : process (clk) is
350  begin
351  if rising_edge(clk) then
352  r <= rin after TPD_G;
353  end if;
354  end process seq;
355 
356 end rtl;
in weasl := '0'
Definition: QuadPortRam.vhd:42
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:46
AxiStreamConfigType := ssiAxiStreamConfig( 8, TKEEP_COMP_C, TUSER_FIRST_LAST_C, 8, 3) RAW_ETH_CONFIG_INIT_C
in clkasl := '0'
Definition: QuadPortRam.vhd:40
_library_ ieeeieee
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
sl eofe
Definition: SsiPkg.vhd:74
out ibMacMasterAxiStreamMasterType
slv( 15 downto 0) tKeep
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
Definition: QuadPortRam.vhd:36
ETH_TYPE_Gslv( 15 downto 0) := x"0010"
TPD_Gtime := 1 ns
in remoteMacslv( 47 downto 0)
TPD_Gtime := 1 ns
Definition: QuadPortRam.vhd:29
slv( 127 downto 0) tData
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:45
out tDestslv( 7 downto 0)
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
out doutbslv( DATA_WIDTH_G- 1 downto 0)
Definition: QuadPortRam.vhd:53
slv( 127 downto 0) tUser
out obAppSlaveAxiStreamSlaveType
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:52
in ibMacSlaveAxiStreamSlaveType
sl eof
Definition: SsiPkg.vhd:73
REG_EN_Gboolean := true
Definition: QuadPortRam.vhd:31
in obAppMasterAxiStreamMasterType
in clkbsl := '0'
Definition: QuadPortRam.vhd:49
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
Definition: QuadPortRam.vhd:34
in localMacslv( 47 downto 0)
std_logic_vector slv
Definition: StdRtlPkg.vhd:29