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

Subversion Repositories mesi_isc

[/] [mesi_isc/] [trunk/] [src/] [tb/] [mesi_isc_tb_cpu.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_tb_cpu                                             ////
38
////  -------------------                                         ////
39
////  Illustrate A coherence CPU with cache and 10 memory lines   ////
40
////                                                              ////
41
///  To Do:                                                       ////
42
////   -                                                          ////
43
////                                                              ////
44
//////////////////////////////////////////////////////////////////////
45
 
46
`include "mesi_isc_define.v"
47
`include "mesi_isc_tb_define.v"
48
 
49
module mesi_isc_tb_cpu
50
    (
51
     // Inputs
52
     clk,
53
     rst,
54
     cbus_addr_i,
55
     cbus_cmd_i,
56
     mbus_data_i,
57
     mbus_ack_i,
58
     cpu_id_i,
59
     tb_ins_i,
60
     tb_ins_addr_i,
61
     // Outputs
62
     mbus_cmd_o,
63
     mbus_addr_o,
64
     mbus_data_o,
65
     cbus_ack_o,
66
     tb_ins_ack_o
67
   );
68
 
69
parameter
70
  CBUS_CMD_WIDTH           = 3,
71
  ADDR_WIDTH               = 32,
72
  DATA_WIDTH               = 32,
73
  BROAD_TYPE_WIDTH         = 2,
74
  BROAD_ID_WIDTH           = 5,
75
  BROAD_REQ_FIFO_SIZE      = 4,
76
  BROAD_REQ_FIFO_SIZE_LOG2 = 2,
77
  MBUS_CMD_WIDTH           = 3,
78
  BREQ_FIFO_SIZE           = 2,
79
  BREQ_FIFO_SIZE_LOG2      = 1;
80
 
81
// Inputs
82
//================================
83
// System
84
input                   clk;          // System clock
85
input                   rst;          // Active high system reset
86
input [ADDR_WIDTH-1:0] cbus_addr_i;   // Coherence bus address. All busses have
87
                                      // the same address
88
input [CBUS_CMD_WIDTH-1:0] cbus_cmd_i; // Coherence bus3 command
89
input [DATA_WIDTH-1:0]  mbus_data_i; // Main bus read data
90
input                  mbus_ack_i;    // Main bus3 acknowledge
91
// tb
92
input [1:0]            cpu_id_i;
93
 
94
input [3:0]            tb_ins_i;      // Instruction for CPU to perform an
95
                                      // action
96
input [3:0]            tb_ins_addr_i; // Instruction address
97
// Outputs
98
//================================
99
// Main buses
100
output [MBUS_CMD_WIDTH-1:0] mbus_cmd_o; // Main bus3 command
101
output [ADDR_WIDTH-1:0]  mbus_addr_o;  // Coherence bus3 address
102
output [DATA_WIDTH-1:0]  mbus_data_o; // Main bus write data
103
// Coherence buses
104
output                   cbus_ack_o;  // Coherence bus3 acknowledge
105
// tb
106
output                   tb_ins_ack_o; // Acknowledge for the
107
                                      //  CPU instruction
108
 
109
 
110
// Regs & wires
111
//================================
112
reg                          tb_ins_ack_o;
113
reg  [31:0]              cache   [9:0];  // CPU cache
114
wire [31:0]              cache0;
115
wire [31:0]              cache1;
116
wire [31:0]              cache2;
117
wire [31:0]              cache3;
118
wire [31:0]              cache4;
119
wire [31:0]              cache5;
120
wire [31:0]              cache6;
121
wire [31:0]              cache7;
122
wire [31:0]              cache8;
123
wire [31:0]              cache9;
124
reg  [3:0]               cache_state [9:0];  // CPU cache MESI state
125
wire [3:0]               cache_state0;
126
wire [3:0]               cache_state1;
127
wire [3:0]               cache_state2;
128
wire [3:0]               cache_state3;
129
wire [3:0]               cache_state4;
130
wire [3:0]               cache_state5;
131
wire [3:0]               cache_state6;
132
wire [3:0]               cache_state7;
133
wire [3:0]               cache_state8;
134
wire [3:0]               cache_state9;
135
reg  [MBUS_CMD_WIDTH-1:0] mbus_cmd_o; // Main bus3 command
136
reg  [ADDR_WIDTH-1:0]    mbus_addr_o;  // Coherence bus3 address
137
reg  [2:0]               m_state;
138
reg  [7:0]               wr_data [5:0];
139
reg                      wr_proc_wait_for_en;
140
reg  [ADDR_WIDTH-1:0]    wr_proc_addr;
141
reg                      rd_proc_wait_for_en;
142
reg  [ADDR_WIDTH-1:0]    rd_proc_addr;
143
reg                      cbus_ack_o;  // Coherence bus3 acknowledge
144
reg                      m_state_c_state_priority;
145
reg  [3:0]               c_state;
146
reg  [ADDR_WIDTH-1:0]    m_addr;
147
reg  [ADDR_WIDTH-1:0]    c_addr;
148
reg  [DATA_WIDTH-1:0]    mbus_data_o; // Main bus write data
149
integer                  m_state_send_wr_br_counter,m_state_send_rd_br_counter;
150
integer                  i,j,k;     // Loop index
151
 
152
// GTKwave can't see arrays. points to array so GTKwave can see these signals
153
assign cache0 = cache[0];
154
assign cache1 = cache[1];
155
assign cache2 = cache[2];
156
assign cache3 = cache[3];
157
assign cache4 = cache[4];
158
assign cache5 = cache[5];
159
assign cache6 = cache[6];
160
assign cache7 = cache[7];
161
assign cache8 = cache[8];
162
assign cache9 = cache[9];
163
assign cache_state0 = cache_state[0];
164
assign cache_state1 = cache_state[1];
165
assign cache_state2 = cache_state[2];
166
assign cache_state3 = cache_state[3];
167
assign cache_state4 = cache_state[4];
168
assign cache_state5 = cache_state[5];
169
assign cache_state6 = cache_state[6];
170
assign cache_state7 = cache_state[7];
171
assign cache_state8 = cache_state[8];
172
assign cache_state9 = cache_state[9];
173
 
174
 
175
// initial
176
//================================  
177
initial
178
  for (i = 0; i < 10; i = i + 1)
179
  begin
180
    cache_state[i] = `MESI_ISC_TB_CPU_MESI_I;
181
  end
182
 
183
// m_state - Main bus state machine and
184
// c_state - Coherence bus state machine and
185
//================================  
186
//
187
//  m_state
188
//  ---------------------------------------------------
189
//  |                                                 |
190
//  -----> IDLE ----- m_state_c_state_priority == 0 ---
191
//          |
192
//          --------- m_state_c_state_priority == 1 ---
193
//                                                    |
194
//         Other states <------------------------------
195
//
196
//  c_state
197
//  ---------------------------------------------------
198
//  |                                                 |
199
//  -----> IDLE ----- m_state_c_state_priority == 1 ---
200
//          |
201
//          --------- m_state_c_state_priority == 0 ---
202
//                                                    |
203
//         Other states <------------------------------
204
 
205
// m_state_c_state_priority
206
//================================ 
207
// When set only m_state can start a process (move from IDLE state).   
208
// When clear only c_state can start a process (move from IDLE state).   
209
always @(posedge clk or posedge rst)
210
  if (rst) m_state_c_state_priority <= 0;
211
  else     m_state_c_state_priority <= ~m_state_c_state_priority;
212
 
213
// m_state    
214
// Main bus state machine
215
//================================  
216
//
217
//  -----------------------------------
218
//  | -------             |           |
219
//  | |     |             |           |
220
//  |----> IDLE --------> WR_CACHE    |
221
//          |                         |
222
//          |-----------> RD_CACHE ---|
223
//          |                         |
224
//          |        -------          |
225
//          |        |     |          |
226
//          |-----------> SEND_WR_BR -|
227
//          |                         |
228
//          |        -------          |
229
//          |        |     |          |
230
//          ------------> SEND_RD_BR -|
231
 
232
always @(posedge clk or posedge rst)
233
  if (rst)
234
  begin
235
            m_state                    <= `MESI_ISC_TB_CPU_M_STATE_IDLE;
236
            tb_ins_ack_o               <= 0;
237
            mbus_cmd_o                 <= `MESI_ISC_MBUS_CMD_NOP;
238
            wr_proc_wait_for_en        <= 0;
239
            wr_proc_addr               <= 0;
240
            rd_proc_wait_for_en        <= 0;
241
            rd_proc_addr               <= 0;
242
            m_state_send_wr_br_counter <= 0;
243
            m_state_send_rd_br_counter <= 0;
244
            for (k = 0; k < 6; k = k + 1)
245
              wr_data[k]               <= 1;
246
 
247
  end
248
  else case (m_state)
249
    `MESI_ISC_TB_CPU_M_STATE_IDLE:
250
    //----------------------------------
251
    begin
252
            m_state_send_wr_br_counter <= 0; // Clear the counter
253
            m_state_send_rd_br_counter <= 0; // Clear the counter
254
            tb_ins_ack_o      <= 0;   // Send ack when an action is finished
255
      // CBUS and MBUS can't be active in the same time. When CBUS is
256
      // active - wait.
257
      // If priority is not of m_state - stay on IDLE 
258
      if (c_state !=`MESI_ISC_TB_CPU_M_STATE_IDLE |
259
          !m_state_c_state_priority)
260
      begin
261
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_IDLE;
262
      end
263
      // Start the action when instruction is received and when there is not a
264
      // pending action - wait for en read or en wr
265
      else if ((tb_ins_i == `MESI_ISC_TB_INS_WR |
266
                tb_ins_i == `MESI_ISC_TB_INS_RD)  &
267
               ~wr_proc_wait_for_en               &
268
               ~rd_proc_wait_for_en)
269
      begin
270
            m_addr            <= tb_ins_addr_i; // Store the address of the
271
                                      // instruction
272
            mbus_addr_o       <= tb_ins_addr_i; // Send the ins address for a
273
                                      // case of an actual action.
274
        // Depends of the state of the cache line of the desired address,
275
        // define the action to perform
276
        case (cache_state[tb_ins_addr_i])
277
          // The cache state is Modify. Write to cache or read from cache.
278
          `MESI_ISC_TB_CPU_MESI_M:
279
            if (tb_ins_i == `MESI_ISC_TB_INS_WR)
280
            begin
281
               m_state        <= `MESI_ISC_TB_CPU_M_STATE_WR_CACHE;
282
               mbus_cmd_o     <= `MESI_ISC_MBUS_CMD_NOP;
283
            end
284
            else
285
            begin
286
               m_state        <= `MESI_ISC_TB_CPU_M_STATE_RD_CACHE;
287
               mbus_cmd_o     <= `MESI_ISC_MBUS_CMD_NOP;
288
            end
289
          // The memory state is Exclusive. Write to cache or read from cache.
290
          `MESI_ISC_TB_CPU_MESI_E:
291
            if (tb_ins_i == `MESI_ISC_TB_INS_WR)
292
            begin
293
               m_state        <= `MESI_ISC_TB_CPU_M_STATE_WR_CACHE;
294
               mbus_cmd_o     <= `MESI_ISC_MBUS_CMD_NOP;
295
            end
296
            else
297
            begin
298
               m_state        <= `MESI_ISC_TB_CPU_M_STATE_RD_CACHE;
299
               mbus_cmd_o     <= `MESI_ISC_MBUS_CMD_NOP;
300
            end
301
          // The memory state is Shared. 
302
          `MESI_ISC_TB_CPU_MESI_S:
303
            if (tb_ins_i == `MESI_ISC_TB_INS_WR)
304
            begin // Send a wr broadcast and wait for wr enable.
305
              wr_proc_wait_for_en <= 1;
306
              wr_proc_addr      <= tb_ins_addr_i;
307
              m_state           <= `MESI_ISC_TB_CPU_M_STATE_SEND_WR_BR;
308
              mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_WR_BROAD;
309
            end
310
            else // Read from cache.
311
            begin
312
              m_state           <= `MESI_ISC_TB_CPU_M_STATE_RD_CACHE;
313
              mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
314
            end
315
          // The memory state is Invalid. 
316
          `MESI_ISC_TB_CPU_MESI_I:
317
             if (tb_ins_i == `MESI_ISC_TB_INS_WR)
318
            begin // Send a wr broadcast and wait foo wr enable.  
319
              wr_proc_wait_for_en <= 1;
320
              wr_proc_addr      <= tb_ins_addr_i;
321
              m_state           <= `MESI_ISC_TB_CPU_M_STATE_SEND_WR_BR;
322
              mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_WR_BROAD;
323
           end
324
            else
325
            begin // Send a rd broadcast and wait foe rd enable.
326
              rd_proc_wait_for_en <= 1;
327
              rd_proc_addr      <= tb_ins_addr_i;
328
              m_state           <= `MESI_ISC_TB_CPU_M_STATE_SEND_RD_BR;
329
              mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_RD_BROAD;
330
            end
331
        endcase
332
      end // if (tb_ins_i == `MESI_ISC_TB_INS_WR)
333
    end // case: `MESI_ISC_TB_CPU_M_STATE_IDLE
334
    // Write to the cache
335
    `MESI_ISC_TB_CPU_M_STATE_WR_CACHE:
336
    //----------------------------------
337
    begin
338
            // State was M or E. After writing it is M
339
            cache_state[m_addr] <= `MESI_ISC_TB_CPU_MESI_M;
340
            // A write data to a line contains the incremental data to the
341
            // related word of the data, depends on the cpu_id_i (word 0 for CPU
342
            // 0, etc.)
343
            case (cpu_id_i)
344
              0: cache[m_addr][ 7 :0] <= wr_data[m_addr];
345
              1: cache[m_addr][15: 8] <= wr_data[m_addr];
346
              2: cache[m_addr][23:16] <= wr_data[m_addr];
347
              3: cache[m_addr][31:24] <= wr_data[m_addr];
348
            endcase // case (cpu_id_i)
349
            wr_data[m_addr]           <= wr_data[m_addr] + 1; // Increment the
350
                                      // write data
351
            // After the write, send acknowledge to main tb and go to the idle
352
            // state 
353
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_IDLE;
354
            tb_ins_ack_o      <= 1;
355
    end // case: `MESI_ISC_TB_CPU_M_STATE_WR_CACHE
356
    // A cache read from a valid line is a symbolic action in this TB
357
    `MESI_ISC_TB_CPU_M_STATE_RD_CACHE:
358
    //----------------------------------
359
    begin
360
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_IDLE;
361
            tb_ins_ack_o      <= 1;
362
    end
363
    `MESI_ISC_TB_CPU_M_STATE_SEND_WR_BR:
364
    //----------------------------------
365
     // Send the wr broadcast. After receiving acknowledge, send acknowledge to
366
     // main tb and go to the idle
367
    begin
368
            mbus_addr_o       <= m_addr;
369
            // Counts the number of cycle which m_state in this state
370
            m_state_send_wr_br_counter = m_state_send_wr_br_counter + 1;
371
      if (mbus_ack_i)
372
      begin
373
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_IDLE;
374
            tb_ins_ack_o      <= 1;
375
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
376
 
377
      end
378
      // To prevent a dead lock, after 31 cycles without an acknowledge, go to
379
      // the IDLE state and try again. It enables to the c_state to response to
380
      //  broadcast requests in this time.
381
      else if (m_state_send_wr_br_counter > 31)
382
      begin
383
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_IDLE;
384
            tb_ins_ack_o      <= 0;
385
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
386
 
387
      end
388
      else // Wait for ack
389
      begin
390
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_SEND_WR_BR;
391
      end
392
    end
393
    `MESI_ISC_TB_CPU_M_STATE_SEND_RD_BR:
394
    //----------------------------------
395
     // Send the rd broadcast. After receiving acknowledge, send acknowledge to
396
     // main tb and go to the idle
397
    begin
398
            mbus_addr_o       <= m_addr;
399
            // Counts the number of cycle which m_state in this state
400
            m_state_send_rd_br_counter = m_state_send_rd_br_counter + 1;
401
      if (mbus_ack_i)
402
      begin
403
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_IDLE;
404
            tb_ins_ack_o      <= 1;
405
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
406
      end
407
      // To prevent a dead lock, after 31 cycles without an acknowledge, go to
408
      // the IDLE state and try again. It enables to the c_state to response to
409
      // broadcast requests in this time.
410
      else if (m_state_send_rd_br_counter > 31)
411
      begin
412
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_IDLE;
413
            tb_ins_ack_o      <= 0;
414
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
415
 
416
      end
417
      else // Wait for ack
418
            m_state           <= `MESI_ISC_TB_CPU_M_STATE_SEND_RD_BR;
419
    end
420
  endcase // case state
421
 
422
 
423
// c_state
424
// Coherence bus state machine
425
//================================  
426
//
427
//  -----------------------------------------
428
//  | -------                               |
429
//  | |     |                               |
430
//  -----> IDLE --------> WR_SNOOP ---------|
431
//          |             |                 |
432
//          |          ----                 |
433
//          |          |                    |
434
//          |          -> EVICT_INVALIDATE -|
435
//          |                               |
436
//          |-----------> RD_SNOOP ---------|
437
//          |             |                 |
438
//          |          ----                 |
439
//          |          |                    |
440
//          |          -> EVICT ------------|
441
//          |                               |
442
//          |-----------> RD_LINE_WR--------|
443
//          |             |                 |
444
//          |          ----                 |
445
//          |          |                    |
446
//          |          -> WR_CACHE  --------|
447
//          |                               |
448
//          |-----------> RD_LINE_RD--------|
449
//
450
always @(posedge clk or posedge rst)
451
  if (rst)
452
  begin
453
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
454
            cbus_ack_o        <= 0;
455
  end
456
  else case (c_state)
457
 
458
    `MESI_ISC_TB_CPU_C_STATE_IDLE:
459
    //----------------------------------
460
    begin
461
            c_addr            <= cbus_addr_i; // Store the address of cbus
462
      // 1. CBUS and MBUS can't be active in the same time. When MBUS is
463
      //    active - wait.
464
      // 2. If priority is not of c_state - stay on IDLE
465
      // 3. If cbus_ack_o is asserted the last action is nor finished yet - wait
466
      //     for its finish
467
      if (m_state !=`MESI_ISC_TB_CPU_M_STATE_IDLE | // 1
468
          m_state_c_state_priority |                // 2
469
          cbus_ack_o)                               // 3
470
      begin
471
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
472
            cbus_ack_o        <= 0;
473
      end
474
      // Start the action when instruction is received.
475
      else
476
      begin
477
        mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
478
        case (cbus_cmd_i)
479
          `MESI_ISC_CBUS_CMD_NOP:
480
          begin
481
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
482
            cbus_ack_o        <= 0;
483
          end
484
          `MESI_ISC_CBUS_CMD_WR_SNOOP:
485
          begin
486
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_WR_SNOOP;
487
            cbus_ack_o        <= 0;
488
          end
489
          `MESI_ISC_CBUS_CMD_RD_SNOOP:
490
          begin
491
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_RD_SNOOP;
492
            cbus_ack_o        <= 0;
493
          end
494
          `MESI_ISC_CBUS_CMD_EN_WR:
495
          begin
496
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_RD_LINE_WR;
497
            cbus_ack_o        <= 0;
498
          end
499
          `MESI_ISC_CBUS_CMD_EN_RD:
500
          begin
501
              c_state           <= `MESI_ISC_TB_CPU_C_STATE_RD_LINE_RD;
502
              cbus_ack_o        <= 0;
503
          end
504
          default: $display ("Error 1. Wrong value - CPU:%d, cbus_cmd_i = %h,time=%d\n",
505
                              cpu_id_i,
506
                              cbus_cmd_i,
507
                              $time);
508
        endcase // case (cbus_cmd_i)
509
      end // else: !if(m_state !=`MESI_ISC_TB_CPU_M_STATE_IDLE |...
510
    end // case: `MESI_ISC_TB_CPU_C_STATE_IDLE
511
 
512
    `MESI_ISC_TB_CPU_C_STATE_WR_SNOOP:
513
    //----------------------------------
514
      if (cache_state[c_addr] == `MESI_ISC_TB_CPU_MESI_M)
515
               c_state           <= `MESI_ISC_TB_CPU_C_STATE_EVICT_INVALIDATE;
516
      else
517
      begin // Invalidate the line, send ack and finish the current process
518
            cbus_ack_o        <= 1;
519
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
520
            cache_state[c_addr] <= `MESI_ISC_TB_CPU_MESI_I;
521
            cache[c_addr]     <= 0;
522
      end
523
 
524
    `MESI_ISC_TB_CPU_C_STATE_RD_SNOOP:
525
    //----------------------------------
526
      if (cache_state[c_addr] == `MESI_ISC_TB_CPU_MESI_M)
527
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_EVICT_INVALIDATE;
528
      else if (cache_state[c_addr] == `MESI_ISC_TB_CPU_MESI_E)
529
      begin // Change state from E to S
530
            cbus_ack_o        <= 1;
531
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
532
            cache_state[c_addr] <= `MESI_ISC_TB_CPU_MESI_S;
533
      end
534
      else
535
      begin // Do nothing send ack and finish the current process
536
            cbus_ack_o        <= 1;
537
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
538
      end
539
 
540
    `MESI_ISC_TB_CPU_C_STATE_EVICT_INVALIDATE:
541
    //----------------------------------
542
    begin
543
      // Debug start ---         
544
      `ifdef messages // ifdef
545
        $display("Message: check err 2. time:%d", $time);
546
      `endif          // endif
547
      // Only a line in a M state can be EVICT_INVALIDATE
548
      if (cache_state[c_addr] != `MESI_ISC_TB_CPU_MESI_M)
549
      begin
550
        $display("Error 2. cache_state[c_addr] is not M.\n",
551
                  "  CPU:%d,c_addr=%h,cache_state[c_addr]=%h,time:%d",
552
                  cpu_id_i,
553
                  c_addr,
554
                  cache_state[c_addr],
555
                  $time);
556
        @(negedge clk) $finish();
557
      end
558
     // Debug end ---    
559
      else
560
      // Write line to memory. After receiving acknowledge, invalidate the line,
561
      // send acknowledge to main cbus and go to idle
562
      begin
563
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_WR;
564
            mbus_addr_o       <= c_addr;
565
            mbus_data_o       <= cache[c_addr];
566
        if (mbus_ack_i)
567
        begin
568
            cache_state[c_addr] <= `MESI_ISC_TB_CPU_MESI_I;
569
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
570
            cbus_ack_o        <= 1;
571
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
572
       end
573
      end
574
    end // case: `MESI_ISC_TB_CPU_C_STATE_EVICT_INVALIDATE
575
 
576
    `MESI_ISC_TB_CPU_C_STATE_EVICT:
577
    //----------------------------------
578
    begin
579
`ifdef messages
580
          $display("Message: check err 3. time:%d",$time);
581
`endif
582
      // Only a line in a S or E state can be EVICT_INVALIDATE
583
      if  (~(cache_state[c_addr] == `MESI_ISC_TB_CPU_MESI_S |
584
             cache_state[c_addr] == `MESI_ISC_TB_CPU_MESI_E))
585
        begin
586
          $display("Error 3. cache_state[c_addr] is not S or E.\n");
587
          $display("  CPU:%d,c_addr=%h,cache_state[c_addr]=%h,time=%d",
588
                   cpu_id_i,
589
                   c_addr,
590
                   cache_state[c_addr],
591
                   $time);
592
          @(negedge clk) $finish();
593
        end
594
      else
595
      // Write line to memory. After receiving acknowledge, change state to S,
596
      // send acknowledge to main cbus and go to idle
597
      begin
598
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_WR;
599
            mbus_addr_o       <= c_addr;
600
            mbus_data_o       <= cache[c_addr];
601
        if (mbus_ack_i)
602
        begin
603
            cache_state[c_addr] <= `MESI_ISC_TB_CPU_MESI_S;
604
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
605
            cbus_ack_o        <= 1;
606
        end
607
      end // else: !if(~(cache_state[c_addr] == `MESI_ISC_TB_CPU_MESI_S |...
608
    end // case: `MESI_ISC_TB_CPU_C_STATE_EVICT
609
 
610
    `MESI_ISC_TB_CPU_C_STATE_RD_LINE_WR:
611
    //----------------------------------
612
    // Read a line from memory and then go to WR_CACHE
613
    // and write to the cache.
614
     begin
615
`ifdef messages
616
      $display("Message: check er 4.time:%d",$time);
617
`endif
618
      if (wr_proc_wait_for_en != 1 |
619
              wr_proc_addr    != c_addr)
620
      begin
621
        $display("Error 4. Write to cache without early broadcast.\n",
622
                     "  CPU:%d,wr_proc_wait_for_en=%h,wr_proc_addr=%h,c_addr=%h, time:%d",
623
                 cpu_id_i,
624
                 wr_proc_wait_for_en,
625
                 wr_proc_addr,
626
                 c_addr,
627
                 $time);
628
        @(negedge clk) $finish();
629
      end
630
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_RD;
631
            mbus_addr_o       <= c_addr;
632
        if (mbus_ack_i)
633
        begin
634
            // A write data to a line contains the incremental data to the
635
            // related word of the data, depends on the cpu_id_i (word 0 for CPU
636
            // 0, etc.)
637
            cache[m_addr]       <= mbus_data_i;
638
            cache_state[m_addr] <= `MESI_ISC_TB_CPU_MESI_S;
639
            c_state             <= `MESI_ISC_TB_CPU_C_STATE_WR_CACHE;
640
            mbus_cmd_o          <= `MESI_ISC_MBUS_CMD_NOP;
641
        end
642
      end
643
 
644
    `MESI_ISC_TB_CPU_C_STATE_RD_LINE_RD:
645
    //----------------------------------
646
    // Read a line from memory and then go back to IDLE.
647
      begin
648
`ifdef messages
649
        $display("Message: check err 5. time:%d",$time);
650
`endif
651
        // EN_RD means that the line is not valid in the cache
652
        if (rd_proc_wait_for_en != 1 |
653
            rd_proc_addr      != c_addr)
654
        begin
655
          $display("Error 5. Read to cache without early broadcast.\n",
656
                "  CPU:%d,rd_proc_wait_for_en=%h,rd_proc_addr=%h,c_addr=%h,time:%d\n",
657
                  cpu_id_i,
658
                  rd_proc_wait_for_en,
659
                  rd_proc_addr,
660
                  c_addr,
661
                  $time);
662
          @(negedge clk) $finish();
663
        end
664
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_RD;
665
            mbus_addr_o       <= c_addr;
666
        if (mbus_ack_i)
667
        begin
668
            // A write data to a line contains the incremental data to the
669
            // related word of the data, depends on the cpu_id_i (word 0 for CPU
670
            // 0, etc.)
671
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
672
            cache[m_addr]     <= mbus_data_i;
673
            cache_state[m_addr] <= `MESI_ISC_TB_CPU_MESI_S;
674
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
675
            cbus_ack_o        <= 1;
676
            rd_proc_wait_for_en <= 0;
677
            mbus_cmd_o          <= `MESI_ISC_MBUS_CMD_NOP;
678
        end // if (mbus_ack_i)
679
      end // case: `MESI_ISC_TB_CPU_C_STATE_RD_LINE_RD
680
 
681
    `MESI_ISC_TB_CPU_C_STATE_WR_CACHE:
682
    //----------------------------------
683
    begin
684
      // A write data to a line contains the incremental data to the
685
      // related word of the data, depends on the cpu_id_i (word 0 for CPU
686
      // 0, etc.)
687
      case (cpu_id_i)
688
        0: cache[m_addr][ 7 :0] <= wr_data[m_addr];
689
        1: cache[m_addr][15: 8] <= wr_data[m_addr];
690
        2: cache[m_addr][23:16] <= wr_data[m_addr];
691
        3: cache[m_addr][31:24] <= wr_data[m_addr];
692
      endcase // case (cpu_id_i)
693
            wr_data[m_addr]   <= wr_data[m_addr] + 1; // Increment the wr data
694
            c_state           <= `MESI_ISC_TB_CPU_C_STATE_IDLE;
695
            mbus_cmd_o        <= `MESI_ISC_MBUS_CMD_NOP;
696
            cache_state[m_addr] <= `MESI_ISC_TB_CPU_MESI_M;
697
            cbus_ack_o        <= 1;
698
            wr_proc_wait_for_en <= 0;
699
     end
700
   endcase // case (c_state)
701
 
702
 
703
endmodule

powered by: WebSVN 2.1.0

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