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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
-------------------------------------------------------------------------------
2
-- Title      : LAN91C111 controller, sender module
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : Original: DM9kA_send_module.vhd
6
-- Author     : Jussi Nieminen. Antti Alhonen for LAN91C111.
7
-- Last update: 2011-11-08
8
-------------------------------------------------------------------------------
9
-- Description: Handles sending procedures
10
-------------------------------------------------------------------------------
11
-- Revisions  :
12
-- Date        Version  Author  Description
13
-- 2009/08/25  1.0      niemin95        Created
14
-- 2011/07/??  lan91c111 alhonena
15
-------------------------------------------------------------------------------
16
 
17
library ieee;
18
use ieee.std_logic_1164.all;
19
use ieee.numeric_std.all;
20
use work.lan91c111_ctrl_pkg.all;
21
 
22
 
23
entity lan91c111_send_module is
24
 
25
  generic (
26
    mode_16bit_g : integer := 0);
27
 
28
  port (
29
    clk                     : in  std_logic;
30
    rst_n                   : in  std_logic;
31
    -- from interrupt handler
32
    tx_completed_in         : in  std_logic;
33
    -- to and from comm module
34
    comm_req_out            : out std_logic;
35
    comm_grant_in           : in  std_logic;
36
    reg_addr_out            : out std_logic_vector( real_addr_width_c-1 downto 0 );
37
    config_data_out         : out std_logic_vector( lan91_data_width_c-1 downto 0 );
38
    config_nBE_out          : out std_logic_vector( 3 downto 0 );
39
    read_not_write_out      : out std_logic;
40
    config_valid_out        : out std_logic;
41
    data_from_comm_in       : in  std_logic_vector( lan91_data_width_c-1 downto 0 );
42
    data_from_comm_valid_in : in  std_logic;
43
    comm_busy_in            : in  std_logic;
44
    -- from upper level
45
    tx_data_in              : in  std_logic_vector( lan91_data_width_c-1 downto 0 );
46
    tx_data_valid_in        : in  std_logic;
47
    tx_re_out               : out std_logic;
48
    tx_MAC_addr_in          : in  std_logic_vector( 47 downto 0 );
49
    new_tx_in               : in  std_logic;
50
    tx_len_in               : in  std_logic_vector( tx_len_w_c-1 downto 0 );
51
    tx_frame_type_in        : in  std_logic_vector( 15 downto 0 )
52
    );
53
 
54
end lan91c111_send_module;
55
 
56
 
57
architecture rtl of lan91c111_send_module is
58
 
59
  signal trgt_MAC_r : std_logic_vector(6*8-1 downto 0);
60
 
61
  type tx_state_type is (wait_tx,
62
                         alloc_mem,
63
                         wait_alloc,
64
                         copy_packet_number,
65
                         write_pointer,
66
                         write_byte_count,
67
                         write_MACs1,
68
                         write_MACs2,
69
                         write_MACs3,
70
                         write_frame_type,
71
                         write_payload,
72
                         write_payload_last16,  -- skipped if tx_len mod 4 = 0 or 1
73
                         write_padding,  -- SMSC bug workaround: autopadding does not work.
74
                         write_control_byte_and_last,
75
                         enqueue_packet_number_to_tx_fifo);
76
  signal tx_state_r : tx_state_type;
77
 
78
  signal tx_len_r : std_logic_vector( tx_len_w_c-1 downto 0 );
79
  signal payload_len_r : std_logic_vector( tx_len_w_c-1 downto 0 );
80
  signal tx_len_r_int : integer range 0 to 2**tx_len_w_c-1;
81
  signal payload_len_int : integer range 0 to 2**tx_len_w_c-1;
82
 
83
  signal tx_data_cnt_r : integer range 0 to 2**tx_len_w_c-1;
84
 
85
  signal pad_cnt_r : integer range 0 to 46;
86
 
87
  signal tx_data_r : std_logic_vector( lan91_data_width_c-1 downto 0 );
88
  signal tx_data_valid_r : std_logic;
89
 
90
  signal comm_req_r : std_logic;
91
  signal config_valid_r : std_logic;
92
 
93
  constant pnt_set_wait_cnt_c : integer := clk_hz_c/2702702;  -- 370 ns wait after pointer is set.
94
  signal pnt_set_wait_cnt_r : integer range 0 to pnt_set_wait_cnt_c;
95
 
96
  signal got_the_odd_r : std_logic;
