OpenCores
URL https://opencores.org/ocsvn/funbase_ip_library/funbase_ip_library/trunk

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.interface/] [udp2hibi/] [1.0/] [vhd/] [hibi_transmitter.vhd] - Blame information for rev 183

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
-------------------------------------------------------------------------------
2
-- Title      : Hibi transmitter
3
-- Project    : UDP2HIBI
4
-------------------------------------------------------------------------------
5
-- File       : hibi_transmitter.vhd
6
-- Author     : Jussi Nieminen
7
-- Last update: 2012-03-23
8
-- Platform   : 
9
-------------------------------------------------------------------------------
10
-- Description: Takes care of transmitting packets via HIBI.
11
--              Gets data from rx ctrl (which gets them from udp/ip).
12
--              Checks parameters fromc ctrl-registers and gives data to hibi
13
--              transmitter.
14
-------------------------------------------------------------------------------
15
-- Revisions  :
16
-- Date        Version  Author  Description
17
-- 2009/12/21  1.0      niemin95        Created
18
-------------------------------------------------------------------------------
19
 
20
library ieee;
21
use ieee.std_logic_1164.all;
22
use work.udp2hibi_pkg.all;
23
 
24
 
25
entity hibi_transmitter is
26
 
27
  generic (
28
    hibi_data_width_g : integer := 32;
29
    hibi_addr_width_g : integer := 32;
30
    hibi_comm_width_g : integer := 5;
31
    ack_fifo_depth_g  : integer := 5
32
    );
33
 
34
  port (
35
    clk              : in  std_logic;
36
    rst_n            : in  std_logic;
37
 
38
    -- to/from HIBI
39
    hibi_comm_out    : out std_logic_vector( hibi_comm_width_g-1 downto 0 );
40
    hibi_data_out    : out std_logic_vector( hibi_data_width_g-1 downto 0 );
41
    hibi_av_out      : out std_logic;
42
    hibi_we_out      : out std_logic;
43
    hibi_full_in     : in  std_logic;
44
 
45
    -- from/to rx_ctrl
46
    send_request_in  : in  std_logic;
47
    rx_len_in        : in  std_logic_vector( tx_len_w_c-1 downto 0 );
48
    ready_for_tx_out : out std_logic;
49
    rx_empty_in      : in  std_logic;
50
    rx_data_in       : in  std_logic_vector( hibi_data_width_g-1 downto 0 );
51
    rx_re_out        : out std_logic;
52
 
53
    -- from ctrl_regs
54
    rx_addr_in       : in  std_logic_vector( hibi_addr_width_g-1 downto 0 );
55
    ack_addr_in      : in  std_logic_vector( hibi_addr_width_g-1 downto 0 );
56
    send_tx_ack_in   : in  std_logic;
57
    send_tx_nack_in  : in  std_logic;
58
    send_rx_ack_in   : in  std_logic;
59
    send_rx_nack_in  : in  std_logic
60
    );
61
 
62
end hibi_transmitter;
63
 
64
 
65
architecture rtl of hibi_transmitter is
66
 
67
  -- FSM
68
  type state_type is (normal, send_ack_addr, send_ack, send_data_addr, send_rx_header);
69
  signal state_r : state_type;
70
 
71
  signal data_from_rx_ctrl : std_logic_vector(hibi_data_width_g-1 downto 0);  -- obsolete?
72
  signal re_to_rx_ctrl     : std_logic;  -- obsolete?
73
 
74
  signal re_we_r           : std_logic;
75
  signal target_addr_r     : std_logic_vector(hibi_addr_width_g-1 downto 0);
76
 
77
 
78
  -- fifo is used to store ack requests
79
  -- ** WARNING! **
80
  -- The fifo is not infinite (really?), so if some agent decides to send e.g.
81
  -- 100 tx conf packets in a row, the fifo will simply discard ack/nack
82
  -- requests that don't fit in.
83
  component fifo
