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

Subversion Repositories cryptosorter

[/] [cryptosorter/] [trunk/] [memocodeDesignContest2008/] [xup/] [PLBMaster/] [PLBMaster.bsv] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 kfleming
/*
2
Copyright (c) 2007 MIT
3
 
4
Permission is hereby granted, free of charge, to any person
5
obtaining a copy of this software and associated documentation
6
files (the "Software"), to deal in the Software without
7
restriction, including without limitation the rights to use,
8
copy, modify, merge, publish, distribute, sublicense, and/or sell
9
copies of the Software, and to permit persons to whom the
10
Software is furnished to do so, subject to the following
11
conditions:
12
 
13
The above copyright notice and this permission notice shall be
14
included in all copies or substantial portions of the Software.
15
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
OTHER DEALINGS IN THE SOFTWARE.
24
 
25
Author: Kermin Fleming
26
*/
27
 
28
/* This file implements a PLB bus master.  The bus master operates on static
29
   sized bursts.  It is written in such a way that read/write bursts may be
30
   overlapped, if the bus and target slave support such a feature. There's also
31
   support for pipelining of read and write requests.  The master is
32
   parameterized by BeatsPerBurst (burst length) and BusWord (bus width),
33
   which allow it to be used for various applications.
34
*/
35
 
36
// Global Imports
37
import GetPut::*;
38
import FIFO::*;
39
import RegFile::*;
40
import BRAMInitiatorWires::*;
41
import RegFile::*;
42
import FIFOF::*;
43
import Vector::*;
44
 
45
import Types::*;
46
import Interfaces::*;
47
import Parameters::*;
48
import DebugFlags::*;
49
 
50
import PLBMasterWires::*;
51
import Memocode08Types::*;
52
 
53
typedef enum {
54
  Idle,
55
  Data,
56
  WaitForBusy
57
} StateTransfer
58
    deriving(Bits, Eq);
59
 
60
typedef enum {
61
  Idle,
62
  RequestingLoad,
63
  RequestingStore
64
} StateRequest
65
    deriving(Bits, Eq);
66
 
67
(* synthesize *)
68
module mkPLBMaster (PLBMaster);
69
  Clock plbClock <- exposeCurrentClock();
70
  Reset plbReset <- exposeCurrentReset();
71
  // state for the actual magic memory hardware
72
  FIFO#(Record)            recordInfifo <- mkFIFO;
73
  FIFO#(Record)            recordOutfifo <- mkFIFO;
74
  FIFO#(PLBMasterCommand)  plbMasterCommandInfifo <- mkFIFO();
75
 
76
 
77
  // Output buffer
78
  RegFile#(Bit#(TAdd#(1,TLog#(BeatsPerBurst))),BusWord)                            storeBuffer <- mkRegFileFull();
79
 
80
 
81
  // Input buffer
82
  RegFile#(Bit#(TAdd#(1,TLog#(BeatsPerBurst))),BusWord)                            loadBuffer <- mkRegFileFull();
83
 
84
 
85
  Reg#(Bit#(24))                              rowAddrOffsetLoad <- mkReg(0);
86
  Reg#(Bit#(24))                              rowAddrOffsetStore <- mkReg(0);
87
 
88
  Reg#(Bool)                                doingLoad <- mkReg(False);
89
  Reg#(Bool)                                doingStore <- mkReg(False);
90
 
91
  Bit#(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))) zeroOffset = 0; // Words per Burst
92
  Reg#(Bool)                                requestingStore <- mkReg(False);
93
  BlockAddr addressOffset                   = zeroExtend({(requestingStore)?rowAddrOffsetStore:rowAddrOffsetLoad,zeroOffset});
94
 
95
 
96
  Reg#(StateRequest)                        stateRequest <- mkReg(Idle);
97
  Reg#(StateTransfer)                       stateLoad <- mkReg(Idle);
98
  Reg#(StateTransfer)                       stateStore <- mkReg(Idle);
99
  Reg#(Bit#(1))                             request <- mkReg(0);
100
  Reg#(Bit#(1))                             rnw <- mkReg(0);
101
 
102
 
103
  Reg#(Bit#(TLog#(BeatsPerBurst)))              loadDataCount <- mkReg(0);
104
  Reg#(Bit#(TLog#(BeatsPerBurst)))              storeDataCount <-mkReg(0);// If you change this examine mWrDBus_o
105
  Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst))))      loadDataCount_plus2 <- mkReg(2);
106
  Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst))))      storeDataCount_plus2 <-mkReg(2);
107
 
108
  Reg#(Bool)                                doAckinIdle <- mkReg(False);