97
  signal odd_r : std_logic_vector(7 downto 0);
98
 
99
  signal need_padding_r : std_logic;       -- Set if packet is short to overcome a bug/feature in lan91c111
100
 
101
-------------------------------------------------------------------------------
102
begin  -- rtl
103
-------------------------------------------------------------------------------
104
 
105
 
106
  comm_req_out <= comm_req_r;
107
  tx_len_r_int <= to_integer( unsigned( tx_len_r ));
108
  payload_len_int <= to_integer( unsigned( payload_len_r ));
109
 
110
  config_valid_out <= config_valid_r;
111
 
112
  main: process (clk, rst_n)
113
 
114
    -- helping with odd length transfers
115
    variable odd_len_compensation_v : integer range 0 to 1;
116
 
117
  begin  -- process main
118
    if rst_n = '0' then                 -- asynchronous reset (active low)
119
 
120
      tx_state_r   <= wait_tx;
121
 
122
      trgt_MAC_r <= (others => '0');
123
 
124
      reg_addr_out <= (others => '0');
125
      config_data_out <= (others => '0');
126
      config_valid_r <= '0';
127
      read_not_write_out <= '0';
128
 
129
      comm_req_r       <= '0';
130
      tx_data_r        <= (others => '0');
131
      tx_data_valid_r  <= '0';
132
      tx_len_r         <= (others => '0');
133
      got_the_odd_r    <= '0';
134
      need_padding_r      <= '0';
135
 
136
    elsif clk'event and clk = '1' then  -- rising clock edge
137
 
138
      -- new_tx_in, tx_len_in and tx_MAC_addr_in must remain stable until
139
      -- the first data is read from the upper level.
140
 
141
      -- tx state machine
142
 
143
      -- Note: We must be in BANK 2; The initialization algorithm sets the correct
144
      -- bank. If any other module switch banks, you must either switch
145
      -- back in those modules (recommended as switches are not usually needed)
146
      -- or add a new state to switch to bank 2 by using the bank change register at location E.
147
 
148
      -- DEFAULTS:
149
      config_valid_r <= '0';
150
      tx_re_out <= '0';
151
 
152
 
153
      case tx_state_r is
154
        when wait_tx =>
155
          got_the_odd_r <= '0';
156
          -- new transfer waiting
157
          if new_tx_in = '1' then
158
            comm_req_r <= '1';
159
            tx_len_r <= std_logic_vector( unsigned( tx_len_in ) + to_unsigned( eth_header_len_c, tx_len_w_c ));
160
            payload_len_r <= tx_len_in;
161
            trgt_MAC_r <= tx_MAC_addr_in;
162
 
163
            if comm_grant_in = '1' and comm_req_r = '1' then
164
              -- we got permission to use the comm module.
165
              tx_state_r <= alloc_mem;
166
              reg_addr_out <= "000";
167
              config_nBE_out <= "1100";  -- 16 bit accesses follow.
168
              read_not_write_out <= '0';
169
              config_data_out <= x"000000" & "00100000";
170
              config_valid_r <= '1';
171
            end if;
172
          end if;
173
 
174
        when alloc_mem =>
175
          if comm_busy_in = '0' and config_valid_r = '0' then
176
            -- Comm not busy anymore; the next operation.
177
            tx_state_r <= wait_alloc;
178
            reg_addr_out <= "110";
179
            read_not_write_out <= '1';
180
            config_valid_r <= '1';
181
          end if;
182
 
183
          if tx_len_r_int < 71 then
184
            need_padding_r <= '1';
185
            pad_cnt_r <= 72 - tx_len_r_int;
186
          else
187
            need_padding_r <= '0';
188
          end if;
189
 
190
        when wait_alloc =>
191
          if data_from_comm_valid_in = '1' then  -- data_valid = '1' means also
192
                                                 -- busy = '0'. See comm module.
193
            if data_from_comm_in(3) = '1' then  -- ALLOC INT flag = ready.
194
              tx_state_r <= copy_packet_number;
195
              reg_addr_out <= "001";
196
              read_not_write_out <= '1';
197
              config_valid_r <= '1';
198
            else
199
              -- Not ready yet...
200
              tx_state_r <= alloc_mem;  -- Poll again.
201
            end if;
202
          end if;
203
 
204
        when copy_packet_number =>
205
          if data_from_comm_valid_in = '1' then
206
            reg_addr_out <= "001";