84
    generic (
85
      data_width_g : integer;
86
      depth_g      : integer);
87
    port (
88
      clk       : in  std_logic;
89
      rst_n     : in  std_logic;
90
      data_in   : in  std_logic_vector (data_width_g-1 downto 0);
91
      we_in     : in  std_logic;
92
      full_out  : out std_logic;
93
      one_p_out : out std_logic;
94
      re_in     : in  std_logic;
95
      data_out  : out std_logic_vector (data_width_g-1 downto 0);
96
      empty_out : out std_logic;
97
      one_d_out : out std_logic);
98
  end component;
99
 
100
  signal requests_to_ack_fifo  : std_logic_vector(3 downto 0);
101
  signal data_to_ack_fifo      : std_logic_vector(hibi_addr_width_g+4-1 downto 0);
102
  signal we_to_ack_fifo        : std_logic;
103
  signal ack_fifo_re_r         : std_logic;
104
  signal data_from_ack_fifo    : std_logic_vector(hibi_addr_width_g+4-1 downto 0);
105
  signal ack_data              : std_logic_vector(3 downto 0);
106
  signal ack_addr              : std_logic_vector(hibi_addr_width_g-1 downto 0);
107
  signal empty_from_ack_fifo   : std_logic;
108
  signal which_ack_r           : std_logic_vector(3 downto 0);
109
  signal target_addr_valid_r   : std_logic;
110
  signal connect_data_in_out_r : std_logic;
111
 
112
  -- Registers for HIBI
113
  signal hibi_data_r           : std_logic_vector(hibi_data_width_g-1 downto 0);
114
  signal hibi_we_r             : std_logic;
115
  signal new_rx_r              : std_logic;
116
  signal rx_len_r              : std_logic_vector(tx_len_w_c-1 downto 0);
117
 
118
  constant hibi_data_comm_c : std_logic_vector( hibi_comm_width_g-1 downto 0 ) := "00010"; --
119
  -- command 2 = write
120
 
121
-------------------------------------------------------------------------------
122
begin  -- rtl
123
-------------------------------------------------------------------------------
124
 
125
  hibi_comm_out <= hibi_data_comm_c;
126
 
127
 
128
  requests_to_ack_fifo <= send_tx_ack_in & send_tx_nack_in &
129
                          send_rx_ack_in & send_rx_nack_in;
130
 
131
  data_to_ack_fifo <= requests_to_ack_fifo & ack_addr_in;
132
  we_to_ack_fifo   <= send_tx_ack_in or send_tx_nack_in or send_rx_ack_in or send_rx_nack_in;
133
 
134
  ack_fifo: fifo
135
    generic map (
136
        data_width_g => hibi_addr_width_g+4,
137
        depth_g      => ack_fifo_depth_g
138
        )
139
    port map (
140
        clk       => clk,
141
        rst_n     => rst_n,
142
 
143
        data_in   => data_to_ack_fifo,
144
        we_in     => we_to_ack_fifo,
145
        full_out  => open,
146
        one_p_out => open,
147
 
148
        re_in     => ack_fifo_re_r,
149
        data_out  => data_from_ack_fifo,
150
        empty_out => empty_from_ack_fifo,
151
        one_d_out => open
152
        );
153
 
154
  ack_data <= data_from_ack_fifo( hibi_addr_width_g+4-1 downto hibi_addr_width_g );
155
  ack_addr <= data_from_ack_fifo( hibi_addr_width_g-1 downto 0 );
156
 
157
 
158
  -----------------------------------------------------------------------------
159
  -- switch output between hibi_data_r and rx_data_in
160
  -----------------------------------------------------------------------------
161
  output_mux: process (connect_data_in_out_r, rx_data_in, hibi_data_r,
162
                       re_we_r, rx_empty_in, hibi_we_r)
163
  begin  -- process output_mux
164
    if connect_data_in_out_r = '1' then
165
      hibi_data_out <= rx_data_in;
