1 |
145 |
lanttu |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Title : Control registers
|
3 |
|
|
-- Project : UDP2HIBI
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- File : ctrl_regs.vhd
|
6 |
|
|
-- Author : Jussi Nieminen
|
7 |
|
|
-- Last update: 2012-03-22
|
8 |
|
|
-- Platform :
|
9 |
|
|
-------------------------------------------------------------------------------
|
10 |
|
|
-- Description: Keep track of current sender and update a table with receiver
|
11 |
|
|
-- information.
|
12 |
|
|
-- Only 1 tx (fpga -> outside world) at a time,
|
13 |
|
|
-- but generic number of rx-operations.
|
14 |
|
|
--
|
15 |
|
|
-- ES 2012-03-22: Check if there is a bug in table_valid.
|
16 |
|
|
-- That note is marked with "!!!", approx. at line 229
|
17 |
|
|
--
|
18 |
|
|
-------------------------------------------------------------------------------
|
19 |
|
|
-- Revisions :
|
20 |
|
|
-- Date Version Author Description
|
21 |
|
|
-- 2009/12/08 1.0 niemin95 Created
|
22 |
|
|
-------------------------------------------------------------------------------
|
23 |
|
|
|
24 |
|
|
library ieee;
|
25 |
|
|
use ieee.std_logic_1164.all;
|
26 |
|
|
use work.udp2hibi_pkg.all;
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
entity ctrl_regs is
|
30 |
|
|
|
31 |
|
|
generic (
|
32 |
|
|
receiver_table_size_g : integer := 4;
|
33 |
|
|
hibi_addr_width_g : integer := 32
|
34 |
|
|
);
|
35 |
|
|
|
36 |
|
|
port (
|
37 |
|
|
clk : in std_logic;
|
38 |
|
|
rst_n : in std_logic;
|
39 |
|
|
|
40 |
|
|
-- from hibi_receiver, new configurations
|
41 |
|
|
release_lock_in : in std_logic;
|
42 |
|
|
new_tx_conf_in : in std_logic;
|
43 |
|
|
new_rx_conf_in : in std_logic;
|
44 |
|
|
ip_in : in std_logic_vector( ip_addr_w_c-1 downto 0 );
|
45 |
|
|
dest_port_in : in std_logic_vector( udp_port_w_c-1 downto 0 );
|
46 |
|
|
source_port_in : in std_logic_vector( udp_port_w_c-1 downto 0 );
|
47 |
|
|
lock_addr_in : in std_logic_vector( hibi_addr_width_g-1 downto 0 );
|
48 |
|
|
response_addr_in : in std_logic_vector( hibi_addr_width_g-1 downto 0 );
|
49 |
|
|
lock_out : out std_logic;
|
50 |
|
|
lock_addr_out : out std_logic_vector( hibi_addr_width_g-1 downto 0 );
|
51 |
|
|
|
52 |
|
|
-- to tx_ctrl, config params for sending
|
53 |
|
|
tx_ip_out : out std_logic_vector( ip_addr_w_c-1 downto 0 );
|
54 |
|
|
tx_dest_port_out : out std_logic_vector( udp_port_w_c-1 downto 0 );
|
55 |
|
|
tx_source_port_out : out std_logic_vector( udp_port_w_c-1 downto 0 );
|
56 |
|
|
timeout_release_in : in std_logic;
|
57 |
|
|
|
58 |
|
|
-- from rx_ctrl, params of the received ip packet
|
59 |
|
|
rx_ip_in : in std_logic_vector( ip_addr_w_c-1 downto 0 );
|
60 |
|
|
rx_dest_port_in : in std_logic_vector( udp_port_w_c-1 downto 0 );
|
61 |
|
|
rx_source_port_in : in std_logic_vector( udp_port_w_c-1 downto 0 );
|
62 |
|
|
rx_addr_valid_out : out std_logic;
|
63 |
|
|
|
64 |
|
|
-- to hibi_transmitter, send acknowledges
|
65 |
|
|
ack_addr_out : out std_logic_vector( hibi_addr_width_g-1 downto 0 );
|
66 |
|
|
rx_addr_out : out std_logic_vector( hibi_addr_width_g-1 downto 0 );
|
67 |
|
|
send_tx_ack_out : out std_logic;
|
68 |
|
|
send_tx_nack_out : out std_logic;
|
69 |
|
|
send_rx_ack_out : out std_logic;
|
70 |
|
|
send_rx_nack_out : out std_logic;
|
71 |
|
|
|
72 |
|
|
-- from toplevel
|
73 |
|
|
eth_link_up_in : in std_logic
|
74 |
|
|
);
|
75 |
|
|
|
76 |
|
|
end ctrl_regs;
|
77 |
|
|
|
78 |
|
|
|
79 |
|
|
architecture rtl of ctrl_regs is
|
80 |
|
|
|
81 |
|
|
-- Wildcards
|
82 |
|
|
constant any_ip_c : std_logic_vector( ip_addr_w_c-1 downto 0 ) := x"FFFFFFFF";
|
83 |
|
|
constant any_port_c : std_logic_vector( udp_port_w_c-1 downto 0 ) := x"FFFF";
|
84 |
|
|
|
85 |
|
|
|
86 |
|
|
-- Registers holding current tx info
|
87 |
|
|
signal current_ip_r : std_logic_vector(ip_addr_w_c-1 downto 0);
|
88 |
|
|
signal current_dest_port_r : std_logic_vector(udp_port_w_c-1 downto 0);
|
89 |
|
|
signal current_source_port_r : std_logic_vector(udp_port_w_c-1 downto 0);
|
90 |
|
|
|
91 |
|
|
-- Tx lock information
|
92 |
|
|
signal locked_r : std_logic;
|
93 |
|
|
signal lock_addr_r : std_logic_vector( hibi_addr_width_g-1 downto 0 );
|
94 |
|
|
|
95 |
|
|
|
96 |
|
|
-- Table for rx receivers (each agent willing to receive data will have to
|
97 |
|
|
-- register its hibi address to some source ip and ports)
|
98 |
|
|
type receiver_info_type is
|
99 |
|
|
record
|
100 |
|
|
source_ip : std_logic_vector(ip_addr_w_c-1 downto 0);
|
101 |
|
|
source_port : std_logic_vector(udp_port_w_c-1 downto 0);
|
102 |
|
|
dest_port : std_logic_vector(udp_port_w_c-1 downto 0);
|
103 |
|
|
hibi_addr : std_logic_vector(hibi_addr_width_g-1 downto 0);
|
104 |
|
|
end record;
|
105 |
|
|
type receiver_table_type is array (0 to receiver_table_size_g-1) of receiver_info_type;
|
106 |
|
|
signal receiver_table_r : receiver_table_type;
|
107 |
|
|
-- validness
|
108 |
|
|
signal table_valid_array_r : std_logic_vector(receiver_table_size_g-1 downto 0);
|
109 |
|
|
-- to easily compare if full:
|
110 |
|
|
constant table_full_c : std_logic_vector(receiver_table_size_g-1 downto 0) := (others => '1');
|
111 |
|
|
|
112 |
|
|
|
113 |
|
|
|
114 |
|
|
|
115 |
|
|
-------------------------------------------------------------------------------
|
116 |
|
|
begin -- rtl
|
117 |
|
|
-------------------------------------------------------------------------------
|
118 |
|
|
|
119 |
|
|
lock_out <= locked_r;
|
120 |
|
|
lock_addr_out <= lock_addr_r;
|
121 |
|
|
tx_ip_out <= current_ip_r;
|
122 |
|
|
|
123 |
|
|
tx_dest_port_out <= current_dest_port_r;
|
124 |
|
|
tx_source_port_out <= current_source_port_r;
|
125 |
|
|
|
126 |
|
|
-----------------------------------------------------------------------------
|
127 |
|
|
--
|
128 |
|
|
-----------------------------------------------------------------------------
|
129 |
|
|
main: process (clk, rst_n)
|
130 |
|
|
variable spot_found_v : std_logic;
|
131 |
|
|
variable match_found_v : std_logic;
|
132 |
|
|
begin -- process main
|
133 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
134 |
|
|
|
135 |
|
|
current_source_port_r <= (others => '0');
|
136 |
|
|
current_dest_port_r <= (others => '0');
|
137 |
|
|
current_ip_r <= (others => '0');
|
138 |
|
|
locked_r <= '0';
|
139 |
|
|
lock_addr_r <= (others => '0');
|
140 |
|
|
table_valid_array_r <= (others => '0');
|
141 |
|
|
receiver_table_r <= (others => ( (others => '0'), (others => '0'), (others => '0'), (others => '0') ));
|
142 |
|
|
|
143 |
|
|
send_rx_nack_out <= '0';
|
144 |
|
|
send_rx_ack_out <= '0';
|
145 |
|
|
send_tx_nack_out <= '0';
|
146 |
|
|
send_tx_ack_out <= '0';
|
147 |
|
|
ack_addr_out <= (others => '0');
|
148 |
|
|
rx_addr_out <= (others => '0');
|
149 |
|
|
rx_addr_valid_out <= '0';
|
150 |
|
|
|
151 |
|
|
elsif clk'event and clk = '1' then -- rising clock edge
|
152 |
|
|
|
153 |
|
|
-- default values
|
154 |
|
|
send_tx_ack_out <= '0';
|
155 |
|
|
send_tx_nack_out <= '0';
|
156 |
|
|
send_rx_ack_out <= '0';
|
157 |
|
|
send_rx_nack_out <= '0';
|
158 |
|
|
|
159 |
|
|
|
160 |
|
|
|
161 |
|
|
-------------------------------------------------------------------------
|
162 |
|
|
-- Handle the configuration requests
|
163 |
|
|
-------------------------------------------------------------------------
|
164 |
|
|
if new_tx_conf_in = '1' then
|
165 |
|
|
-- New tx conf coming. Ensure that is not already locked at all, or
|
166 |
|
|
-- locked to the same address, and then update values and send ack.
|
167 |
|
|
-- Otherwise send nack.
|
168 |
|
|
|
169 |
|
|
if ( locked_r = '0' or lock_addr_r = lock_addr_in )
|
170 |
|
|
and eth_link_up_in = '1'
|
171 |
|
|
then
|
172 |
|
|
-- accept configuration
|
173 |
|
|
current_ip_r <= ip_in;
|
174 |
|
|
current_dest_port_r <= dest_port_in;
|
175 |
|
|
current_source_port_r <= source_port_in;
|
176 |
|
|
lock_addr_r <= lock_addr_in;
|
177 |
|
|
locked_r <= '1';
|
178 |
|
|
|
179 |
|
|
-- send ack
|
180 |
|
|
send_tx_ack_out <= '1';
|
181 |
|
|
|
182 |
|
|
else
|
183 |
|
|
-- reject configuration attempt
|
184 |
|
|
send_tx_nack_out <= '1';
|
185 |
|
|
end if;
|
186 |
|
|
|
187 |
|
|
ack_addr_out <= response_addr_in;
|
188 |
|
|
|
189 |
|
|
|
190 |
|
|
elsif new_rx_conf_in = '1' then
|
191 |
|
|
-- New rx conf coming. Check if there's room in the table, and store
|
192 |
|
|
-- information if possible. Otherwise send a nack.
|
193 |
|
|
|
194 |
|
|
-- Check if table full
|
195 |
|
|
if table_valid_array_r = table_full_c then
|
196 |
|
|
-- send a nack
|
197 |
|
|
send_rx_nack_out <= '1';
|
198 |
|
|
else
|
199 |
|
|
|
200 |
|
|
-- Find an empty spot
|
201 |
|
|
spot_found_v := '0';
|
202 |
|
|
for n in 0 to receiver_table_size_g-1 loop
|
203 |
|
|
if table_valid_array_r(n) = '0' and spot_found_v = '0' then
|
204 |
|
|
-- Put it here, to smallest empty spot
|
205 |
|
|
receiver_table_r(n).source_ip <= ip_in;
|
206 |
|
|
receiver_table_r(n).source_port <= source_port_in;
|
207 |
|
|
receiver_table_r(n).dest_port <= dest_port_in;
|
208 |
|
|
receiver_table_r(n).hibi_addr <= response_addr_in;
|
209 |
|
|
table_valid_array_r(n) <= '1';
|
210 |
|
|
|
211 |
|
|
spot_found_v := '1';
|
212 |
|
|
end if;
|
213 |
|
|
end loop; -- n
|
214 |
|
|
|
215 |
|
|
send_rx_ack_out <= '1';
|
216 |
|
|
|
217 |
|
|
end if;
|
218 |
|
|
|
219 |
|
|
ack_addr_out <= response_addr_in;
|
220 |
|
|
|
221 |
|
|
|
222 |
|
|
elsif release_lock_in = '1' then
|
223 |
|
|
-- Release tx lock if requested
|
224 |
|
|
locked_r <= '0';
|
225 |
|
|
end if;
|
226 |
|
|
-- /conf requests
|
227 |
|
|
|
228 |
|
|
|
229 |
|
|
|
230 |
|
|
-- !!! ES 2012-03-22
|
231 |
|
|
-- It seems that signal table_valid_array_r(n) is never
|
232 |
|
|
-- assigned to '0' after reset? Once the table gets full,
|
233 |
|
|
-- there is not way to get more room.
|
234 |
|
|
-- !!!
|
235 |
|
|
|
236 |
|
|
|
237 |
|
|
-------------------------------------------------------------------------
|
238 |
|
|
-- Address translation to rx address (hibi addr) according to info
|
239 |
|
|
-- provided by rx_ctrl.
|
240 |
|
|
-- Check that all 3 fields: src ip addr, src port and dst port match.
|
241 |
|
|
-- Wildcards are accepted.
|
242 |
|
|
-------------------------------------------------------------------------
|
243 |
|
|
match_found_v := '0';
|
244 |
|
|
for n in 0 to receiver_table_size_g-1 loop
|
245 |
|
|
if table_valid_array_r(n) = '1'
|
246 |
|
|
and (rx_ip_in = receiver_table_r(n).source_ip
|
247 |
|
|
or
|
248 |
|
|
receiver_table_r(n).source_ip = any_ip_c)
|
249 |
|
|
and (rx_source_port_in = receiver_table_r(n).source_port
|
250 |
|
|
or
|
251 |
|
|
receiver_table_r(n).source_port = any_port_c)
|
252 |
|
|
and (rx_dest_port_in = receiver_table_r(n).dest_port
|
253 |
|
|
or
|
254 |
|
|
receiver_table_r(n).dest_port = any_port_c)
|
255 |
|
|
then
|
256 |
|
|
rx_addr_out <= receiver_table_r(n).hibi_addr;
|
257 |
|
|
match_found_v := '1';
|
258 |
|
|
end if;
|
259 |
|
|
end loop; -- n
|
260 |
|
|
|
261 |
|
|
if match_found_v = '1' then
|
262 |
|
|
rx_addr_valid_out <= '1';
|
263 |
|
|
else
|
264 |
|
|
rx_addr_valid_out <= '0';
|
265 |
|
|
end if;
|
266 |
|
|
|
267 |
|
|
-------------------------------------------------------------------------
|
268 |
|
|
-- If timeout occures during a tx, tx_ctrl notifies about it and lock
|
269 |
|
|
-- must be released in order to reset hibi_receiver's state
|
270 |
|
|
-------------------------------------------------------------------------
|
271 |
|
|
if timeout_release_in = '1' then
|
272 |
|
|
locked_r <= '0';
|
273 |
|
|
end if;
|
274 |
|
|
|
275 |
|
|
end if;
|
276 |
|
|
end process main;
|
277 |
|
|
|
278 |
|
|
|
279 |
|
|
|
280 |
|
|
end rtl;
|