207
            -- Copy from ALLOCATED PACKET NUMBER to PACKET NUMBER TX AREA. Both
208
            -- are within the same word.
209
            config_nBE_out <= "1100";
210
            config_data_out <= x"000000" & "00" & data_from_comm_in(13 downto 8);
211
            read_not_write_out <= '0';
212
            config_valid_r <= '1';
213
            tx_state_r <= write_pointer;
214
          end if;
215
 
216
        when write_pointer =>
217
          if comm_busy_in = '0'  and config_valid_r = '0' then
218
            reg_addr_out <= "011";
219
            -- Set pointer to RAM offset 2 (Byte count starts here),
220
            -- with Auto Increment on.
221
            config_nBE_out <= "1100";
222
            config_data_out <= x"0000" & "01000" & "00000000010";
223
            read_not_write_out <= '0';
224
            config_valid_r <= '1';
225
            tx_state_r <= write_byte_count;
226
            pnt_set_wait_cnt_r <= pnt_set_wait_cnt_c;
227
          end if;
228
 
229
        when write_byte_count =>
230
          if comm_busy_in = '0'  and config_valid_r = '0' then
231
            if pnt_set_wait_cnt_r = 0 then
232
              reg_addr_out <= "100";      -- All further operations go to this address.
233
              config_nBE_out <= "1100";
234
              read_not_write_out <= '0';  -- Everything after this will be writes.
235
              if need_padding_r = '1' then
236
                config_data_out <= x"0000" & "00000" & "00001001000";
237
              else
238
                config_data_out <= x"0000" & "00000" & tx_len_r;
239
              end if;
240
              config_valid_r <= '1';
241
              tx_state_r <= write_MACs1;
242
            else
243
              pnt_set_wait_cnt_r <= pnt_set_wait_cnt_r - 1;
244
            end if;
245
          end if;
246
 
247
        when write_MACs1 =>
248
          if comm_busy_in = '0' and config_valid_r = '0' then
249
            config_nBE_out <= "0000";   -- 32 bit access.
250
            config_data_out <= trgt_MAC_r(3*8-1 downto 2*8) & trgt_MAC_r(4*8-1 downto 3*8) & trgt_MAC_r(5*8-1 downto 4*8) & trgt_MAC_r(6*8-1 downto 5*8);
251
            config_valid_r <= '1';
252
            tx_state_r <= write_MACs2;
253
          end if;
254
 
255
        when write_MACs2 =>
256
          if comm_busy_in = '0' and config_valid_r = '0'  then
257
            config_nBE_out <= "0000";
258
            config_data_out <= MAC_addr_c(5*8-1 downto 4*8) & MAC_addr_c(6*8-1 downto 5*8) & trgt_MAC_r(1*8-1 downto 0) & trgt_MAC_r(2*8-1 downto 1*8);
259
            config_valid_r <= '1';
260
            tx_state_r <= write_MACs3;
261
          end if;
262
 
263
        when write_MACs3 =>
264
          if comm_busy_in = '0' and config_valid_r = '0'  then
265
            config_nBE_out <= "0000";
266
            config_data_out <= MAC_addr_c(1*8-1 downto 0*8) & MAC_addr_c(2*8-1 downto 1*8) & MAC_addr_c(3*8-1 downto 2*8) & MAC_addr_c(4*8-1 downto 3*8);
267
            config_valid_r <= '1';
268
            tx_state_r <= write_frame_type;
269
          end if;
270
 
271
        when write_frame_type =>
272
          if comm_busy_in = '0' and config_valid_r = '0'  then
273
            config_nBE_out <= "1100";   -- 16 bit access!
274
            config_data_out <= x"0000" & tx_frame_type_in(7 downto 0) & tx_frame_type_in(15 downto 8);
275
            config_valid_r <= '1';
276
            if payload_len_int = 1 then
277
              if need_padding_r = '1' then
278
                tx_state_r <= write_padding;
279
              else
280
                tx_state_r <= write_control_byte_and_last;
281
              end if;
282
            elsif mode_16bit_g = 0 and (payload_len_int = 2 or payload_len_int = 3) then
283
              tx_state_r <= write_payload_last16;
284
            else
285
              tx_state_r <= write_payload;
286
            end if;
287
            tx_data_cnt_r <= payload_len_int;
288
          end if;
289
 
290
        when write_payload =>
291
          if comm_busy_in = '0' and config_valid_r = '0' and tx_data_valid_in = '1' then
