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/] [eth_dm9000a_ctrl/] [1.0/] [vhd/] [DM9kA_read_module.vhd] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
-------------------------------------------------------------------------------
2
-- Title      : DM9kA controller, read module
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : DM9kA_read_module.vhd
6
-- Author     : Jussi Nieminen
7
-- Company    : TUT
8
-- Last update: 2012-04-04
9
-------------------------------------------------------------------------------
10
-- Description: Handles the reading of rx data DM9kA -> application
11
-------------------------------------------------------------------------------
12
-- Revisions  :
13
-- Date        Version  Author  Description
14
-- 2009/09/02  1.0      niemin95        Created
15
-------------------------------------------------------------------------------
16
 
17
library ieee;
18
use ieee.std_logic_1164.all;
19
use ieee.numeric_std.all;
20
use work.DM9kA_ctrl_pkg.all;
21
 
22
 
23
entity DM9kA_read_module is
24
 
25
  port (
26
    clk                     : in  std_logic;
27
    rst_n                   : in  std_logic;
28
    -- from interrupt handler
29
    rx_waiting_in           : in  std_logic;
30
 
31
    -- from/to comm module
32
    rx_data_in              : in  std_logic_vector(data_width_c-1 downto 0);
33
    rx_data_valid_in        : in  std_logic;
34
    rx_re_out               : out std_logic;
35
    reg_addr_out            : out std_logic_vector(7 downto 0);
36
    config_data_out         : out std_logic_vector(7 downto 0);
37
    read_not_write_out      : out std_logic;
38
    config_valid_out        : out std_logic;
39
    data_from_comm_in       : in  std_logic_vector(data_width_c-1 downto 0);
40
    data_from_comm_valid_in : in  std_logic;
41
    comm_busy_in            : in  std_logic;
42
    comm_req_out            : out std_logic;
43
    comm_grant_in           : in  std_logic;
44
 
45
    -- from/to upper level
46
    rx_data_out             : out std_logic_vector(data_width_c-1 downto 0);
47
    rx_data_valid_out       : out std_logic;
48
    rx_re_in                : in  std_logic;
49
    new_rx_out              : out std_logic;
50
    rx_len_out              : out std_logic_vector(tx_len_w_c-1 downto 0);
51
    frame_type_out          : out std_logic_vector(15 downto 0);
52
    rx_erroneous_out        : out std_logic;
53
    fatal_error_out         : out std_logic  -- worse than some network error
54
    );
55
 
56
end DM9kA_read_module;
57
 
58
 
59
architecture rtl of DM9kA_read_module is
60
 
61
  type read_state_type is (wait_rx, peek_first_byte, delay, prepare_comm,
62
                           check_first_byte, check_status, get_length,
63
                           strip_header, relay_data, strip_checksum1,
64
                           strip_checksum2, check_next, clear_interrupt, fatal_error);
65
  signal state_r : read_state_type;
66
 
67
  signal comm_req_r  : std_logic;
68
  signal rx_re_r     : std_logic;
69
  signal rx_status_r : std_logic_vector(7 downto 0);
70
 
71
  signal rx_len_r          : integer range 0 to 2**tx_len_w_c-1;
72
  signal delay_done_r      : std_logic;
73
  signal header_cnt_r      : integer range 0 to 6;
74
  signal clear_interrupt_r : std_logic;
75
 
76
-------------------------------------------------------------------------------
77
begin  -- rtl
78
-------------------------------------------------------------------------------
79
 
80
  --
81
  -- Combinatorial process
82
  --
83
  mux : process (rx_data_in, rx_data_valid_in, rx_re_in, rx_re_r, state_r)
84
  begin  -- process mux
85
 
86
    if state_r = relay_data then
87
 
88
      rx_data_out       <= rx_data_in;
89
      rx_data_valid_out <= rx_data_valid_in;
90
      rx_re_out         <= rx_re_in;
91
 
92
    else
93
      rx_data_out       <= (others => '0');
94
      rx_data_valid_out <= '0';
95
      rx_re_out         <= rx_re_r;
96
 
97
    end if;
98
  end process mux;
99
 
100
  comm_req_out <= comm_req_r;
101
 
102
 
103
  --
104
  -- Sequential process for state machine
105
  --
106
  main : process (clk, rst_n)
107
 
108
    variable rx_len_v : integer range 0 to 2**tx_len_w_c-1;
109
 
110
  begin  -- process main
111
    if rst_n = '0' then                 -- asynchronous reset (active low)
