vme_cli_arb.vhd 8.34 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
library ieee;
use ieee.std_logic_1164.all;
use work.vme_pkg.all;

-- Multiplex signals between the VME core and two clients.
--
-- Each client sees signals such as if it was the only
-- client connected to the core.  (With the exception that it
-- may take a longer time before a 'go' request starts
-- to be processed).

entity vme_cli_arb is
  port (
    signal clk      : in std_logic;

    -- Signals to/from the first client.
    -- For documentation on the signal purposes, see vme_bus.vhd.

    signal p1_busy                 : out std_logic := '0';

    signal p1_int_data_o           : out vme_vec_64_t;
    signal p1_int_data_strobe      : out std_logic := c_DATA_CLEAR;
    signal p1_int_go_consumed_strobe : out std_logic := '0';
    signal p1_int_blt_decision_strobe : out std_logic := '0';
    signal p1_int_err_code         : out ERR_CODE := OK;    
    
    signal p1_int_addr             : in vme_addr_t;
    signal p1_int_data_i           : in vme_vec_64_t;
    signal p1_int_am_i             : in am_vec_t;
    signal p1_int_vme_rw           : in std_logic;
    signal p1_int_vme_go           : in std_logic;

    signal p1_int_blt_decided      : in std_logic;
    signal p1_int_blt_continue     : in std_logic;    

    signal p1_int_berr_ok          : in std_logic;

Michael Munch's avatar
Michael Munch committed
38
39
    signal p1_go                  : in std_logic;

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    -- Signals to/from the second client.
    
    signal p2_busy                 : out std_logic := '0';

    signal p2_int_data_o           : out vme_vec_64_t;
    signal p2_int_data_strobe      : out std_logic := c_DATA_CLEAR;
    signal p2_int_go_consumed_strobe : out std_logic := '0';
    signal p2_int_blt_decision_strobe : out std_logic := '0';
    signal p2_int_err_code         : out ERR_CODE := OK;    
    
    signal p2_int_addr             : in vme_addr_t;
    signal p2_int_data_i           : in vme_vec_64_t;
    signal p2_int_am_i             : in am_vec_t;
    signal p2_int_vme_rw           : in std_logic;
    signal p2_int_vme_go           : in std_logic;

    signal p2_int_blt_decided      : in std_logic;
    signal p2_int_blt_continue     : in std_logic;    

    signal p2_int_berr_ok          : in std_logic;

Michael Munch's avatar
Michael Munch committed
61
62
    signal p2_go                  : in std_logic;    

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
    -- Signals to/from the VME core.
    -- Directions inverted relative to the core.

    signal vc_busy                 : in std_logic := '0';

    signal vc_int_data_o           : in vme_vec_64_t;
    signal vc_int_data_strobe      : in std_logic := c_DATA_CLEAR;
    signal vc_int_go_consumed_strobe : in std_logic := '0';
    signal vc_int_blt_decision_strobe : in std_logic := '0';
    signal vc_int_err_code         : in ERR_CODE := OK;    
    
    signal vc_int_addr             : out vme_addr_t;
    signal vc_int_data_i           : out vme_vec_64_t;
    signal vc_int_am_i             : out am_vec_t;
    signal vc_int_vme_rw           : out std_logic;
    signal vc_int_vme_go           : out std_logic;

    signal vc_int_blt_decided      : out std_logic;
    signal vc_int_blt_continue     : out std_logic;    

Håkan Johansson's avatar
Håkan Johansson committed
83
    signal vc_int_berr_ok          : out std_logic
84

Håkan Johansson's avatar
Håkan Johansson committed
85
86
--    -- Dropped signals (since they cannot be multiplexed /
--    -- span multiple access cycles).
87

Håkan Johansson's avatar
Håkan Johansson committed
88
89
--    signal stop                 : in std_logic;
--    signal int_err_clear        : in std_logic;
90

Håkan Johansson's avatar
Håkan Johansson committed
91
--    signal int_data_ack : in std_logic;
92

Håkan Johansson's avatar
Håkan Johansson committed
93
--    -- Changed behaviour:
94

Håkan Johansson's avatar
Håkan Johansson committed
95
96
--    -- Single-cycle strobe:
--    signal int_data_strobe      : out std_logic := c_DATA_CLEAR;
97
98
99
100
101
102
103
104
105

    
    );
end entity;



architecture rtl of vme_cli_arb is

Michael Munch's avatar
Michael Munch committed
106
107
108
  -- signal state          : vme_data_state := STOPPED;
  -- signal addr_mode      : addr_type_t;
  -- signal transfer_mode  : transfer_type_t;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130



  -- In case we are not busy, which client would we like to
  -- make active (if any).
  signal want_1         : boolean;
  signal want_2         : boolean;

  -- Who do we start?
  signal start_1         : boolean;
  signal start_2         : boolean;

  -- Who is live, i.e. is active, or activated this cycle.
  signal live_1         : boolean;
  signal live_2         : boolean;

  -- Who is currently live.
  signal active_1       : boolean := false;
  signal active_2       : boolean := false;

  -- Who will we prefer when we can take the next client, i.e. are
  -- no longer busy?
Michael Munch's avatar
Michael Munch committed
131
132
133
134
  signal prefer_1       : boolean := false;

  signal p1_int_data_o_latched   : vme_vec_64_t;
  signal p2_int_data_o_latched   : vme_vec_64_t;
135

Michael Munch's avatar
Michael Munch committed
136
137
  signal p1_int_err_code_latched : ERR_CODE := OK;
  signal p2_int_err_code_latched : ERR_CODE := OK;      
