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_comm_module.vhd] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
-------------------------------------------------------------------------------
2
-- Title      : Communication module for the LAN91C111 controller
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : Lan91c111_comm_module.vhd
6
-- Author     : Jussi Nieminen, Antti Alhonen
7
-- Last update: 2011-11-06
8
-------------------------------------------------------------------------------
9
-- Description: 
10
-------------------------------------------------------------------------------
11
-- Revisions  :
12
-- Date        Version  Author  Description
13
-- 2009/08/21  1.0      niemin95        Created
14
-- 2011/07/17  2.0      alhonena        Modified for LAN91C111
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
entity lan91c111_comm_module is
23
  port (
24
    clk                    : in    std_logic;  -- 25 MHz
25
    rst_n                  : in    std_logic;
26
    comm_requests_in       : in    std_logic_vector( submodules_c-1 downto 0 );
27
    comm_grants_out        : out   std_logic_vector( submodules_c-1 downto 0 );
28
    interrupt_out          : out   std_logic;
29
    init_ready_in          : in    std_logic;
30
    -- interface to submodules (and to init block)
31
    register_addrs_in      : in    std_logic_vector( (submodules_c+1) * real_addr_width_c - 1 downto 0 );  -- from each submodule
32
    config_datas_in        : in    std_logic_vector( (submodules_c+1) * lan91_data_width_c - 1 downto 0 );
33
    config_nBEs_in         : in    std_logic_vector( (submodules_c+1) * 4 - 1 downto 0 );
34
    read_not_write_in      : in    std_logic_vector( submodules_c downto 0 );
35
    configs_valid_in       : in    std_logic_vector( submodules_c downto 0 );
36
    data_to_submodules_out : out   std_logic_vector( lan91_data_width_c - 1 downto 0 );
37
    data_to_sb_valid_out   : out   std_logic;
38
    busy_to_submodules_out : out   std_logic;
39
    -- interface to LAN91C111
40
    eth_data_inout         : inout std_logic_vector( lan91_data_width_c-1 downto 0 );
41
    eth_addr_out           : out   std_logic_vector( lan91_addr_width_c-1 downto 0 );
42
    eth_interrupt_in       : in    std_logic;
43
    eth_read_out           : out   std_logic;
44
    eth_write_out          : out   std_logic;
45
    eth_nADS_out           : out   std_logic;
46
    eth_nAEN_out           : out   std_logic;
47
    eth_nBE_out            : out   std_logic_vector(3 downto 0)
48
    );
49
 
50
end lan91c111_comm_module;
51
 
52
 
53
architecture rtl of lan91c111_comm_module is
54
 
55
  -- Major change compared to DM9000A controller by Jussi Nieminen;
56
  -- Data muxes between "config_data", "tx data" and "rx data" have
57
  -- been moved completely to the Send and Read modules; this module takes only
58
  -- one type of input from Send and Read, not two types. Hence, this
59
  -- module is simplified a lot.
60
  -- The major reason for the change is that whereas DM9000A does not include
61
  -- "register address" for every write/read operation, LAN91C111 does; all
62
  -- data is accessed via a single register address, pointed by a separate
63
  -- pointer register with its own address.
64
 
65
  -- WRITING AND READING PROCEDURES by comm_state_r
66
  -- wait_valid:
67
  -- Wait until one of the submodules wants to write or read. Immediately put
68
  -- the address (and data in case of write) on the busses and go to write_data
69
  -- or read_data, which asserts write or read enable signal to the chip.
70
  --
71
  -- write_data:
72
  -- Set write_out low. Go to data_written.
73
  --
74
  -- read_data:
75
  -- Set read_out low. Go to data_read.
76
  --
77
  -- data_written:
78
  -- Set write_out high. Go to wait_valid.
79
  --
80
  -- data_read:
81
  -- Read the data. Set read_out high. Go to wait_valid.
82
  --
83
  -- Example of the read operation:
84
  --                  |1 |2 |3 |4 |5 |6 |
85
  -- config_valid_in  ___----------------