112
 
113
      state_r           <= wait_rx;
114
      comm_req_r        <= '0';
115
      rx_status_r       <= (others => '0');
116
      rx_len_r          <= 0;
117
      clear_interrupt_r <= '0';
118
 
119
      reg_addr_out       <= (others => '0');
120
      config_data_out    <= (others => '0');
121
      config_valid_out   <= '0';
122
      read_not_write_out <= '0';
123
      rx_re_r            <= '0';
124
      rx_len_out         <= (others => '0');
125
      new_rx_out         <= '0';
126
      rx_erroneous_out   <= '0';
127
      fatal_error_out    <= '0';
128
      frame_type_out     <= (others => '0');
129
      header_cnt_r       <= 0;
130
 
131
 
132
    elsif clk'event and clk = '1' then  -- rising clock edge
133
 
134
      case state_r is
135
 
136
        when wait_rx =>
137
 
138
          rx_erroneous_out <= '0';
139
 
140
          -- notification from int handler
141
          if rx_waiting_in = '1' then
142
            -- ask for a turn
143
            comm_req_r <= '1';
144
          end if;
145
 
146
          if comm_req_r = '1' and comm_grant_in = '1' then
147
            -- our turn
148
            state_r <= peek_first_byte;
149
          end if;
150
 
151
 
152
        when peek_first_byte =>
153
 
154
          -- this is just a dummy read, returned value is rubbish for some
155
          -- reason... 
156
          reg_addr_out       <= rx_peek_reg_c;
157
          read_not_write_out <= '1';
158
          config_valid_out   <= '1';
159
 
160
          if comm_busy_in = '1' then
161
            config_valid_out <= '0';
162
            if data_from_comm_valid_in = '1' then
163
              state_r <= delay;
164
            end if;
165
          end if;
166
 
167
 
168
        when delay =>
169
 
170
          -- the chip needs a bit time after reading from rx_peek_reg_c
171
          if delay_done_r = '1' then
172
            delay_done_r <= '0';
173
            if clear_interrupt_r = '1' then
174
              state_r <= clear_interrupt;
175
            else
176
              state_r <= prepare_comm;
177
            end if;
178
          else
179
            delay_done_r <= '1';
180
          end if;
181
 
182
 
183
        when clear_interrupt =>
184
 
185
          -- Clearing interrupt flag. This is done only if we have already
186
          -- received one transmission, and find out that there is another when
187
          -- in check_next state.
188
          reg_addr_out       <= ISR_c;
189
          read_not_write_out <= '0';
190
          config_valid_out   <= '1';
191
          -- rx received interrupt flag (index 0) is cleared by writing 1 to it
192
          config_data_out    <= (0 => '1', others => '0');
193
 
194
          if comm_busy_in = '1' then
195
            config_valid_out  <= '0';
196
            clear_interrupt_r <= '0';
197
          end if;
198
 
199
          if comm_busy_in = '0' and clear_interrupt_r = '0' then
200
            state_r <= prepare_comm;
201
          end if;
202
 
203
 
204
        when prepare_comm =>
205
 
206
          -- set rx_data_reg
207
          reg_addr_out       <= rx_data_reg_c;
208
          read_not_write_out <= '1';
209
          config_valid_out   <= '1';
210
 
211
          if comm_busy_in = '1' then
212
            state_r <= check_first_byte;
213
          end if;
214
 
215
 
216
        when check_first_byte =>
217
 
218
          -- the first byte must be either x"01" (rx really waiting) or
219
          -- x"00" (no rx waiting). Any other value means that something
220
          -- has gone terribly wrong. This state should only be entered when
221
          -- there is something to read (after rx interrupt or when there is
222
          -- two or more rx:s waiting), so also the x"00" value is invalid.
223
 
224
          if rx_data_valid_in = '1' then
225
            rx_re_r <= '1';
226
          end if;
227
 
228
          if rx_data_valid_in = '1' and rx_re_r = '1' then
229
            rx_re_r <= '0';
230
 
231
            -- status is the upper byte
232
            rx_status_r <= rx_data_in(data_width_c-1 downto 8);
233
 
234
            -- the first byte:
235
            if rx_data_in(7 downto 0) = x"01" then
236
              -- everything's ok
237
              state_r <= check_status;
238
            else
239
              -- nothing's ok
240
              state_r <= fatal_error;
241
            end if;
242
          end if;
243
 
244
 
245
        when check_status =>
246
 
