OpenCores
URL https://opencores.org/ocsvn/mesi_isc/mesi_isc/trunk

Subversion Repositories mesi_isc

[/] [mesi_isc/] [trunk/] [src/] [rtl/] [mesi_isc_broad_cntl.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 yaira
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
4
////                                                              ////
5
//// This source file may be used and distributed without         ////
6
//// restriction provided that this copyright statement is not    ////
7
//// removed from the file and that any derivative work contains  ////
8
//// the original copyright notice and the associated disclaimer. ////
9
////                                                              ////
10
//// This source file is free software; you can redistribute it   ////
11
//// and/or modify it under the terms of the GNU Lesser General   ////
12
//// Public License as published by the Free Software Foundation; ////
13
//// either version 2.1 of the License, or (at your option) any   ////
14
//// later version.                                               ////
15
////                                                              ////
16
//// This source is distributed in the hope that it will be       ////
17
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
18
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
19
//// PURPOSE.  See the GNU Lesser General Public License for more ////
20
//// details.                                                     ////
21
////                                                              ////
22
//// You should have received a copy of the GNU Lesser General    ////
23
//// Public License along with this source; if not, download it   ////
24
//// from http://www.opencores.org/lgpl.shtml                     ////
25
////                                                              ////
26
//////////////////////////////////////////////////////////////////////
27
 
28
//////////////////////////////////////////////////////////////////////
29
////                                                              ////
30
////  MESI_ISC Project                                            ////
31
////                                                              ////
32
////  Author(s):                                                  ////
33
////      - Yair Amitay       yair.amitay@yahoo.com               ////
34
////                          www.linkedin.com/in/yairamitay      ////
35
////                                                              ////
36
////  Description                                                 ////
37
////  mesi_isc_broad_cntl                                          ////
38
////  -------------------                                         ////
39
////                                                              ////
40
////                                                              ////
41
////  To Do:                                                      ////
42
////   -                                                          ////
43
////                                                              ////
44
//////////////////////////////////////////////////////////////////////
45
 
46
`include "mesi_isc_define.v"
47
 
48
module mesi_isc_broad_cntl
49
    (
50
     // Inputs
51
     clk,
52
     rst,
53
     cbus_ack_array_i,
54
     fifo_status_empty_i,
55
     fifo_status_full_i,
56
     broad_snoop_type_i,
57
     broad_snoop_cpu_id_i,
58
     broad_snoop_id_i,
59
     // Outputs
60
     cbus_cmd_array_o,
61
     broad_fifo_rd_o
62
     );
63
parameter
64
  CBUS_CMD_WIDTH           = 3,
65
  BROAD_TYPE_WIDTH         = 2,
66
  BROAD_ID_WIDTH           = 5;
67
 
68
// Inputs
69
//================================
70
// System
71
input                   clk;          // System clock
72
input                   rst;          // Active high system reset
73
// Coherence buses
74
input [3:0]             cbus_ack_array_i;
75
// broad_fifo
76
input                   fifo_status_empty_i;
77
input                   fifo_status_full_i;
78
// broad_fifo
79
input [BROAD_TYPE_WIDTH-1:0] broad_snoop_type_i; // The type of the broad
80
input [1:0]             broad_snoop_cpu_id_i; // The ID of the initiator CPU
81
input [BROAD_ID_WIDTH-1:0] broad_snoop_id_i; // The ID of the broad
82
 
83
// Outputs
84
//================================
85
output [4*CBUS_CMD_WIDTH-1:0] cbus_cmd_array_o; // Command for coherence bus.
86
                                      // write broadcast, read broadcast, write
87
                                      // enable or read enable 
88
// fifo
89
output                  broad_fifo_rd_o;
90
 
91
// Regs & wires
92
//================================
93
wire [CBUS_CMD_WIDTH-1:0] cbus_cmd3;  // Command for coherence bus.
94
wire [CBUS_CMD_WIDTH-1:0] cbus_cmd2;  // Command for coherence bus.
95
wire [CBUS_CMD_WIDTH-1:0] cbus_cmd1;  // Command for coherence bus.
96
wire [CBUS_CMD_WIDTH-1:0] cbus_cmd0;  // Command for coherence bus.
97
reg                       broadcast_in_progress; // A broadcast process
98
                                      // contains 2 stages. The first stage is 
99
                                      // to send read or write broadcast to
100
                                      // all CPUs and to receive an
101
                                      // acknowledge for each one. The second
102
                                      // stage is to send an
103
                                      // enable-access to the initiator CPU. 
104
reg  [3:0]                cbus_active_broad_array; // For each bit, when high a
105
                                      // broad access is sent to the CPU
106
reg  [3:0]                cbus_active_en_access_array; // For each bit, when
107
                                      // hing a enable-access is sent to the
108
                                      // CPU
109
reg                       broad_fifo_rd_o; // output
110
wire [3:0]                cbus_active_en_access_and_not_cbus_ack_array;
111
 
112
 
113
//cbus_cmd
114
assign cbus_cmd_array_o[(3+1)*CBUS_CMD_WIDTH-1 : 3*CBUS_CMD_WIDTH] = cbus_cmd3;
115
assign cbus_cmd_array_o[(2+1)*CBUS_CMD_WIDTH-1 : 2*CBUS_CMD_WIDTH] = cbus_cmd2;
116
assign cbus_cmd_array_o[(1+1)*CBUS_CMD_WIDTH-1 : 1*CBUS_CMD_WIDTH] = cbus_cmd1;
117
assign cbus_cmd_array_o[(0+1)*CBUS_CMD_WIDTH-1 : 0*CBUS_CMD_WIDTH] = cbus_cmd0;
118
 
119
// The command of the coherence bus is define according to the state of 
120
// cbus_active_broad_array and cbus_active_en_access_array
121
       //     \ /
122
assign cbus_cmd3 =
123
         // The broadcast proccess is active. Send the broadcast request 
124
         //                     \ /
125
         cbus_active_broad_array[3] ?
126
           broad_snoop_type_i == `MESI_ISC_BREQ_TYPE_WR ?
127
                                           `MESI_ISC_CBUS_CMD_WR_SNOOP:
128
                                           `MESI_ISC_CBUS_CMD_RD_SNOOP     :
129
         // All the broadcast proccesses were done. This CPU is the initiator
130
         // of the request. Enable it to continue by send en_wr/en_rd
131
         !(|cbus_active_broad_array)    &
132
         //                         \ /
133
         cbus_active_en_access_array[3] &
134
         ~broad_fifo_rd_o ?
135
           broad_snoop_type_i == `MESI_ISC_BREQ_TYPE_WR ?
136
                                           `MESI_ISC_CBUS_CMD_EN_WR:
137
                                           `MESI_ISC_CBUS_CMD_EN_RD        :
138
                                           `MESI_ISC_CBUS_CMD_NOP;
139
       //     \ /
140
assign cbus_cmd2 =
141
         //                     \ /
142
         cbus_active_broad_array[2] ?
143
           broad_snoop_type_i == `MESI_ISC_BREQ_TYPE_WR ?
144
                                           `MESI_ISC_CBUS_CMD_WR_SNOOP:
145
                                           `MESI_ISC_CBUS_CMD_RD_SNOOP     :
146
         !(|cbus_active_broad_array)    &
147
         //                         \ /
148
         cbus_active_en_access_array[2] &
149
         ~broad_fifo_rd_o ?
150
           broad_snoop_type_i == `MESI_ISC_BREQ_TYPE_WR ?
151
                                           `MESI_ISC_CBUS_CMD_EN_WR:
152
                                           `MESI_ISC_CBUS_CMD_EN_RD        :
153
                                           `MESI_ISC_CBUS_CMD_NOP;
154
       //     \ /
155
assign cbus_cmd1 =
156
         //                     \ /
157
         cbus_active_broad_array[1] ?
158
           broad_snoop_type_i == `MESI_ISC_BREQ_TYPE_WR ?
159
                                           `MESI_ISC_CBUS_CMD_WR_SNOOP:
160
                                           `MESI_ISC_CBUS_CMD_RD_SNOOP     :
161
         !(|cbus_active_broad_array)    &
162
         //                         \ /
163
         cbus_active_en_access_array[1] &
164
         ~broad_fifo_rd_o ?
165
           broad_snoop_type_i == `MESI_ISC_BREQ_TYPE_WR ?
166
                                           `MESI_ISC_CBUS_CMD_EN_WR:
167
                                           `MESI_ISC_CBUS_CMD_EN_RD        :
168
                                           `MESI_ISC_CBUS_CMD_NOP;
169
       //     \ /
170
assign cbus_cmd0 =
171
         // Send read or write broad according to the type of the broad.
172
         //                     \ /
173
         cbus_active_broad_array[0] ?
174
           broad_snoop_type_i == `MESI_ISC_BREQ_TYPE_WR ?
175
                                           `MESI_ISC_CBUS_CMD_WR_SNOOP:
176
                                           `MESI_ISC_CBUS_CMD_RD_SNOOP     :
177
         !(|cbus_active_broad_array)    &
178
         //                         \ /
179
         cbus_active_en_access_array[0] &
180
         ~broad_fifo_rd_o ?
181
           broad_snoop_type_i == `MESI_ISC_BREQ_TYPE_WR ?
182
                                           `MESI_ISC_CBUS_CMD_EN_WR:
183
                                           `MESI_ISC_CBUS_CMD_EN_RD        :
184
 
185
                                           `MESI_ISC_CBUS_CMD_NOP;
186
 
187
 
188
// A broadcast process contains 5 sub-processes: Each one of the 4 CPU receives
189
// a snoop request and answers with an acknowledge. Then the initiator CPU
190
// receives an access enable and answer  answers with an acknowledge.
191
//
192
// The broadcast process *stages* are:
193
// 1. Curently there is no an active process. If there is a valid broadcast to
194
//  send then:
195
// 1.1 broadcast_in_progress   <= 1 : It represents an active process of
196
//     broadcast. It contains 4 snoop sub-processes and 1 enable sub-process. 
197
// 1.2 cbus_active_broad_array <= 4'b1111 : Each bit represents an active
198
//     sub-process, for each CPU - sending a snoop request and get an answer
199
//     with an acknowledge.
200
// 1.3 cbus_active_en_access_array[ID of initiator CPU] <= 1
201
//     The corresponding bit of the initiator CPU in the
202
//     cbus_active_en_access_array is set to enable in stage 4 to send an
203
//     enable-access to the initiator CPU.
204
// 2. cbus_active_broad_array[ID of CPU] <= 0
205
//    A snoop request is send for all the CPUs. For each CPU that answers with
206
//    acknowledge the corresponding bit is clear:
207
//    cbus_active_broad_array == 0
208
//    After all CPUs answer with acknowledge all the bits of 
209
//    cbus_active_broad_array are clear.
210
// 3. cbus_active_en_access_array[ID of initiator CPU] <= 0
211
//    broadcast_in_progress                            <= 0
212
//    The enable access is sent to the initiator CPU. When it answers with an
213
//    acknowledge then the broadcast process is finished:  the corresponding
214
//    bit in the cbus_active_en_access_array is clear and
215
//    the broadcast_in_progress is clear
216
//
217
//
218
// broadcast_in_progress
219
// There is an active action of the broadcast. Either not all CPU received the
220
// broadcast and return acknowledge. or the initiator CPU received the access
221
// enable and return acknowledge. 
222
//
223
// cbus_active_broad_array
224
// For each bit, when set - there is an active process of sending a snoop
225
// request and answering with an acknowledge.
226
// 
227
// cbus_active_en_access_array
228
// For each bit, when set -  there is an active process of sending 
229
// enable-access request to the initiator CPU and receive an acknowledge answer.
230
// The enable-access request is send only after all CPUs receive and approve
231
// the snoop requests.
232
//
233
// broad_fifo_rd_o
234
// When broadcast process in finish clear the corresponding entry from the fifo
235
always @(posedge clk or posedge rst)
236
  if (rst)
237
  begin
238
        broadcast_in_progress       <= 0;
239
        cbus_active_broad_array     <= 4'b0000;
240
        cbus_active_en_access_array <= 4'b0000;
241
        broad_fifo_rd_o             <= 0;
242
  end
243
  else if (~broadcast_in_progress & ~broad_fifo_rd_o)
244
    if (~fifo_status_empty_i)
245
    // Stage 1
246
      begin
247
        broadcast_in_progress       <= 1;
248
        case (broad_snoop_cpu_id_i) // The initiator does not received a
249
                                    // broadcast for the same line it asks the
250
                                    // broadcast
251
          0:
252
          begin
253
            cbus_active_broad_array     <= 4'b1110;
254
            cbus_active_en_access_array <= 4'b0001;
255
          end
256
          1:
257
          begin
258
            cbus_active_broad_array     <= 4'b1101;
259
            cbus_active_en_access_array <= 4'b0010;
260
          end
261
          2:
262
          begin
263
            cbus_active_broad_array     <= 4'b1011;
264
            cbus_active_en_access_array <= 4'b0100;
265
          end
266
          3:
267
          begin
268
            cbus_active_broad_array     <= 4'b0111;
269
            cbus_active_en_access_array <= 4'b1000;
270
          end
271
          default
272
          begin
273
            cbus_active_broad_array     <= 4'b0000;
274
            cbus_active_en_access_array <= 4'b0000;
275
          end
276
        endcase
277
        broad_fifo_rd_o             <= 0;
278
      end
279
    else // if (~fifo_status_empty_i)
280
    begin
281
        broadcast_in_progress       <= 0;
282
        cbus_active_broad_array     <= 4'b0000;
283
        cbus_active_en_access_array <= 4'b0000;
284
        broad_fifo_rd_o             <= 0;
285
    end
286
  else // if (~broadcast_in_progress)
287
    // Stage 2
288
    if (|cbus_active_broad_array)     // There is at least on active snoop
289
                                      //  sub-process
290
      begin
291
        broadcast_in_progress       <= 1;
292
        // Clear related sub-process of a CPU then returns ack for the snoop
293
        // request.
294
        cbus_active_broad_array     <= cbus_active_broad_array &
295
                                       ~cbus_ack_array_i;
296
        cbus_active_en_access_array <= cbus_active_en_access_array;
297
        broad_fifo_rd_o             <= 0;
298
      end
299
    // Stage 3
300
    else if (broad_fifo_rd_o)         // All snoop sub-process were done
301
      begin
302
        broadcast_in_progress       <= 0;
303
        cbus_active_broad_array     <= 0;
304
        cbus_active_en_access_array <= 0;
305
        broad_fifo_rd_o             <= 0;
306
      end
307
    else
308
      broad_fifo_rd_o <= !(|(cbus_active_en_access_and_not_cbus_ack_array));
309
 
310
assign cbus_active_en_access_and_not_cbus_ack_array =
311
        cbus_active_en_access_array  & ~cbus_ack_array_i;
312
 
313
 
314
endmodule

powered by: WebSVN 2.1.0

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