109
 
110
  Reg#(Bit#(1))                             rdBurst <- mkReg(0);
111
  Reg#(Bit#(1))                             wrBurst <- mkReg(0);
112
 
113
  Reg#(Bit#(1))                             storeCounter <- mkReg(0);
114
  Reg#(Bit#(1))                             loadCounter <- mkReg(0);
115
 
116
  Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) storeBufferWritePointer <- mkReg(0);
117
  FIFOF#(Bit#(0))                           storeValid <- mkUGFIFOF;//XXX: This could be bad
118
  Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) loadBufferReadPointer <- mkReg(0);
119
  FIFOF#(Bit#(0))                           loadValid <- mkUGFIFOF;//XXX: This could be bad
120
 
121
 
122
  // Input wires
123
  Wire#(Bit#(1)) mRst <- mkBypassWire();
124
  Wire#(Bit#(1)) mAddrAck <- mkBypassWire();
125
  Wire#(Bit#(1)) mBusy <- mkBypassWire();
126
  Wire#(Bit#(1)) mErr <- mkBypassWire();
127
  Wire#(Bit#(1)) mRdBTerm <- mkBypassWire();
128
  Wire#(Bit#(1)) mRdDAck <- mkBypassWire();
129
  Wire#(Bit#(64))mRdDBus <- mkBypassWire();
130
  Wire#(Bit#(3)) mRdWdAddr <- mkBypassWire();
131
  Wire#(Bit#(1)) mRearbitrate <- mkBypassWire();
132
  Wire#(Bit#(1)) mWrBTerm <- mkBypassWire();
133
  Wire#(Bit#(1)) mWrDAck <- mkBypassWire();
134
  Wire#(Bit#(1)) mSSize <- mkBypassWire();
135
  Wire#(Bit#(1)) sMErr <- mkBypassWire(); // on a read, during the data ack
136
  Wire#(Bit#(1)) sMBusy <- mkBypassWire();
137
 
138
  //  Outputs
139
 
140
 
141
  Bit#(PLBAddrSize) mABus_o = {addressOffset,2'b00}; // Our address Address Bus, we extend to compensate for word
142
 
143
 
144
  Bit#(TAdd#(1,TLog#(BeatsPerBurst))) sbuf_addr = {storeCounter,storeDataCount};
145
 
146
 
147
  Bit#(64)mWrDBus_o   = storeBuffer.sub(sbuf_addr);
148
  Bit#(1) mRequest_o  = request & ~mRst; // Request
149
  Bit#(1) mBusLock_o  = 1'b0 & ~mRst; // Bus lock
150
  Bit#(1) mRdBurst_o  = rdBurst & ~mRst; // read burst
151
  Bit#(1) mWrBurst_o  = wrBurst & ~mRst; // write burst
152
  Bit#(1) mRNW_o      = rnw; // Read Not Write
153
  Bit#(1) mAbort_o    = 1'b0; // Abort
154
  Bit#(2) mPriority_o = 2'b11;// priority indicator
155
  Bit#(1) mCompress_o = 1'b0;// compressed transfer
156
  Bit#(1) mGuarded_o  = 1'b0;// guarded transfer
157
  Bit#(1) mOrdered_o  = 1'b0;// synchronize transfer
158
  Bit#(1) mLockErr_o  = 1'b0;// lock erro
159
  Bit#(4) mSize_o     = 4'b1011; // Burst double word transfer - see PLB p.24
160
  Bit#(3) mType_o     = 3'b000; // Memory Transfer
161
  Bit#(8) mBE_o       = 8'b00001111; // 16 word burst
162
  Bit#(2) mMSize_o    = 2'b00;
163
 
164
 
165
  // precompute the next address offset.  Sometimes
166
 
167
 
168
  PLBMasterCommand cmd_in_first = plbMasterCommandInfifo.first();
169
 
170
  let newloadDataCount  =  loadDataCount + 1;
171
  let newstoreDataCount = storeDataCount + 1;
172
  let newloadDataCount_plus2  =  loadDataCount_plus2 + 1;
173
  let newstoreDataCount_plus2 = storeDataCount_plus2 + 1;
174
 
175
 
176
  rule startPageLoad(cmd_in_first matches tagged LoadPage .ba &&& !doingLoad);
177
        $display("Start Page");
178
        plbMasterCommandInfifo.deq();
179
        $display("Load Page");
180
        rowAddrOffsetLoad   <= truncate(ba>>(valueof(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))))); // this is the log
181
        if (ba[3:0] != 0)
182
          $display("ERROR:Address not 64-byte aligned");