138
139
begin

Michael Munch's avatar
Michael Munch committed
140
141
  want_1 <= (p1_go = '1' and p2_go  = '0') or (p1_go = '1' and     prefer_1);
  want_2 <= (p2_go = '1' and p1_go  = '0') or (p2_go = '1' and not prefer_1);
142

Michael Munch's avatar
Michael Munch committed
143
144
  start_1 <= vc_busy = '0' and want_1;
  start_2 <= vc_busy = '0' and want_2;
145
146
147

  -- We kill the live assignment as soon as busy is removed.
  -- (Not really needed.)
Michael Munch's avatar
Michael Munch committed
148
149
  live_1 <= (active_1 and vc_busy = '1') or start_1;
  live_2 <= (active_2 and vc_busy = '1') or start_2;
150
151
152
153
154
  
  process (clk)
  begin
    if (rising_edge(clk)) then

Michael Munch's avatar
Michael Munch committed
155
      if (vc_busy = '0') then
156
157
158
159
160
161
162
163
164
165
166
167
168
169
        active_1 <= false;
        active_2 <= false;
      end if;
      -- These assignments may overwrite the above, if we take another
      -- client directly.
      if (start_1) then
        active_1 <= true;
        prefer_1 <= false;
      end if;
      if (start_2) then
        active_2 <= true;
        prefer_1 <= true;
      end if;

170
171
172
      -- We select on active instead of live, since active is cheaper (comes
      -- directly from a flip-flop, instead of logic), and
      -- vc_int_data_strobe will not come on the first cycle. 
Michael Munch's avatar
Michael Munch committed
173
      if (active_1 and vc_int_data_strobe = '1') then
174
175
176
        p1_int_data_o_latched   <= vc_int_data_o;
        p1_int_err_code_latched <= vc_int_err_code;
      end if;
Michael Munch's avatar
Michael Munch committed
177
      if (active_2 and vc_int_data_strobe = '1') then
178
179
180
181
        p2_int_data_o_latched   <= vc_int_data_o;
        p2_int_err_code_latched <= vc_int_err_code;
      end if;

182
183
184
185
186
187
188
189
190
191
    end if;
  end process;


  -- Signals to the VME core are taken from the live client:
  
  -- If no client is live, we (arbitrarily) take the signals from
  -- client 2.  This does not matter, since the VME core will
  -- only react to anything if the 'go' signal is given.
  
Michael Munch's avatar
Michael Munch committed
192
193
194
195
196
197
198
199
  vc_int_addr         <= p1_int_addr          when live_1 else p2_int_addr;
  vc_int_data_i       <= p1_int_data_i        when live_1 else p2_int_data_i;
  vc_int_am_i         <= p1_int_am_i          when live_1 else p2_int_am_i;
  vc_int_vme_rw       <= p1_int_vme_rw        when live_1 else p2_int_vme_rw;
  vc_int_vme_go       <= p1_int_vme_go        when live_1 else p2_int_vme_go;
  vc_int_blt_decided  <= p1_int_blt_decided   when live_1 else p2_int_blt_decided;
  vc_int_blt_continue <= p1_int_blt_continue  when live_1 else p2_int_blt_continue;
  vc_int_berr_ok      <= p1_int_berr_ok       when live_1 else p2_int_berr_ok;
200
201
202

  -- Signals to the clients from the VME core:

203
204
205
206
  -- TODO: All the selects below could use active_1 / active_2 instead
  -- of live_1 / live_2, since the signals from the VME core
  -- will not happen on the first cycle we are active!
  
207
208
  -- Data is passed directly through on the cycle they have been latched.
  -- Otherwise, take the latched value:
Michael Munch's avatar
Michael Munch committed
209
  p1_int_data_o <= vc_int_data_o when (live_1 and vc_int_data_strobe = '1') else
210
                   p1_int_data_o_latched;
Michael Munch's avatar
Michael Munch committed
211
  p2_int_data_o <= vc_int_data_o when (live_2 and vc_int_data_strobe = '1') else
212
213
                   p2_int_data_o_latched;
  -- The error code follows the data.
Michael Munch's avatar
Michael Munch committed
214
  p1_int_err_code <= vc_int_err_code when (live_1 and vc_int_data_strobe = '1') else
215
                     p1_int_err_code_latched;
Michael Munch's avatar
Michael Munch committed
216
  p2_int_err_code <= vc_int_err_code when (live_2 and vc_int_data_strobe = '1') else
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
                     p2_int_err_code_latched;

  -- The strobes always go to the live client.
  p1_int_data_strobe <= vc_int_data_strobe when live_1 else '0';
  p2_int_data_strobe <= vc_int_data_strobe when live_2 else '0';

  p1_int_go_consumed_strobe <= vc_int_go_consumed_strobe when live_1 else '0';
  p2_int_go_consumed_strobe <= vc_int_go_consumed_strobe when live_2 else '0';

  p1_int_blt_decision_strobe <= vc_int_blt_decision_strobe when live_1 else '0';
  p2_int_blt_decision_strobe <= vc_int_blt_decision_strobe when live_2 else '0';

  -- The busy of a client is simply while it is live.
  -- This actually means that we will report busy some cycles
  -- early.  (But the clients are not likely to use this signal...)
Michael Munch's avatar
Michael Munch committed
232
233
  p1_busy <= '1' when live_1 else '0';
  p2_busy <= '1' when live_2 else '0';
234
235
236
237
238

end architecture;