86
  -- readnotwrite     ___----------------
87
  -- addr_out         xxxxxx< ADDR  >xxxx  (valid for 3 cycles)
88
  -- data_out         xxxxxxZZZZZZZZZxxxx  (valid for 3 cycles)
89
  -- nEth_read_out    ---------___------   (1 cycle long in the middle)
90
  -- Read data here:             <>        (on the rising edge of read enable signal)
91
  --
92
  -- Example of the write operation:
93
  --                  |1 |2 |3 |4 |5 |6 |
94
  -- config_valid_in  ___----------------
95
  -- readnotwrite     ___________________
96
  -- addr_out         xxxxxx< ADDR  >xxxx  (valid for 3 cycles)
97
  -- data_out         xxxxxx< DATA  >xxxx  (valid for 3 cycles)
98
  -- nEth_write_out   ---------___------   (1 cycle long in the middle)
99
 
100
 
101
  type comm_state_type is (wait_valid, write_data, data_written, read_data, data_read);
102
  signal comm_state_r : comm_state_type;
103
 
104
  -- Arbiter side selects one of the incoming communication requests and feeds
105
  -- data to these:
106
  signal register_addr  : std_logic_vector( real_addr_width_c-1 downto 0 );
107
  signal config_data    : std_logic_vector( lan91_data_width_c-1 downto 0 );
108
  signal config_nBE : std_logic_vector( 3 downto 0 );
109
  signal read_not_write : std_logic;    -- 1 = read, 0 = write
110
  signal config_valid   : std_logic;
111
 
112
  signal comm_grants_r : std_logic_vector( submodules_c-1 downto 0 );
113
 
114
-------------------------------------------------------------------------------
115
begin  -- rtl
116
-------------------------------------------------------------------------------
117
 
118
  -- concurrent assignments
119
  comm_grants_out   <= comm_grants_r;
120
  interrupt_out     <= eth_interrupt_in;
121
  eth_nADS_out      <= '0';
122
  eth_nAEN_out      <= '0';
123
 
124
  arbitration: process (clk, rst_n)
125
    variable reserved_v : std_logic;
126
  begin  -- process arbitration
127
    if rst_n = '0' then                 -- asynchronous reset (active low)
128
 
129
      comm_grants_r <= (others => '0');
130
 
131
    elsif clk'event and clk = '1' then  -- rising clock edge
132
 
133
      reserved_v := '0';
134
 
135
      if init_ready_in = '1' then
136
        -- can't use 'others' in comparison, so we do it this way
137
        if comm_grants_r = std_logic_vector( to_unsigned( 0, submodules_c )) then
138
 
139
          -- no one is using comm_module right now
140
          -- lowest index wins
141
          for n in 0 to submodules_c-1 loop
142
            if comm_requests_in(n) = '1' then
143
              if reserved_v = '0' then
144
                comm_grants_r(n) <= '1';
145
                reserved_v := '1';
146
              end if;
147
            end if;
148
          end loop;  -- n
149
 
150
        else
151
 
152
          -- clear grant when request goes out
153
          for n in 0 to submodules_c-1 loop
154
            if comm_grants_r(n) = '1' and comm_requests_in(n) = '0' then
155
              comm_grants_r(n) <= '0';
156
            end if;
157
          end loop;  -- n
158
 
159
        end if;
160
 
161
      else
162
      -- no grants during initialization
163
        comm_grants_r <= (others => '0');
164
      end if;
165
 
166
    end if;
167
  end process arbitration;
168
 
169
 
170
  submodule_mux: process (comm_grants_r, register_addrs_in, config_datas_in, config_nBEs_in,
171
                          read_not_write_in, configs_valid_in, init_ready_in)
172
  begin  -- process submodule_mux
173
 
174
    if init_ready_in = '0' then
175
 
176
      -- init block has the highest index, but it doesn't compete for it's turn
177
      register_addr <= register_addrs_in( (submodules_c+1)*real_addr_width_c - 1 downto submodules_c*real_addr_width_c );