183
        doingLoad <= True;
184
  endrule
185
 
186
  rule startPageStore(cmd_in_first matches tagged StorePage .ba &&& !doingStore);
187
    $display("Start Page");
188
    plbMasterCommandInfifo.deq();
189
    $display("Store Page");
190
    rowAddrOffsetStore <= truncate(ba>>(valueof(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))))); // this is the log
191
                                                                                             // size of burst addr
192
    if (ba[3:0] != 0)
193
      $display("ERROR:Address not 64-byte aligned");
194
    doingStore <= True;
195
  endrule
196
 
197
 
198
  rule loadPage_Idle(doingLoad && stateRequest == Idle && stateLoad == Idle);
199
    // We should not initiate a transfer if the wordOutfifo is not valid
200
    //$display("loadPage_Idle");
201
    requestingStore <= False;
202
    if(loadValid.notFull())// Check for a spot.
203
      begin
204
        request <= 1'b1;
205
        stateRequest <= RequestingLoad;
206
      end
207
    else
208
      begin
209
        request <= 1'b0;  // Not Sure this is needed
210
      end
211
 
212
    rnw <= 1'b1; // We're reading
213
  endrule
214
 
215
 
216
 
217
  rule loadPage_Requesting(doingLoad && stateRequest == RequestingLoad && stateLoad == Idle);
218
    // We've just requested the bus and are waiting for an ack
219
    //$display("loadPage_Requesting");
220
    if(mAddrAck == 1 )
221
      begin
222
        stateRequest <= Idle;
223
        // Check for error conditions
224
        if(mRearbitrate == 1)
225
          begin
226
            // Got terminated by the bus
227
            $display("Terminated by BUS @ %d",$time);
228
            stateLoad <= Idle;
229
            rdBurst <= 1'b0; // if we're rearbing this should be off. It may be off anyway?
230
            request <= 1'b0;
231
          end
232
        else
233
          begin
234
            //Whew! didn't die yet.. wait for acks to come back
235
            stateLoad <= Data;
236
            // Not permissible to assert burst until after addrAck p. 35
237
            rdBurst <= 1'b1;
238
            // Set down request, as we are not request pipelining
239
            request <= 1'b0;
240
          end
241
      end
242
  endrule
243
 
244
  rule loadPage_Data(doingLoad && stateLoad == Data);
245
    if(((mRdBTerm == 1) && (loadDataCount_plus2 < (fromInteger(valueof(BeatsPerBurst))))) || (mErr == 1))
246
      begin
247
        // We got terminated / Errored
248
        rdBurst <= 1'b0;
249
        loadDataCount <= 0;
250
        loadDataCount_plus2 <= 2;
251
        stateLoad <= Idle;
252
      end
253
    else if(mRdDAck == 1)
254
      begin
255
        loadDataCount <= newloadDataCount;
256
        loadDataCount_plus2 <= newloadDataCount_plus2;
257
        loadBuffer.upd({loadCounter,loadDataCount}, mRdDBus);
258
        if(newloadDataCount == 0)
259
          begin
260
            loadCounter <= loadCounter + 1; // Flip the loadCounter
261
            //We're now done reading... what should we do?
262
            loadValid.enq(0);  // This signifies that the data is valid Nirav could probably remove this
263
            doingLoad <= False;
264
            stateLoad <= Idle;
265
          end
266
        else if(newloadDataCount == maxBound) // YYY: ndave used to ~0
267
          begin
268
            // Last read is upcoming.  Need to set down the
269
            // rdBurst signal.
270
            rdBurst <= 1'b0;
271
          end
272
      end
273
  endrule
274
 
275
 
276
 
277
  rule storePage_Idle(doingStore && stateRequest == Idle && stateStore == Idle);
278
    requestingStore <= True;
279
    if(storeValid.notEmpty())
280
      begin
281
        request <= 1'b1;
282
        stateRequest <= RequestingStore;
283
      end
284
    else
285
      begin
286
        request <= 1'b0;
287
      end
288
 
289
    wrBurst <= 1'b1; // Write burst is asserted with the write request
290
    rnw <= 1'b0; // We're writing
291
  endrule
292
 
293
  rule storePage_Requesting(doingStore && stateRequest == RequestingStore && stateStore == Idle);
294
    // We've just requested the bus and are waiting for an ack
295
    if(mAddrAck == 1 )
296
      begin
297
        stateRequest <= Idle;
298
        // Check for error conditions
299
        if(mRearbitrate == 1)
300
          begin
301
            // Got terminated by the bus