166
      hibi_we_out   <= re_we_r and (not rx_empty_in);
167
    else
168
      hibi_data_out <= hibi_data_r;
169
      hibi_we_out   <= hibi_we_r;
170
    end if;
171
  end process output_mux;
172
 
173
  rx_re_out <= re_we_r and (not hibi_full_in);
174
 
175
 
176
 
177
  -----------------------------------------------------------------------------
178
  --
179
  -----------------------------------------------------------------------------
180
  main: process (clk, rst_n)
181
  begin  -- process main
182
    if rst_n = '0' then                 -- asynchronous reset (active low)
183
 
184
      state_r       <= normal;
185
      ack_fifo_re_r <= '0';
186
      re_we_r       <= '0';
187
      target_addr_r <= (others => '0');
188
      which_ack_r   <= (others => '0');
189
 
190
      target_addr_valid_r   <= '0';
191
      connect_data_in_out_r <= '0';
192
 
193
      hibi_we_r   <= '0';
194
      hibi_data_r <= (others => '0');
195
      new_rx_r    <= '0';
196
      rx_len_r    <= (others => '0');
197
 
198
      hibi_av_out      <= '0';
199
      ready_for_tx_out <= '0';
200
 
201
    elsif clk'event and clk = '1' then  -- rising clock edge
202
 
203
      -- default values
204
      ready_for_tx_out <= '0';
205
      ack_fifo_re_r    <= '0';
206
      hibi_we_r        <= '0';
207
      hibi_av_out      <= '0';
208
      re_we_r          <= '0';
209
      connect_data_in_out_r <= '0';
210
 
211
 
212
      -- state machine
213
      case state_r is
214
 
215
        -----------------------------------------------------------------------
216
        when normal =>
217
          -- normal state means that we are either idle or in the middle of
218
          -- sending data. We don't have to know which case it is, we just
219
          -- send all the data we get to the address stored in target_addr_r.
220
          -- We are ready for new transfers when we are in this state and both,
221
          -- tx_fifo and ack fifo are empty.
222
 
223
          if rx_empty_in = '1' and empty_from_ack_fifo = '1' and send_request_in = '0' then
224
            ready_for_tx_out <= '1';
225
          end if;
226
 
227
          -- if rx_ctrl requests a new transmission
228
          if send_request_in = '1' then
229
            target_addr_r <= rx_addr_in;
230
            state_r       <= send_data_addr;
231
            rx_len_r      <= rx_len_in;
232
            new_rx_r      <= '1';
233
 
234
            hibi_av_out <= '1';
235
            hibi_we_r   <= '1';
236
            hibi_data_r <= rx_addr_in;
237
 
238
          -- else if there is new (n)ack to be sent
239
          elsif empty_from_ack_fifo = '0' then
240
            which_ack_r   <= ack_data;
241
            ack_fifo_re_r <= '1';
242
            -- target address for data is no longer in hibi wrapper's register
243
            target_addr_valid_r <= '0';
244
 
245
            hibi_av_out <= '1';
246
            hibi_data_r <= ack_addr;
247
            hibi_we_r   <= '1';
248
            state_r     <= send_ack_addr;
249
 
250
          -- else if there is data to be sent and room where to send it
251
          elsif rx_empty_in = '0' and hibi_full_in = '0' then
252
 
253
            -- if we have sent an ack/nack in the middle of the transfer, we
254
            -- have to resend the target address
255
            if target_addr_valid_r = '0' then
256
              hibi_av_out <= '1';
257
              hibi_we_r   <= '1';
258
              hibi_data_r <= target_addr_r;
259
              state_r <= send_data_addr;
260
            else
261
              -- address is valid, just keep on sending data
262
              re_we_r <= '1';
263
              connect_data_in_out_r <= '1';
264
            end if;
265
          end if;
266
 
267
 
268
        -----------------------------------------------------------------------
269
        when send_ack_addr =>
270
 
271
          hibi_we_r <= '1';
272
 