178
      config_data <= config_datas_in( (submodules_c+1)*lan91_data_width_c - 1 downto submodules_c*lan91_data_width_c );
179
      config_nBE  <= config_nBEs_in( (submodules_c+1)*4 - 1 downto submodules_c*4 );
180
      read_not_write <= read_not_write_in( submodules_c );
181
      config_valid <= configs_valid_in( submodules_c );
182
 
183
    else
184
      -- init ready, normal arbitration
185
 
186
      -- default:
187
      register_addr <= (others => '0');
188
      config_data <= (others => '0');
189
      config_nBE <= (others => '0');
190
      read_not_write <= '0';
191
      config_valid <= '0';
192
 
193
      -- grant signal decides
194
      for n in 0 to submodules_c-1 loop
195
 
196
        if comm_grants_r(n) = '1' then
197
          register_addr <= register_addrs_in( (n+1)*real_addr_width_c - 1 downto n*real_addr_width_c );
198
          config_data <= config_datas_in( (n+1)*lan91_data_width_c - 1 downto n*lan91_data_width_c );
199
          config_nBE <= config_nBEs_in( (n+1)*4 - 1 downto n*4 );
200
          read_not_write <= read_not_write_in(n);
201
          config_valid <= configs_valid_in(n);
202
        end if;
203
      end loop;  -- n
204
    end if;
205
 
206
  end process submodule_mux;
207
 
208
 
209
  lan91c111_communication: process (clk, rst_n)
210
  begin  -- process lan91c111_communication
211
    if rst_n = '0' then                 -- asynchronous reset (active low)
212
 
213
      eth_write_out  <= '1';
214
      eth_read_out     <= '1';
215
      eth_data_inout <= (others => 'Z');
216
 
217
      data_to_submodules_out <= (others => '0');
218
      data_to_sb_valid_out   <= '0';
219
      busy_to_submodules_out <= '0';
220
 
221
    elsif clk'event and clk = '1' then  -- rising clock edge
222
 
223
      -- defaults:
224
      eth_write_out        <= '1';        -- remember, active low
225
      eth_read_out         <= '1';
226
      data_to_sb_valid_out <= '0';        -- this is active high
227
 
228
      case comm_state_r is
229
        when wait_valid =>
230
          busy_to_submodules_out <= '0';
231
 
232
          if config_valid = '1' then
233
            busy_to_submodules_out <= '1';
234
            eth_addr_out <= base_addr_c & register_addr;
235
            if read_not_write = '1' then
236
              eth_data_inout <= (others => 'Z');
237
              comm_state_r <= read_data;
238
            else
239
              eth_data_inout <= config_data;
240
              comm_state_r <= write_data;
241
            end if;
242
 
243
            eth_nBE_out <= config_nBE;
244
 
245
          end if;
246
 
247
        when write_data =>
248
          eth_write_out <= '0';
249
          comm_state_r <= data_written;
250
 
251
        when data_written =>
252
          busy_to_submodules_out <= '0';
253
          comm_state_r <= wait_valid;
254
 
255
        when read_data =>
256
          eth_read_out <= '0';
257
          comm_state_r <= data_read;
258
 
259
        when data_read =>
260
          busy_to_submodules_out <= '0';
261
          -- read the data here:
262
          data_to_submodules_out <= eth_data_inout;
263
          data_to_sb_valid_out <= '1';  -- It is important that the
264
                                        -- busy_to_submodules_out goes low no
265
                                        -- later than valid goes high.
266
                                        -- Currently, the other modules rely on
267
                                        -- that to simplify the state machines.
268
 
269
          -- Also note that data_to_sb_valid_out is high only for one clock cycle
270
          -- and you must read the data immediately.
271
 
272
          -- eth_data_inout is left in high-impedance state. If needed for some
273
          -- reason, you can write something else to it here.
274
          comm_state_r <= wait_valid;
275
 
276
        when others => null;
277
      end case;
278
    end if;
279
  end process lan91c111_communication;
280
 
281
end rtl;

powered by: WebSVN 2.1.0

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