302
            wrBurst <= 1'b0;
303
            request <= 1'b0;
304
          end
305
        else
306
          begin
307
            // Set down request, as we are not request pipelining
308
            request <= 1'b0;
309
            // We can be WrDAck'ed at this time p.29 or WrBTerm p.30
310
            if(mWrBTerm == 1)
311
              begin
312
                wrBurst <= 1'b0;
313
              end
314
            else if(mWrDAck == 1)
315
              begin
316
                storeDataCount <= newstoreDataCount;
317
                storeDataCount_plus2 <= newstoreDataCount_plus2;
318
                stateStore <= Data;
319
              end
320
            else
321
              begin
322
                stateStore <= Data;
323
              end
324
          end
325
      end
326
  endrule
327
 
328
 
329
  rule storePage_Data(doingStore && stateStore == Data);
330
    if((mWrBTerm == 1) && (storeDataCount_plus2 < (fromInteger(valueof(BeatsPerBurst)))) || (mErr == 1))
331
      begin
332
        // We got terminated / Errored
333
        wrBurst <= 1'b0;
334
        storeDataCount <= 0;
335
        storeDataCount_plus2 <= 2;
336
        stateStore <= Idle; // Can't burst for a cycle p. 30
337
      end
338
    else if(mWrDAck == 1)
339
      begin
340
        storeDataCount <= newstoreDataCount;
341
        storeDataCount_plus2 <= newstoreDataCount_plus2;
342
        if(newstoreDataCount == 0)
343
          begin
344
            //We're now done reading... what should we do?
345
            // Data transfer complete
346
            if(mBusy == 0)
347
              begin
348
                doingStore <= False;
349
                stateStore <= Idle;
350
                storeValid.deq();
351
                storeCounter <= storeCounter + 1;
352
              end
353
            else
354
              begin
355
                stateStore <= WaitForBusy;
356
              end
357
          end
358
        else if(newstoreDataCount == maxBound) //YYY: used to be ~0
359
          begin
360
            // Last read is upcoming.  Need to set down the
361
            // wrBurst signal.
362
            wrBurst <= 1'b0;
363
          end
364
      end
365
  endrule
366
 
367
  rule storePage_WaitForBusy(doingStore && stateStore == WaitForBusy);
368
    if(mErr == 1)
369
      begin
370
        // We got terminated / Errored
371
        wrBurst <= 1'b0;
372
        storeDataCount <= 0; // may not be necessary
373
        storeDataCount_plus2 <= 2;
374
        stateStore <= Idle; // Can't burst for a cycle p. 30
375
      end
376
    else if(mBusy == 0)
377
      begin
378
        storeCounter <= storeCounter + 1;
379
        doingStore <= False;
380
        stateStore <= Idle;
381
        storeValid.deq();
382
      end
383
  endrule
384
 
385
  /********
386
  /* Code For Handling Record Translation
387
  /*******/
388
 
389
  Reg#(Bit#(DoubleWordWidth)) recordSled <- mkReg(0);
390
 
391
 
392
 
393
 
394
  rule writeStoreData(storeValid.notFull());
395
    storeBufferWritePointer <= storeBufferWritePointer + 1;
396
 
397
    case(storeBufferWritePointer[0])
398
      0: storeBuffer.upd(storeBufferWritePointer, {recordInfifo.first[31:0] ,recordInfifo.first[63:32]});
399
      1: storeBuffer.upd(storeBufferWritePointer, {recordInfifo.first[95:64],recordInfifo.first[127:96]});
400
    endcase
401
 
402
    if((storeBufferWritePointer + 1)[0] == 0)
403
      begin
404
        recordInfifo.deq;
405
      end
406
 
407
    Bit#(TLog#(BeatsPerBurst)) bottomValue = 0;
408
    if(truncate(storeBufferWritePointer + 1) == bottomValue)
409
      begin
410
        $display("Store Data finished a flight");
411
        storeValid.enq(0);
412
      end
413
  endrule
414
 
415
 
416
  rule wordToRecord(loadValid.notEmpty());
417
    loadBufferReadPointer <= loadBufferReadPointer + 1;
418
    Bit#(64) loadValue = loadBuffer.sub(loadBufferReadPointer);
419
    Bit#(32) loadHigh = loadValue [63:32];
420
    Bit#(32) loadLow = loadValue [31:0];
421
    Bit#(TLog#(BeatsPerBurst)) bottomValue = 0;
422
    if(truncate(loadBufferReadPointer + 1) == bottomValue)
423
      begin
424
        $display("Load Data finished a flight");
425
        loadValid.deq();