292
            if mode_16bit_g = 1 then
293
              config_nBE_out <= "1100";
294
 
295
              config_data_out <= tx_data_in;
296
              config_valid_r <= '1';
297
              tx_re_out <= '1';
298
 
299
              if tx_data_cnt_r = 2 or tx_data_cnt_r = 3 then
300
                if need_padding_r = '1' then
301
                  tx_state_r <= write_padding;
302
                else
303
                  tx_state_r <= write_control_byte_and_last;
304
                end if;
305
              end if;
306
 
307
              tx_data_cnt_r <= tx_data_cnt_r - 2;
308
 
309
            else                        -- 32 bit mode (original)
310
              config_nBE_out <= "0000";
311
 
312
              config_data_out <= tx_data_in;
313
              config_valid_r <= '1';
314
              tx_re_out <= '1';
315
 
316
              if tx_data_cnt_r = 4 or tx_data_cnt_r = 5 then
317
                if need_padding_r = '1' then
318
                  tx_state_r <= write_padding;
319
                else
320
                  tx_state_r <= write_control_byte_and_last;
321
                end if;
322
              elsif tx_data_cnt_r = 6 or tx_data_cnt_r = 7 then
323
                tx_state_r <= write_payload_last16;
324
              end if;
325
 
326
              tx_data_cnt_r <= tx_data_cnt_r - 4;
327
 
328
            end if;
329
          end if;
330
 
331
        when write_payload_last16 =>
332
          assert mode_16bit_g = 0 report "Shouldn't be here!" severity failure;
333
          if comm_busy_in = '0' and config_valid_r = '0' and tx_data_valid_in = '1' then
334
            config_nBE_out <= "1100";
335
            config_data_out(15 downto 0) <= tx_data_in(15 downto 0);
336
            got_the_odd_r <= '1';
337
            odd_r <= tx_data_in(23 downto 16);
338
            config_valid_r <= '1';
339
            tx_re_out <= '1';
340
            if need_padding_r = '1' then
341
              tx_state_r <= write_padding;
342
            else
343
              tx_state_r <= write_control_byte_and_last;
344
            end if;
345
 
346
          end if;
347
 
348
        when write_padding =>
349
          if comm_busy_in = '0' and config_valid_r = '0' then
350
            -- Padding as 16-bit writes to simplify.
351
            config_nBE_out <= "1100";
352
 
353
            config_data_out <= x"00000000";
354
            config_valid_r <= '1';
355
 
356
            if pad_cnt_r = 2 or pad_cnt_r = 3 then
357
              tx_state_r <= write_control_byte_and_last;
358
            end if;
359
 
360
            pad_cnt_r <= pad_cnt_r - 2;
361
          end if;
362
 
363
        when write_control_byte_and_last =>
364
          if comm_busy_in = '0' and config_valid_r = '0'  then
365
            if tx_data_cnt_r = 0 or tx_data_cnt_r = 2 then
366
              -- no odd byte.
367
              config_nBE_out <= "1100";
368
              config_data_out <= x"0000" & "00010000" & x"00";
369
              config_valid_r <= '1';
370
              tx_state_r <= enqueue_packet_number_to_tx_fifo;
371
            else
372
              if tx_data_valid_in = '1' or got_the_odd_r = '1' then
373
                config_nBE_out <= "1100";
374
                if got_the_odd_r = '1' then
375
                  config_data_out <= x"0000" & "00110000" & odd_r;
376
                else
377
                  config_data_out <= x"0000" & "00110000" & tx_data_in(7 downto 0);
378
                  tx_re_out <= '1';           -- read the odd byte.                  
379
                end if;
380
                config_valid_r <= '1';
381
                tx_state_r <= enqueue_packet_number_to_tx_fifo;
382
              end if;
383
            end if;
384
          end if;
385
 
386
        when enqueue_packet_number_to_tx_fifo =>
387
          if comm_busy_in = '0' and config_valid_r = '0' then
388
            reg_addr_out <= "000";
389
            read_not_write_out <= '0';
390
            config_data_out <= x"000000" & "11000000";
391
            config_valid_r <= '1';
392
            tx_state_r <= wait_tx;
393
            comm_req_r <= '0';
394
          end if;
395
 
396
        when others => null;
397
      end case;                     -- tx_state_r
398
    end if;
399
  end process main;
400
 
401
 
402
end rtl;

powered by: WebSVN 2.1.0

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