vme_cli_arb.vhd 7.16 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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;

    -- 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;

    -- 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
79
    signal vc_int_berr_ok          : out std_logic
80

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

Håkan Johansson's avatar
Håkan Johansson committed
84
85
--    signal stop                 : in std_logic;
--    signal int_err_clear        : in std_logic;
86

Håkan Johansson's avatar
Håkan Johansson committed
87
--    signal int_data_ack : in std_logic;
88

Håkan Johansson's avatar
Håkan Johansson committed
89
--    -- Changed behaviour:
90

Håkan Johansson's avatar
Håkan Johansson committed
91
92
--    -- Single-cycle strobe:
--    signal int_data_strobe      : out std_logic := c_DATA_CLEAR;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

    
    );
end entity;



architecture rtl of vme_cli_arb is

  signal state          : vme_data_state := STOPPED;
  signal addr_mode      : addr_type_t;
  signal transfer_mode  : transfer_type_t;



  -- 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?
  signal prefer_1       : std_logic := '1';

begin

  want_1 <= (go_1 and not go_2) or (go_1 and     prefer_1);
  want_2 <= (go_2 and not go_1) or (go_2 and not prefer_1);

  start_1 <= not busy and want_1;
  start_2 <= not busy and want_2;

  -- We kill the live assignment as soon as busy is removed.
  -- (Not really needed.)
  live_1 <= (active_1 and busy) or start_1;
  live_2 <= (active_2 and busy) or start_2;
  
  process (clk)
  begin
    if (rising_edge(clk)) then

      if (not busy) then
        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;

    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.
  
  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_cont    <= p1_int_blt_cont    when live_1 else p2_int_blt_cont;
  vc_int_berr_ok     <= p1_int_berr_ok     when live_1 else p2_int_berr_ok;

  -- Signals to the clients from the VME core:

  -- Data is passed directly through on the cycle they have been latched.
  -- Otherwise, take the latched value:
  p1_int_data_o <= vc_int_data_o when (live_1 and vc_int_data_strobe) else
                   p1_int_data_o_latched;
  p2_int_data_o <= vc_int_data_o when (live_2 and vc_int_data_strobe) else
                   p2_int_data_o_latched;
  -- The error code follows the data.
  p1_int_err_code <= vc_int_err_code when (live_1 and vc_int_data_strobe) else
                     p1_int_err_code_latched;
  p2_int_err_code <= vc_int_err_code when (live_2 and vc_int_data_strobe) else
                     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...)
  p1_busy <= live_1;
  p2_busy <= live_2;

end architecture;