426
      end
427
 
428
    if((loadBufferReadPointer + 1)[0] == 0)
429
      begin
430
        recordOutfifo.enq({{loadLow,loadHigh},recordSled});
431
      end
432
    else
433
      begin
434
        recordSled <= {loadLow,loadHigh};
435
      end
436
  endrule
437
 
438
  interface Put wordInput = fifoToPut(recordInfifo);
439
 
440
  interface Get wordOutput = fifoToGet(recordOutfifo);
441
 
442
  interface Put plbMasterCommandInput = fifoToPut(plbMasterCommandInfifo);
443
 
444
 
445
  interface PLBMasterWires  plbMasterWires;
446
 
447
    method Bit#(PLBAddrSize) mABus();     // Address Bus
448
      return mABus_o;
449
    endmethod
450
    method Bit#(8)           mBE();       // Byte Enable
451
      return mBE_o;
452
    endmethod
453
 
454
    method Bit#(1)           mRNW();      // Read Not Write
455
      return mRNW_o;
456
    endmethod
457
 
458
    method Bit#(1)           mAbort();    // Abort
459
      return mAbort_o;
460
    endmethod
461
 
462
    method Bit#(1)           mBusLock();  // Bus lock
463
      return mBusLock_o;
464
    endmethod
465
 
466
    method Bit#(1)           mCompress(); // compressed transfer
467
      return mCompress_o;
468
    endmethod
469
 
470
    method Bit#(1)           mGuarded();  // guarded transfer
471
      return mGuarded_o;
472
    endmethod
473
 
474
    method Bit#(1)           mLockErr();  // lock error
475
      return mLockErr_o;
476
    endmethod
477
 
478
    method Bit#(2)           mMSize();    // data bus width?
479
      return mMSize_o;
480
    endmethod
481
 
482
    method Bit#(1)           mOrdered();  // synchronize transfer
483
      return mOrdered_o;
484
    endmethod
485
 
486
    method Bit#(2)           mPriority(); // priority indicator
487
      return mPriority_o;
488
    endmethod
489
 
490
    method Bit#(1)           mRdBurst();  // read burst
491
      return mRdBurst_o;
492
    endmethod
493
 
494
    method Bit#(1)           mRequest();  // bus request
495
      return mRequest_o;
496
    endmethod
497
 
498
    method Bit#(4)           mSize();     // transfer size
499
      return mSize_o;
500
    endmethod
501
 
502
    method Bit#(3)           mType();     // transfer type (dma)
503
      return mType_o;
504
    endmethod
505
 
506
    method Bit#(1)           mWrBurst();  // write burst
507
      return mWrBurst_o;
508
    endmethod
509
 
510
    method Bit#(64)          mWrDBus();   // write data bus
511
      return mWrDBus_o;
512
    endmethod
513
 
514
    method Action plbIN(
515
      Bit#(1) mRst_in,            // PLB reset
516
      Bit#(1) mAddrAck_in,             // Addr Ack
517
      Bit#(1) mBusy_in,           // Master Busy
518
      Bit#(1) mErr_in,            // Slave Error
519
      Bit#(1) mRdBTerm_in,             // Read burst terminate signal
520
      Bit#(1) mRdDAck_in,              // Read data ack
521
      Bit#(64)mRdDBus_in,              // Read data bus
522
      Bit#(3) mRdWdAddr_in,       // Read word address
523
      Bit#(1) mRearbitrate_in,    // Rearbitrate
524
      Bit#(1) mWrBTerm_in,             // Write burst terminate
525
      Bit#(1) mWrDAck_in,              // Write data ack
526
      Bit#(1) mSSize_in,               // Slave bus size
527
      Bit#(1) sMErr_in,        // Slave error
528
      Bit#(1) sMBusy_in);              // Slave busy
529
      mRst <= mRst_in;
530
      mAddrAck <= mAddrAck_in;
531
      mBusy <= mBusy_in;
532
      mErr <= mErr_in;
533
      mRdBTerm <= mRdBTerm_in;
534
      mRdDAck <= mRdDAck_in;
535
      mRdDBus <= mRdDBus_in;
536
      mRdWdAddr <= mRdWdAddr_in;
537
      mRearbitrate <= mRearbitrate_in;
538
      mWrBTerm <= mWrBTerm_in;
539
      mWrDAck <= mWrDAck_in;
540
      mSSize <= mSSize_in;
541
      sMErr <= sMErr_in;
542
      sMBusy <= sMBusy_in;
543
    endmethod
544
   endinterface
545
endmodule

powered by: WebSVN 2.1.0

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