AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
XGbEMAC.vhd
1 ----------------------------------------------------------------------------------
2 -- Company:
3 -- Engineer:
4 --
5 -- Create Date: 12:02:40 04/20/2013
6 -- Design Name:
7 -- Module Name: XGbEMAC - Behavioral
8 -- Project Name:
9 -- Target Devices:
10 -- Tool versions:
11 -- Description:
12 --
13 -- Dependencies:
14 --
15 -- Revision:
16 -- Revision 0.01 - File Created
17 -- Additional Comments:
18 -- RS is integrated into this MAC module already
19 -- this MAC only accepts ARP and IP4 packets
20 -- jumbo frame is supported, but if it's over 9KB, CRC is not efficeint any more
21 -- and if more than 32KB, you may run into clock correction problem unless you increase the IFG
22 ----------------------------------------------------------------------------------
23 library IEEE;
24 use IEEE.STD_LOGIC_1164.ALL;
25 use IEEE.STD_LOGIC_ARITH.ALL;
26 use IEEE.STD_LOGIC_UNSIGNED.ALL;
27 use IEEE.std_logic_misc.all;
28 
29 -- Uncomment the following library declaration if using
30 -- arithmetic functions with Signed or Unsigned values
31 --use IEEE.NUMERIC_STD.ALL;
32 
33 -- Uncomment the following library declaration if instantiating
34 -- any Xilinx primitives in this code.
35 library UNISIM;
36 use UNISIM.VComponents.all;
37 
38 entity XGbEMAC is
39  Port ( clk : in STD_LOGIC;
40  reset : in STD_LOGIC;
41  enTxJumboFrame : in STD_LOGIC;
42  enRxJumboFrame : in STD_LOGIC;
43  EmacPhyTxc : out STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
44  EmacPhyTxd : out STD_LOGIC_VECTOR (31 downto 0) := (others => '0');
45  PhyEmacRxc : in STD_LOGIC_VECTOR (3 downto 0);
46  PhyEmacRxd : in STD_LOGIC_VECTOR (31 downto 0);
47  ClientEmacTxd : in STD_LOGIC_VECTOR (31 downto 0);
48  ClientEmacTxdVld : in STD_LOGIC_VECTOR (3 downto 0);
49  ClientEmacTxUnderrun : in STD_LOGIC;
50  EmacClientTack : out STD_LOGIC := '0';
51  EmacClientRxd : out STD_LOGIC_VECTOR (31 downto 0) := (others => '0');
52  EmacClientRxdWe : out STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
53  EmacClientRxGoodFrame : out STD_LOGIC := '0';
54  EmacClientRxbadFrame : out STD_LOGIC := '0'
55  );
56 end XGbEMAC;
57 
58 architecture Behavioral of XGbEMAC is
59 COMPONENT EthernetCRCD32
60  PORT(
61  clk : IN std_logic;
62  init : IN std_logic;
63  ce : IN std_logic;
64  d : IN std_logic_vector(31 downto 0);
65  byte_cnt : IN std_logic_vector(1 downto 0);
66  crc : OUT std_logic_vector(31 downto 0);
67  bad_crc : OUT std_logic
68  );
69 END COMPONENT;
70 COMPONENT link_status
71  PORT(
72  clk : IN std_logic;
73  reset : IN std_logic;
74  Rxc : IN std_logic_vector(3 downto 0);
75  Rxd : IN std_logic_vector(31 downto 0);
76  link_fault : OUT std_logic_vector(1 downto 0)
77  );
78 END COMPONENT;
79 type array13X32 is array(0 to 12) of bit_vector(31 downto 0);
80 constant Tx_const_INIT : array13X32 := (x"0000fff0",x"ffff00fe",x"ffffff0e",x"0000ff0c",x"0000ff0e",
81  x"ffffff0c",x"ffff00fc",x"0000fffe",x"0000ff02",x"00000002",x"fffffffc",x"000000fc",x"fffffffe");
82 signal Tx_ack : std_logic := '0';
83 signal Tx_busy : std_logic := '0';
84 signal init_tx_crc : std_logic := '0';
85 signal padding : std_logic := '0';
86 signal ce_tx_crc : std_logic := '0';
87 signal ce_tx_crc_q : std_logic_vector(1 downto 0) := (others => '0');
88 signal TxErr : std_logic := '0';
89 signal TxOverrun : std_logic := '0';
90 signal TxUnderrun : std_logic := '0';
91 signal SendStop : std_logic := '0';
92 signal SendIdle : std_logic := '0';
93 signal SendIdle_q : std_logic := '0';
94 signal Tx_const_do : std_logic_vector(12 downto 0) := (others => '0');
95 signal Tx_const : std_logic_vector(36 downto 0) := (others => '0');
96 signal Txd_wc : std_logic_vector(4 downto 0) := (others => '0');
97 signal TxFrame_wc : std_logic_vector(9 downto 0) := (others => '0');
98 signal Txd_ByteCnt : std_logic_vector(1 downto 0) := (others => '0');
99 signal Txd : std_logic_vector(31 downto 0) := (others => '0');
100 signal Txd_q : std_logic_vector(31 downto 0) := (others => '0');
101 signal Txd_ByteCnt_q : std_logic_vector(1 downto 0) := (others => '0');
102 signal Txd_ByteCnt_q2 : std_logic_vector(1 downto 0) := (others => '0');
103 signal tx_crc : std_logic_vector(31 downto 0) := (others => '0');
104 signal Rx_start : std_logic := '0';
105 signal Rx_SFD : std_logic := '0';
106 signal Receive : std_logic := '0';
107 signal CtrlErr : std_logic := '0';
108 signal TypeErr : std_logic := '0';
109 signal init_rx_crc : std_logic := '0';
110 signal ce_rx_crc : std_logic := '0';
111 signal bad_rx_crc : std_logic := '0';
112 signal check_rx_crc : std_logic := '0';
113 signal Rxd_ByteCnt : std_logic_vector(1 downto 0) := (others => '0');
114 signal Rxd : std_logic_vector(31 downto 0) := (others => '0');
115 signal Rxd_net : std_logic_vector(31 downto 0) := (others => '0');
116 signal link_fault : std_logic_vector(1 downto 0) := (others => '0');
117 signal Rxd_wc : std_logic_vector(4 downto 0) := (others => '0');
118 signal RxFrame_wc : std_logic_vector(9 downto 0) := (others => '0');
119 begin
120 -- Tx logic
121 process(clk)
122 begin
123  if(clk'event and clk = '1')then
124  EmacClientTack <= Tx_ack and not reset;
125  SendIdle_q <= SendIdle;
126 -- IFG is quaranteed to be more than 12 bytes
127  Tx_ack <= not reset and ClientEmacTxdVld(3) and not Tx_busy and not link_fault(1) and not link_fault(0) and SendIdle and SendIdle_q;
128  if(reset = '1')then
129  Tx_busy <= '0';
130  elsif(ClientEmacTxdVld(3) = '1' and link_fault = "00" and SendIdle = '1' and SendIdle_q = '1')then
131  Tx_busy <= '1';
132  elsif(SendStop = '1' or (ce_tx_crc_q = "10" and Txd_ByteCnt_q2 /= "00"))then
133  Tx_busy <= '0';
134  end if;
135 -- minimum Ethernet length is 64 bytes
136  if(reset = '1')then
137  Txd_wc <= (others => '0');
138  elsif(Tx_ack = '1')then
139  Txd_wc <= "10001";
140  elsif(Txd_wc(4) = '1')then
141  Txd_wc <= Txd_wc + 1;
142  end if;
143 -- maximum Ethernet length is 1522 bytes
144  if(reset = '1' or enTxJumboFrame = '1' or SendIdle = '1')then
145  TxFrame_wc <= "00" & x"84";
146  elsif(ClientEmacTxdVld(1) = '1' and TxFrame_wc(9) = '0')then
147  TxFrame_wc <= TxFrame_wc + 1;
148  end if;
149  if(SendIdle = '1')then
150  padding <= '0';
151  elsif(Txd_wc(4) = '1' and ClientEmacTxdVld(0) = '0')then
152  padding <= '1';
153  end if;
154 -- convert byte order from computer to network
155  if(Txd_wc(4) = '1')then
156  Txd_ByteCnt <= "00";
157  for i in 0 to 3 loop
158  if(padding = '1' or ClientEmacTxdVld(i) = '0')then
159  Txd(31-i*8 downto 24-i*8) <= (others => '0');
160  else
161  Txd(31-i*8 downto 24-i*8) <= ClientEmacTxd(i*8+7 downto i*8);
162  end if;
163  end loop;
164  else
165  case ClientEmacTxdVld is
166  when x"f" | x"0" => Txd_ByteCnt <= "00";
167  when x"8" => Txd_ByteCnt <= "01";
168  when x"c" => Txd_ByteCnt <= "10";
169  when others => Txd_ByteCnt <= "11";
170  end case;
171  Txd <= ClientEmacTxd(7 downto 0) & ClientEmacTxd(15 downto 8) & ClientEmacTxd(23 downto 16) & ClientEmacTxd(31 downto 24);
172  end if;
173  if(ClientEmacTxUnderrun = '1' or (ClientEmacTxdVld(1) = '1' and and_reduce(TxFrame_wc(8 downto 0)) = '1'))then
174  Txd(7 downto 0) <= x"fe";
175  end if;
176  if(reset = '1')then
177  ce_tx_crc <= '0';
178  elsif(Txd_wc(4) = '1')then
179  ce_tx_crc <= '1';
180  elsif(ClientEmacTxdVld(3) = '0' or TxOverrun = '1'or padding = '1')then
181  ce_tx_crc <= '0';
182  end if;
183  init_tx_crc <= Tx_ack;
184  if((reset = '0' and Txd_ByteCnt_q = "00" and ce_tx_crc_q(0) = '1' and ce_tx_crc = '0' and TxFrame_wc(9) = '0') or TxOverrun = '1')then
185  SendStop <= '1';
186  else
187  SendStop <= '0';
188  end if;
189  if(reset = '1' or link_fault(1) = '1' or SendStop = '1' or (ce_tx_crc_q(0) = '1' and ce_tx_crc = '0' and Txd_ByteCnt_q /= "00"))then
190  SendIdle <= '1';
191  elsif(tx_ack = '1')then
192  SendIdle <= '0';
193  end if;
194  ce_tx_crc_q <= ce_tx_crc_q(0) & ce_tx_crc;
195  Txd_q <= Txd;
196  Txd_ByteCnt_q <= Txd_ByteCnt;
197  Txd_ByteCnt_q2 <= Txd_ByteCnt_q;
198  Tx_const(36) <= Tx_const_do(12);
199  Tx_const(35 downto 32) <= Tx_const_do(11) & Tx_const_do(11) & Tx_const_do(11) & Tx_const_do(10);
200  Tx_const(31 downto 28) <= Tx_const_do(9) & Tx_const_do(8) & '0' & Tx_const_do(8);
201  Tx_const(27 downto 24) <= '0' & Tx_const_do(7) & Tx_const_do(6) & Tx_const_do(7);
202  Tx_const(23 downto 20) <= '0' & Tx_const_do(8) & '0' & Tx_const_do(8);
203  Tx_const(19 downto 16) <= '0' & Tx_const_do(7) & Tx_const_do(11) & Tx_const_do(7);
204  Tx_const(15 downto 12) <= '0' & Tx_const_do(8) & '0' & Tx_const_do(8);
205  Tx_const(11 downto 8) <= '0' & Tx_const_do(7) & Tx_const_do(11) & Tx_const_do(7);
206  Tx_const(7 downto 4) <= Tx_const_do(5) & Tx_const_do(4) & Tx_const_do(3) & Tx_const_do(2);
207  Tx_const(3 downto 0) <= Tx_const_do(5) & Tx_const_do(1) & Tx_const_do(0) & Tx_const_do(7);
208  if(Tx_const(36) = '1')then
209  EmacPhyTxc <= Tx_const(35 downto 32);
210  EmacPhyTxd <= Tx_const(31 downto 0);
211  elsif(ce_tx_crc_q(0) = '1')then
212  EmacPhyTxc <= x"0";
213  case Txd_ByteCnt_q is
214  when "00" => EmacPhyTxd <= Txd_q;
215  when "01" => EmacPhyTxd <= tx_crc(23 downto 0) & Txd_q(7 downto 0);
216  when "10" => EmacPhyTxd <= tx_crc(15 downto 0) & Txd_q(15 downto 0);
217  when others => EmacPhyTxd <= tx_crc(7 downto 0) & Txd_q(23 downto 0);
218  end case;
219  else
220  case Txd_ByteCnt_q2 is
221  when "00" =>
222  EmacPhyTxc <= x"0";
223  EmacPhyTxd <= tx_crc;
224  when "01" =>
225  EmacPhyTxc <= x"e";
226  EmacPhyTxd <= x"0707fd" & tx_crc(31 downto 24);
227  when "10" =>
228  EmacPhyTxc <= x"c";
229  EmacPhyTxd <= x"07fd" & tx_crc(31 downto 16);
230  when others =>
231  EmacPhyTxc <= x"8";
232  EmacPhyTxd <= x"fd" & tx_crc(31 downto 8);
233  end case;
234  end if;
235  if(ClientEmacTxUnderrun = '1')then
236  TxUnderrun <= '1';
237  else
238  TxUnderrun <= '0';
239  end if;
240  if(ClientEmacTxdVld(1) = '1' and and_reduce(TxFrame_wc(8 downto 0)) = '1')then
241  TxOverrun <= '1';
242  else
243  TxOverrun <= '0';
244  end if;
245  TxErr <= TxUnderrun or TxOverrun;
246  if(TxErr = '1')then
247  EmacPhyTxc(0) <= '1';
248  end if;
249  end if;
250 end process;
251 i_tx_CRC: EthernetCRCD32 PORT MAP(
252  clk => clk,
253  init => init_tx_crc,
254  ce => ce_tx_crc,
255  d => Txd,
256  byte_cnt => Txd_ByteCnt,
257  crc => tx_crc ,
258  bad_crc => open
259  );
260 g_Tx_const : for i in 0 to 12 generate
261  i_Tx_const : ROM32X1
262  generic map (
263  INIT => Tx_const_INIT(i))
264  port map (
265  O => Tx_const_do(i), -- ROM output
266  A0 => init_tx_crc, -- ROM address[0] send SFD x"0d5555555"
267  A1 => SendStop, -- ROM address[1] Send stop control x"f070707fd";
268  A2 => SendIdle, -- ROM address[2] send idle x"f07070707"
269  A3 => Tx_ack, -- ROM address[3] send start control x"1555555fb"
270  A4 => link_fault(0) -- ROM address[4] send remote_fault x"10200009c"
271  );
272 end generate;
273 -- Rx logic
274 Rxd <= Rxd_net(7 downto 0) & Rxd_net(15 downto 8) & Rxd_net(23 downto 16) & Rxd_net(31 downto 24);
275 process(clk)
276 begin
277  if(clk'event and clk = '1')then
278  Rxd_net <= PhyEmacRxd;
279  EmacClientRxd <= Rxd;
280  if(reset = '0' and PhyEmacRxc = x"1" and PhyEmacRxd = x"555555fb")then
281  Rx_start <= '1';
282  else
283  Rx_start <= '0';
284  end if;
285  if(reset = '0' and Rx_start = '1' and PhyEmacRxc = x"0" and PhyEmacRxd = x"d5555555")then
286  Rx_SFD <= '1';
287  else
288  Rx_SFD <= '0';
289  end if;
290  if(reset = '1' or PhyEmacRxc = x"f" or RxFrame_wc(9) = '1')then
291  ce_rx_crc <= '0';
292  elsif(init_rx_crc = '1')then
293  ce_rx_crc <= '1';
294  end if;
295  if(reset = '0' and (PhyEmacRxc = x"f" or RxFrame_wc(9) = '1') and ce_rx_crc = '1')then
296  check_rx_crc <= '1';
297  else
298  check_rx_crc <= '0';
299  end if;
300  if(check_rx_crc = '1' and reset = '0')then
301  EmacClientRxGoodFrame <= not (bad_rx_crc or CtrlErr or not Rxd_wc(4) or TypeErr or RxFrame_wc(9));
302  EmacClientRxBadFrame <= bad_rx_crc or CtrlErr or not Rxd_wc(4) or TypeErr or RxFrame_wc(9);
303  else
304  EmacClientRxGoodFrame <= '0';
305  EmacClientRxBadFrame <= '0';
306  end if;
307  case PhyEmacRxc is
308  when x"e" => Rxd_ByteCnt <= "01";
309  when x"c" => Rxd_ByteCnt <= "10";
310  when x"8" => Rxd_ByteCnt <= "11";
311  when others => Rxd_ByteCnt <= "00";
312  end case;
313  if(reset = '1' or PhyEmacRxc(3) = '1')then
314  Receive <= '0';
315  elsif(Rx_SFD = '1')then
316  Receive <= '1';
317  end if;
318  if(reset = '1')then
319  EmacClientRxdWe <= x"0";
320  elsif(ce_rx_crc = '1')then
321  EmacClientRxdWe(0) <= not or_reduce(PhyEmacRxc);
322  EmacClientRxdWe(1) <= not or_reduce(PhyEmacRxc(2 downto 0));
323  EmacClientRxdWe(2) <= not or_reduce(PhyEmacRxc(1 downto 0));
324  EmacClientRxdWe(3) <= not PhyEmacRxc(0);
325  else
326  EmacClientRxdWe <= x"0";
327  end if;
328  if(reset = '1' or Rx_SFD = '1')then
329  CtrlErr <= '0';
330  elsif(Receive = '1')then
331  if(PhyEmacRxc(0) = '1')then
332  if(PhyEmacRxd(7 downto 0) /= x"fd")then
333  CtrlErr <= '1';
334  end if;
335  elsif(PhyEmacRxc(1) = '1')then
336  if(PhyEmacRxd(15 downto 8) /= x"fd")then
337  CtrlErr <= '1';
338  end if;
339  elsif(PhyEmacRxc(2) = '1')then
340  if(PhyEmacRxd(23 downto 16) /= x"fd")then
341  CtrlErr <= '1';
342  end if;
343  elsif(PhyEmacRxc(3) = '1')then
344  if(PhyEmacRxd(31 downto 24) /= x"fd")then
345  CtrlErr <= '1';
346  end if;
347  end if;
348  end if;
349  if(Rxd_wc(3 downto 0) = x"4")then
350  if(Rxd(31 downto 16) = x"0800" or Rxd(31 downto 16) = x"0806")then
351  TypeErr <= '0';
352  else
353  TypeErr <= '1';
354  end if;
355  end if;
356 -- minimum Ethernet length is 64 bytes
357  if(reset = '1' or Rx_start = '1')then
358  Rxd_wc <= (others => '0');
359  elsif(Rxd_wc(4) = '0' and PhyEmacRxc(3) = '0')then
360  Rxd_wc <= Rxd_wc + 1;
361  end if;
362 -- maximum Ethernet length is 1522 bytes
363  if(reset = '1' or enRxJumboFrame = '1' or Receive = '0')then
364  RxFrame_wc <= "00" & x"84";
365  elsif(PhyEmacRxc(2) = '0' and RxFrame_wc(9) = '0')then
366  RxFrame_wc <= RxFrame_wc + 1;
367  end if;
368  end if;
369 end process;
370 i_rx_CRC: EthernetCRCD32 PORT MAP(
371  clk => clk,
372  init => init_rx_crc,
373  ce => ce_rx_crc,
374  d => Rxd_net,
375  byte_cnt => Rxd_ByteCnt,
376  crc => open,
377  bad_crc => bad_rx_crc
378  );
379 init_rx_crc <= Rx_SFD;
380 i_link_status: link_status PORT MAP(
381  clk => clk,
382  reset => reset,
383  Rxc => PhyEmacRxc,
384  Rxd => PhyEmacRxd,
385  link_fault => link_fault
386  );
387 end Behavioral;
388