247
          -- if there's non-zero bits, (excluding the multicast frame bit)
248
          -- something has gone wrong.
249
          if (rx_status_r and "10111111") /= x"00" then
250
            rx_erroneous_out <= '1';
251
          end if;
252
 
253
          state_r <= get_length;
254
 
255
 
256
        when get_length =>
257
 
258
          if rx_data_valid_in = '1' then
259
            rx_re_r <= '1';
260
          end if;
261
 
262
          if rx_data_valid_in = '1' and rx_re_r = '1' then
263
            rx_re_r <= '0';
264
 
265
            -- rx length doesn't include the header nor the checksum
266
            rx_len_v   := to_integer(unsigned(rx_data_in)) - eth_header_len_c - eth_checksum_len_c;
267
            rx_len_r   <= rx_len_v;
268
            rx_len_out <= std_logic_vector(to_unsigned(rx_len_v, tx_len_w_c));
269
            state_r    <= strip_header;
270
          end if;
271
 
272
 
273
        when strip_header =>
274
          -- the data contains MAC addresses and frame type, so we must
275
          -- get those before relaying the data.
276
 
277
          if rx_data_valid_in = '1' then
278
            rx_re_r <= '1';
279
          end if;
280
 
281
          if rx_data_valid_in = '1' and rx_re_r = '1' then
282
            rx_re_r <= '0';
283
 
284
            if header_cnt_r = 6 then
285
              -- write out the frame type
286
              frame_type_out(15 downto 8) <= rx_data_in(7 downto 0);
287
              frame_type_out(7 downto 0)  <= rx_data_in(15 downto 8);
288
              new_rx_out                  <= '1';
289
              state_r                     <= relay_data;
290
              header_cnt_r                <= 0;
291
            else
292
              -- do nothing with the MAC addresses
293
              header_cnt_r <= header_cnt_r + 1;
294
            end if;
295
 
296
          end if;
297
 
298
 
299
 
300
        when relay_data =>
301
 
302
          if rx_re_in = '1' and rx_data_valid_in = '1' then
303
            new_rx_out <= '0';
304
 
305
            -- upper level reads two bytes
306
            if rx_len_r <= 2 then
307
              -- those are the last two
308
              rx_len_r <= 0;
309
              state_r  <= strip_checksum1;
310
            else
311
              rx_len_r <= rx_len_r - 2;
312
            end if;
313
          end if;
314
 
315
 
316
        when strip_checksum1 =>
317
 
318
          if rx_data_valid_in = '1' then
319
            rx_re_r <= '1';
320
          end if;
321
 
322
          if rx_data_valid_in = '1' and rx_re_r = '1' then
323
            rx_re_r <= '0';
324
            state_r <= strip_checksum2;
325
          end if;
326
 
327
 
328
        when strip_checksum2 =>
329
 
330
          if rx_data_valid_in = '1' then
331
            -- config_valid_out must drop early enough to prevent unwanted reading
332
            config_valid_out <= '0';
333
            rx_re_r          <= '1';
334
          end if;
335
 
336
          if rx_data_valid_in = '1' and rx_re_r = '1' then
337
            rx_re_r <= '0';
338
            state_r <= check_next;
339
          end if;
340
 
341
 
342
        when check_next =>
343
 
344
 
345
          -- make sure that there's no other rx:s waiting
346
          reg_addr_out       <= rx_peek_reg_c;
347
          read_not_write_out <= '1';
348
          config_valid_out   <= '1';
349
 
350
          if comm_busy_in = '1' then
351
            config_valid_out <= '0';
352
 
353
            if data_from_comm_valid_in = '1' then
354
 
355
              if data_from_comm_in(7 downto 0) = x"01" then
356
                -- there really is a new rx coming, so we must clear the
357
                -- interrupt (so that we don't get an invalid rx_waiting signal
358
                -- afterwards)
359
                state_r           <= delay;
360
                clear_interrupt_r <= '1';
361
              elsif data_from_comm_in(7 downto 0) = x"00" then
362
                -- nothing incoming
363
                state_r    <= wait_rx;
364
                comm_req_r <= '0';
365
              else
366
                state_r <= fatal_error;
367
              end if;
368
            end if;
369
          end if;
370
 
371
 
372
        when fatal_error =>
373
          fatal_error_out <= '1';
374
        when others => null;
375
      end case;
376
 
377
    end if;
378
  end process main;
379
 
380
end rtl;

powered by: WebSVN 2.1.0

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