273
          if hibi_full_in = '0' then
274
 
275
            if which_ack_r(3) = '1' or which_ack_r(1) = '1' then
276
              -- it's an ack
277
              hibi_data_r( id_hi_idx_c downto id_lo_idx_c ) <= ack_header_id_c;
278
            else
279
              -- a nack
280
              hibi_data_r( id_hi_idx_c downto id_lo_idx_c ) <= nack_header_id_c;
281
            end if;
282
            if which_ack_r(3) = '1' or which_ack_r(2) = '1' then
283
              -- it's tx (n)ack
284
              hibi_data_r( id_lo_idx_c-1 ) <= '1';
285
            else
286
              -- rx (n)ack
287
              hibi_data_r( id_lo_idx_c-1 ) <= '0';
288
            end if;
289
 
290
            hibi_data_r( id_lo_idx_c-2 downto 0 ) <= (others => '0');
291
 
292
            state_r <= send_ack;
293
 
294
          else
295
            hibi_av_out <= '1';
296
          end if;
297
 
298
        -----------------------------------------------------------------------
299
        when send_ack =>
300
          -- ack is currently being sent. Decide what to do next.
301
 
302
          if hibi_full_in = '0' then
303
            if empty_from_ack_fifo = '1' and rx_empty_in = '1' then
304
              -- no more acks and no data, start waiting in normal state
305
              state_r <= normal;
306
 
307
            elsif empty_from_ack_fifo = '0' then
308
              -- another ack, send it
309
              which_ack_r   <= ack_data;
310
              ack_fifo_re_r <= '1';
311
 
312
              hibi_av_out <= '1';
313
              hibi_data_r <= ack_addr;
314
              hibi_we_r   <= '1';
315
              state_r     <= send_ack_addr;
316
 
317
            else
318
              -- there's data to be sent, resend the address
319
              hibi_av_out <= '1';
320
              hibi_we_r   <= '1';
321
              hibi_data_r <= target_addr_r;
322
              state_r <= send_data_addr;
323
            end if;
324
          else
325
            hibi_we_r <= '1';
326
          end if;
327
 
328
 
329
        -----------------------------------------------------------------------
330
        when send_data_addr =>
331
          -- send receiver address, and after that either send a new rx header
332
          -- or continue the old rx
333
 
334
          if hibi_full_in = '0' then
335
            if new_rx_r = '1' then
336
              -- new rx, send header
337
              hibi_we_r                                                <= '1';
338
              hibi_data_r                                              <= (others => '0');
339
              hibi_data_r(id_hi_idx_c downto id_lo_idx_c)              <= rx_data_header_id_c;
340
              hibi_data_r(id_lo_idx_c-1 downto id_lo_idx_c-tx_len_w_c) <= rx_len_r;
341
              state_r                                                  <= send_rx_header;
342
              new_rx_r                                                 <= '0';
343
 
344
            else
345
              state_r <= normal;
346
              -- if possible, start sending
347
              if rx_empty_in = '0' and hibi_full_in = '0' then
348
                re_we_r <= '1';
349
                connect_data_in_out_r <= '1';
350
              end if;
351
            end if;
352
 
353
            target_addr_valid_r <= '1';
354
          else
355
            hibi_av_out <= '1';
356
            hibi_we_r   <= '1';
357
          end if;
358
 
359
 
360
        -----------------------------------------------------------------------
361
        when send_rx_header =>
362
          -- new rx starting, send the header
363
 
364
          if hibi_full_in = '0' then
365
            state_r <= normal;
366
            -- if possible, start sending
367
            if rx_empty_in = '0' and hibi_full_in = '0' then
368
              re_we_r <= '1';
369
              connect_data_in_out_r <= '1';
370
            end if;
371
          else
372
            hibi_we_r <= '1';
373
          end if;
374
 
375
 
376
        when others => null;
377
      end case;
378
 
379
 
380
    end if;
381
  end process main;
382
 
383
 
384
 
385
end rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.