URL
https://opencores.org/ocsvn/cryptosorter/cryptosorter/trunk
Subversion Repositories cryptosorter
[/] [cryptosorter/] [trunk/] [memocodeDesignContest2008/] [xup/] [PLBMaster/] [PLBMaster.bsv] - Rev 6
Compare with Previous | Blame | View Log
/*Copyright (c) 2007 MITPermission is hereby granted, free of charge, to any personobtaining a copy of this software and associated documentationfiles (the "Software"), to deal in the Software withoutrestriction, including without limitation the rights to use,copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom theSoftware is furnished to do so, subject to the followingconditions:The above copyright notice and this permission notice shall beincluded in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIESOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE ANDNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISINGFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OROTHER DEALINGS IN THE SOFTWARE.Author: Kermin Fleming*//* This file implements a PLB bus master. The bus master operates on staticsized bursts. It is written in such a way that read/write bursts may beoverlapped, if the bus and target slave support such a feature. There's alsosupport for pipelining of read and write requests. The master isparameterized by BeatsPerBurst (burst length) and BusWord (bus width),which allow it to be used for various applications.*/// Global Importsimport GetPut::*;import FIFO::*;import RegFile::*;import BRAMInitiatorWires::*;import RegFile::*;import FIFOF::*;import Vector::*;import Types::*;import Interfaces::*;import Parameters::*;import DebugFlags::*;import PLBMasterWires::*;import Memocode08Types::*;typedef enum {Idle,Data,WaitForBusy} StateTransferderiving(Bits, Eq);typedef enum {Idle,RequestingLoad,RequestingStore} StateRequestderiving(Bits, Eq);(* synthesize *)module mkPLBMaster (PLBMaster);Clock plbClock <- exposeCurrentClock();Reset plbReset <- exposeCurrentReset();// state for the actual magic memory hardwareFIFO#(Record) recordInfifo <- mkFIFO;FIFO#(Record) recordOutfifo <- mkFIFO;FIFO#(PLBMasterCommand) plbMasterCommandInfifo <- mkFIFO();// Output bufferRegFile#(Bit#(TAdd#(1,TLog#(BeatsPerBurst))),BusWord) storeBuffer <- mkRegFileFull();// Input bufferRegFile#(Bit#(TAdd#(1,TLog#(BeatsPerBurst))),BusWord) loadBuffer <- mkRegFileFull();Reg#(Bit#(24)) rowAddrOffsetLoad <- mkReg(0);Reg#(Bit#(24)) rowAddrOffsetStore <- mkReg(0);Reg#(Bool) doingLoad <- mkReg(False);Reg#(Bool) doingStore <- mkReg(False);Bit#(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))) zeroOffset = 0; // Words per BurstReg#(Bool) requestingStore <- mkReg(False);BlockAddr addressOffset = zeroExtend({(requestingStore)?rowAddrOffsetStore:rowAddrOffsetLoad,zeroOffset});Reg#(StateRequest) stateRequest <- mkReg(Idle);Reg#(StateTransfer) stateLoad <- mkReg(Idle);Reg#(StateTransfer) stateStore <- mkReg(Idle);Reg#(Bit#(1)) request <- mkReg(0);Reg#(Bit#(1)) rnw <- mkReg(0);Reg#(Bit#(TLog#(BeatsPerBurst))) loadDataCount <- mkReg(0);Reg#(Bit#(TLog#(BeatsPerBurst))) storeDataCount <-mkReg(0);// If you change this examine mWrDBus_oReg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) loadDataCount_plus2 <- mkReg(2);Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) storeDataCount_plus2 <-mkReg(2);Reg#(Bool) doAckinIdle <- mkReg(False);Reg#(Bit#(1)) rdBurst <- mkReg(0);Reg#(Bit#(1)) wrBurst <- mkReg(0);Reg#(Bit#(1)) storeCounter <- mkReg(0);Reg#(Bit#(1)) loadCounter <- mkReg(0);Reg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) storeBufferWritePointer <- mkReg(0);FIFOF#(Bit#(0)) storeValid <- mkUGFIFOF;//XXX: This could be badReg#(Bit#(TAdd#(1,TLog#(BeatsPerBurst)))) loadBufferReadPointer <- mkReg(0);FIFOF#(Bit#(0)) loadValid <- mkUGFIFOF;//XXX: This could be bad// Input wiresWire#(Bit#(1)) mRst <- mkBypassWire();Wire#(Bit#(1)) mAddrAck <- mkBypassWire();Wire#(Bit#(1)) mBusy <- mkBypassWire();Wire#(Bit#(1)) mErr <- mkBypassWire();Wire#(Bit#(1)) mRdBTerm <- mkBypassWire();Wire#(Bit#(1)) mRdDAck <- mkBypassWire();Wire#(Bit#(64))mRdDBus <- mkBypassWire();Wire#(Bit#(3)) mRdWdAddr <- mkBypassWire();Wire#(Bit#(1)) mRearbitrate <- mkBypassWire();Wire#(Bit#(1)) mWrBTerm <- mkBypassWire();Wire#(Bit#(1)) mWrDAck <- mkBypassWire();Wire#(Bit#(1)) mSSize <- mkBypassWire();Wire#(Bit#(1)) sMErr <- mkBypassWire(); // on a read, during the data ackWire#(Bit#(1)) sMBusy <- mkBypassWire();// OutputsBit#(PLBAddrSize) mABus_o = {addressOffset,2'b00}; // Our address Address Bus, we extend to compensate for wordBit#(TAdd#(1,TLog#(BeatsPerBurst))) sbuf_addr = {storeCounter,storeDataCount};Bit#(64)mWrDBus_o = storeBuffer.sub(sbuf_addr);Bit#(1) mRequest_o = request & ~mRst; // RequestBit#(1) mBusLock_o = 1'b0 & ~mRst; // Bus lockBit#(1) mRdBurst_o = rdBurst & ~mRst; // read burstBit#(1) mWrBurst_o = wrBurst & ~mRst; // write burstBit#(1) mRNW_o = rnw; // Read Not WriteBit#(1) mAbort_o = 1'b0; // AbortBit#(2) mPriority_o = 2'b11;// priority indicatorBit#(1) mCompress_o = 1'b0;// compressed transferBit#(1) mGuarded_o = 1'b0;// guarded transferBit#(1) mOrdered_o = 1'b0;// synchronize transferBit#(1) mLockErr_o = 1'b0;// lock erroBit#(4) mSize_o = 4'b1011; // Burst double word transfer - see PLB p.24Bit#(3) mType_o = 3'b000; // Memory TransferBit#(8) mBE_o = 8'b00001111; // 16 word burstBit#(2) mMSize_o = 2'b00;// precompute the next address offset. SometimesPLBMasterCommand cmd_in_first = plbMasterCommandInfifo.first();let newloadDataCount = loadDataCount + 1;let newstoreDataCount = storeDataCount + 1;let newloadDataCount_plus2 = loadDataCount_plus2 + 1;let newstoreDataCount_plus2 = storeDataCount_plus2 + 1;rule startPageLoad(cmd_in_first matches tagged LoadPage .ba &&& !doingLoad);$display("Start Page");plbMasterCommandInfifo.deq();$display("Load Page");rowAddrOffsetLoad <= truncate(ba>>(valueof(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))))); // this is the logif (ba[3:0] != 0)$display("ERROR:Address not 64-byte aligned");doingLoad <= True;endrulerule startPageStore(cmd_in_first matches tagged StorePage .ba &&& !doingStore);$display("Start Page");plbMasterCommandInfifo.deq();$display("Store Page");rowAddrOffsetStore <= truncate(ba>>(valueof(TLog#(TMul#(BeatsPerBurst, WordsPerBeat))))); // this is the log// size of burst addrif (ba[3:0] != 0)$display("ERROR:Address not 64-byte aligned");doingStore <= True;endrulerule loadPage_Idle(doingLoad && stateRequest == Idle && stateLoad == Idle);// We should not initiate a transfer if the wordOutfifo is not valid//$display("loadPage_Idle");requestingStore <= False;if(loadValid.notFull())// Check for a spot.beginrequest <= 1'b1;stateRequest <= RequestingLoad;endelsebeginrequest <= 1'b0; // Not Sure this is neededendrnw <= 1'b1; // We're readingendrulerule loadPage_Requesting(doingLoad && stateRequest == RequestingLoad && stateLoad == Idle);// We've just requested the bus and are waiting for an ack//$display("loadPage_Requesting");if(mAddrAck == 1 )beginstateRequest <= Idle;// Check for error conditionsif(mRearbitrate == 1)begin// Got terminated by the bus$display("Terminated by BUS @ %d",$time);stateLoad <= Idle;rdBurst <= 1'b0; // if we're rearbing this should be off. It may be off anyway?request <= 1'b0;endelsebegin//Whew! didn't die yet.. wait for acks to come backstateLoad <= Data;// Not permissible to assert burst until after addrAck p. 35rdBurst <= 1'b1;// Set down request, as we are not request pipeliningrequest <= 1'b0;endendendrulerule loadPage_Data(doingLoad && stateLoad == Data);if(((mRdBTerm == 1) && (loadDataCount_plus2 < (fromInteger(valueof(BeatsPerBurst))))) || (mErr == 1))begin// We got terminated / ErroredrdBurst <= 1'b0;loadDataCount <= 0;loadDataCount_plus2 <= 2;stateLoad <= Idle;endelse if(mRdDAck == 1)beginloadDataCount <= newloadDataCount;loadDataCount_plus2 <= newloadDataCount_plus2;loadBuffer.upd({loadCounter,loadDataCount}, mRdDBus);if(newloadDataCount == 0)beginloadCounter <= loadCounter + 1; // Flip the loadCounter//We're now done reading... what should we do?loadValid.enq(0); // This signifies that the data is valid Nirav could probably remove thisdoingLoad <= False;stateLoad <= Idle;endelse if(newloadDataCount == maxBound) // YYY: ndave used to ~0begin// Last read is upcoming. Need to set down the// rdBurst signal.rdBurst <= 1'b0;endendendrulerule storePage_Idle(doingStore && stateRequest == Idle && stateStore == Idle);requestingStore <= True;if(storeValid.notEmpty())beginrequest <= 1'b1;stateRequest <= RequestingStore;endelsebeginrequest <= 1'b0;endwrBurst <= 1'b1; // Write burst is asserted with the write requestrnw <= 1'b0; // We're writingendrulerule storePage_Requesting(doingStore && stateRequest == RequestingStore && stateStore == Idle);// We've just requested the bus and are waiting for an ackif(mAddrAck == 1 )beginstateRequest <= Idle;// Check for error conditionsif(mRearbitrate == 1)begin// Got terminated by the buswrBurst <= 1'b0;request <= 1'b0;endelsebegin// Set down request, as we are not request pipeliningrequest <= 1'b0;// We can be WrDAck'ed at this time p.29 or WrBTerm p.30if(mWrBTerm == 1)beginwrBurst <= 1'b0;endelse if(mWrDAck == 1)beginstoreDataCount <= newstoreDataCount;storeDataCount_plus2 <= newstoreDataCount_plus2;stateStore <= Data;endelsebeginstateStore <= Data;endendendendrulerule storePage_Data(doingStore && stateStore == Data);if((mWrBTerm == 1) && (storeDataCount_plus2 < (fromInteger(valueof(BeatsPerBurst)))) || (mErr == 1))begin// We got terminated / ErroredwrBurst <= 1'b0;storeDataCount <= 0;storeDataCount_plus2 <= 2;stateStore <= Idle; // Can't burst for a cycle p. 30endelse if(mWrDAck == 1)beginstoreDataCount <= newstoreDataCount;storeDataCount_plus2 <= newstoreDataCount_plus2;if(newstoreDataCount == 0)begin//We're now done reading... what should we do?// Data transfer completeif(mBusy == 0)begindoingStore <= False;stateStore <= Idle;storeValid.deq();storeCounter <= storeCounter + 1;endelsebeginstateStore <= WaitForBusy;endendelse if(newstoreDataCount == maxBound) //YYY: used to be ~0begin// Last read is upcoming. Need to set down the// wrBurst signal.wrBurst <= 1'b0;endendendrulerule storePage_WaitForBusy(doingStore && stateStore == WaitForBusy);if(mErr == 1)begin// We got terminated / ErroredwrBurst <= 1'b0;storeDataCount <= 0; // may not be necessarystoreDataCount_plus2 <= 2;stateStore <= Idle; // Can't burst for a cycle p. 30endelse if(mBusy == 0)beginstoreCounter <= storeCounter + 1;doingStore <= False;stateStore <= Idle;storeValid.deq();endendrule/********/* Code For Handling Record Translation/*******/Reg#(Bit#(DoubleWordWidth)) recordSled <- mkReg(0);rule writeStoreData(storeValid.notFull());storeBufferWritePointer <= storeBufferWritePointer + 1;case(storeBufferWritePointer[0])0: storeBuffer.upd(storeBufferWritePointer, {recordInfifo.first[31:0] ,recordInfifo.first[63:32]});1: storeBuffer.upd(storeBufferWritePointer, {recordInfifo.first[95:64],recordInfifo.first[127:96]});endcaseif((storeBufferWritePointer + 1)[0] == 0)beginrecordInfifo.deq;endBit#(TLog#(BeatsPerBurst)) bottomValue = 0;if(truncate(storeBufferWritePointer + 1) == bottomValue)begin$display("Store Data finished a flight");storeValid.enq(0);endendrulerule wordToRecord(loadValid.notEmpty());loadBufferReadPointer <= loadBufferReadPointer + 1;Bit#(64) loadValue = loadBuffer.sub(loadBufferReadPointer);Bit#(32) loadHigh = loadValue [63:32];Bit#(32) loadLow = loadValue [31:0];Bit#(TLog#(BeatsPerBurst)) bottomValue = 0;if(truncate(loadBufferReadPointer + 1) == bottomValue)begin$display("Load Data finished a flight");loadValid.deq();endif((loadBufferReadPointer + 1)[0] == 0)beginrecordOutfifo.enq({{loadLow,loadHigh},recordSled});endelsebeginrecordSled <= {loadLow,loadHigh};endendruleinterface Put wordInput = fifoToPut(recordInfifo);interface Get wordOutput = fifoToGet(recordOutfifo);interface Put plbMasterCommandInput = fifoToPut(plbMasterCommandInfifo);interface PLBMasterWires plbMasterWires;method Bit#(PLBAddrSize) mABus(); // Address Busreturn mABus_o;endmethodmethod Bit#(8) mBE(); // Byte Enablereturn mBE_o;endmethodmethod Bit#(1) mRNW(); // Read Not Writereturn mRNW_o;endmethodmethod Bit#(1) mAbort(); // Abortreturn mAbort_o;endmethodmethod Bit#(1) mBusLock(); // Bus lockreturn mBusLock_o;endmethodmethod Bit#(1) mCompress(); // compressed transferreturn mCompress_o;endmethodmethod Bit#(1) mGuarded(); // guarded transferreturn mGuarded_o;endmethodmethod Bit#(1) mLockErr(); // lock errorreturn mLockErr_o;endmethodmethod Bit#(2) mMSize(); // data bus width?return mMSize_o;endmethodmethod Bit#(1) mOrdered(); // synchronize transferreturn mOrdered_o;endmethodmethod Bit#(2) mPriority(); // priority indicatorreturn mPriority_o;endmethodmethod Bit#(1) mRdBurst(); // read burstreturn mRdBurst_o;endmethodmethod Bit#(1) mRequest(); // bus requestreturn mRequest_o;endmethodmethod Bit#(4) mSize(); // transfer sizereturn mSize_o;endmethodmethod Bit#(3) mType(); // transfer type (dma)return mType_o;endmethodmethod Bit#(1) mWrBurst(); // write burstreturn mWrBurst_o;endmethodmethod Bit#(64) mWrDBus(); // write data busreturn mWrDBus_o;endmethodmethod Action plbIN(Bit#(1) mRst_in, // PLB resetBit#(1) mAddrAck_in, // Addr AckBit#(1) mBusy_in, // Master BusyBit#(1) mErr_in, // Slave ErrorBit#(1) mRdBTerm_in, // Read burst terminate signalBit#(1) mRdDAck_in, // Read data ackBit#(64)mRdDBus_in, // Read data busBit#(3) mRdWdAddr_in, // Read word addressBit#(1) mRearbitrate_in, // RearbitrateBit#(1) mWrBTerm_in, // Write burst terminateBit#(1) mWrDAck_in, // Write data ackBit#(1) mSSize_in, // Slave bus sizeBit#(1) sMErr_in, // Slave errorBit#(1) sMBusy_in); // Slave busymRst <= mRst_in;mAddrAck <= mAddrAck_in;mBusy <= mBusy_in;mErr <= mErr_in;mRdBTerm <= mRdBTerm_in;mRdDAck <= mRdDAck_in;mRdDBus <= mRdDBus_in;mRdWdAddr <= mRdWdAddr_in;mRearbitrate <= mRearbitrate_in;mWrBTerm <= mWrBTerm_in;mWrDAck <= mWrDAck_in;mSSize <= mSSize_in;sMErr <= sMErr_in;sMBusy <= sMBusy_in;endmethodendinterfaceendmodule
