AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
udp_clock_crossing_if.vhd
1 -- Signals crossing clock domain...
2 --
3 -- Dave Sankey, January 2013
4 
5 library ieee;
6 use ieee.std_logic_1164.all;
7 use ieee.numeric_std.all;
8 
10  generic(
11  BUFWIDTH: natural := 0
12  );
13  port (
14  mac_clk: in std_logic;
15  rst_macclk: in std_logic;
16 --
17  busy_125: in std_logic;
18  rx_read_buffer_125: in std_logic_vector(BUFWIDTH - 1 downto 0);
19  rx_req_send_125: in std_logic;
20  tx_write_buffer_125: in std_logic_vector(BUFWIDTH - 1 downto 0);
21  enable_125: out std_logic;
22  rarp_125: out std_logic;
23  rst_ipb_125: out std_logic;
24  rx_ram_sent: out std_logic;
25  tx_ram_written: out std_logic;
26  we_125: out std_logic;
27 --
28  ipb_clk: in std_logic;
29  rst_ipb: in std_logic;
30 --
31  enable: in std_logic;
32  pkt_done_read: in std_logic;
33  pkt_done_write: in std_logic;
34  RARP: in std_logic;
35  we: in std_logic;
36  busy: out std_logic;
37  pkt_rdy: out std_logic;
38  rx_read_buffer: out std_logic_vector(BUFWIDTH - 1 downto 0);
39  tx_write_buffer: out std_logic_vector(BUFWIDTH - 1 downto 0)
40  );
41 end udp_clock_crossing_if;
42 
43 architecture rtl of udp_clock_crossing_if is
44 
45  signal req_send_tff, busy_buf, busy_up_tff, busy_down_tff: std_logic;
46  signal enable_buf, rarp_buf, we_buf, rst_ipb_buf: std_logic_vector(1 downto 0);
47  signal req_send_buf, pkt_done_read_buf, pkt_done_write_buf, busy_up_buf,
48  busy_down_buf, pkt_done_r_tff, pkt_done_w_tff: std_logic_vector(2 downto 0);
49  signal rx_read_buf_buf, tx_write_buf_buf: std_logic_vector(BUFWIDTH - 1 downto 0);
50 
51  attribute KEEP: string;
52  attribute KEEP of busy_down_buf: signal is "TRUE";
53  attribute KEEP of busy_up_buf: signal is "TRUE";
54  attribute KEEP of enable_buf: signal is "TRUE";
55  attribute KEEP of pkt_done_read_buf: signal is "TRUE";
56  attribute KEEP of pkt_done_write_buf: signal is "TRUE";
57  attribute KEEP of rarp_buf: signal is "TRUE";
58  attribute KEEP of req_send_buf: signal is "TRUE";
59  attribute KEEP of rst_ipb_buf: signal is "TRUE";
60  attribute KEEP of rx_read_buf_buf: signal is "TRUE";
61  attribute KEEP of tx_write_buf_buf: signal is "TRUE";
62  attribute KEEP of we_buf: signal is "TRUE";
63 
64 begin
65 
66 -- clock domain crossing logic based on
67 -- http://sc.morganisms.net/2010/06/rtl-for-passing-pulse-across-clock-domains-in-vhdl/
68 -- assumption is that ipbus clock is significantly slower than ethernet mac clock
69 -- so that transitions in ipbus clock domain are always caught in mac clock domain
70 -- whereas toggle flip flops are used to ensure the reciprocal
71 -- but just to be safe do the same for pkt_done...
72 
73  enable_125 <= enable_buf(1);
74  rarp_125 <= rarp_buf(1);
75  we_125 <= we_buf(1);
76  rst_ipb_125 <= rst_ipb_buf(1);
77 
78 pkt_done_ipb_clk: process(ipb_clk)
79  begin
80  if rising_edge(ipb_clk) then
81  if rst_ipb = '1' then
82  pkt_done_r_tff <= "000";
83  pkt_done_w_tff <= "000";
84  else
85 -- infer a (delayed) toggle flip flop in source domain
86  pkt_done_r_tff <= pkt_done_r_tff(1 downto 0) & (pkt_done_r_tff(0) xor pkt_done_read);
87  pkt_done_w_tff <= pkt_done_w_tff(1 downto 0) & (pkt_done_w_tff(0) xor pkt_done_write);
88  end if;
89  end if;
90  end process;
91 
92 pkt_done_mac_clk: process(mac_clk)
93  begin
94  if rising_edge(mac_clk) then
95 -- rx_ram_sent and tx_ram_written only high for 1 tick...
96  rx_ram_sent <= pkt_done_read_buf(2) xor pkt_done_read_buf(1);
97  tx_ram_written <= pkt_done_write_buf(2) xor pkt_done_write_buf(1);
98 -- pick up delayed tff from ipbus domain
99  pkt_done_read_buf <= pkt_done_read_buf(1 downto 0) & pkt_done_r_tff(2);
100  pkt_done_write_buf <= pkt_done_write_buf(1 downto 0) & pkt_done_w_tff(2);
101  end if;
102  end process;
103 
104 req_send_mac_clk: process(mac_clk)
105  begin
106  if rising_edge(mac_clk) then
107  if rst_macclk = '1' then
108  req_send_tff <= '0';
109  else
110 -- infer a toggle flip flop in source domain
111  req_send_tff <= req_send_tff xor rx_req_send_125;
112  end if;
113  end if;
114  end process;
115 
116 req_send_buf_ipb_clk: process(ipb_clk)
117  begin
118  if rising_edge(ipb_clk) then
119  req_send_buf <= req_send_buf(1 downto 0) & req_send_tff;
120  end if;
121  end process;
122 
123 pkt_rdy_ipb_clk: process(ipb_clk)
124  variable pkt_rdy_buf: std_logic_vector(2 downto 0);
125  begin
126  if rising_edge(ipb_clk) then
127  if rst_ipb = '1' then
128  pkt_rdy_buf := (Others => '0');
129  elsif pkt_done_read = '1' then
130  pkt_rdy_buf := (Others => '0');
131  elsif (req_send_buf(2) xor req_send_buf(1)) = '1' then
132  pkt_rdy_buf := pkt_rdy_buf(1 downto 0) & '1';
133  else
134  pkt_rdy_buf := pkt_rdy_buf(1 downto 0) & pkt_rdy_buf(0);
135  end if;
136  pkt_rdy <= pkt_rdy_buf(2);
137  end if;
138  end process;
139 
140 enable_mac_clk: process(mac_clk)
141  begin
142  if rising_edge(mac_clk) then
143  enable_buf <= enable_buf(0) & enable;
144  end if;
145  end process;
146 
147 rarp_mac_clk: process(mac_clk)
148  begin
149  if rising_edge(mac_clk) then
150  rarp_buf <= rarp_buf(0) & RARP;
151  end if;
152  end process;
153 
154 we_mac_clk: process(mac_clk)
155  begin
156  if rising_edge(mac_clk) then
157  we_buf <= we_buf(0) & we;
158  end if;
159  end process;
160 
161 rst_ipb_mac_clk: process(mac_clk)
162  begin
163  if rising_edge(mac_clk) then
164  rst_ipb_buf <= rst_ipb_buf(0) & rst_ipb;
165  end if;
166  end process;
167 
168 busy_mac_clk: process(mac_clk)
169  begin
170  if rising_edge(mac_clk) then
171  if rst_macclk = '1' then
172  busy_up_tff <= '0';
173  busy_down_tff <= '0';
174  busy_buf <= '0';
175  else
176 -- infer toggle flip flops in source domain
177  busy_up_tff <= busy_up_tff xor (busy_125 and not busy_buf);
178  busy_down_tff <= busy_down_tff xor (busy_buf and not busy_125);
179  busy_buf <= busy_125;
180  end if;
181  end if;
182  end process;
183 
184 busy_up_down_ipb_clk: process(ipb_clk)
185  begin
186  if rising_edge(ipb_clk) then
187  busy_up_buf <= busy_up_buf(1 downto 0) & busy_up_tff;
188  busy_down_buf <= busy_down_buf(1 downto 0) & busy_down_tff;
189  end if;
190  end process;
191 
192 busy_ipb_clk: process(ipb_clk)
193  variable busy_buf: std_logic_vector(3 downto 0);
194  begin
195  if rising_edge(ipb_clk) then
196  if rst_ipb = '1' then
197  busy_buf := (Others => '0');
198  elsif pkt_done_write = '1' then
199  busy_buf := (Others => '1');
200  elsif (busy_up_buf(2) xor busy_up_buf(1)) = '1' then
201  busy_buf := (Others => '1');
202  end if;
203  busy <= busy_buf(3);
204  if (busy_down_buf(2) xor busy_down_buf(1)) = '1' then
205  busy_buf := busy_buf(2 downto 0) & '0';
206  else
207  busy_buf := busy_buf(2 downto 0) & busy_buf(0);
208  end if;
209  end if;
210  end process;
211 
212 rx_read_buffer_ipb_clk: process(ipb_clk)
213  begin
214  if rising_edge(ipb_clk) then
215  rx_read_buf_buf <= rx_read_buffer_125;
216  rx_read_buffer <= rx_read_buf_buf;
217  end if;
218  end process;
219 
220 tx_write_buffer_ipb_clk: process(ipb_clk)
221  begin
222  if rising_edge(ipb_clk) then
223  tx_write_buf_buf <= tx_write_buffer_125;
224  tx_write_buffer <= tx_write_buf_buf;
225  end if;
226  end process;
227 
228 end rtl;