Loading files
//
// Memory Access Controller
// キャッシュとメモリの間に存在し、
// メモリアクセス要求の形式を変換する。
// ICacheとDCacheからのアクセスの調停も行う。
//
module MemoryAccessController (
port : modport CacheSystemIF::MemoryAccessController,
nextMemReadSerial : input MemAccessSerial , // RSDの次の読み出し要求に割り当てられるシリアル(id)
nextMemWriteSerial : input MemWriteSerial , // RSDの次の書き込み要求に割り当てられるシリアル(id)
memReadData : input MemoryTypes::MemoryEntryDataPath ,
memReadDataReady : input logic ,
memReadSerial : input MemAccessSerial , // メモリの読み出しデータのシリアル
memAccessResponse : input MemAccessResponse , // メモリ書き込み完了通知
memAccessReadBusy : input logic ,
memAccessWriteBusy : input logic ,
memAccessAddr : output MemoryMapTypes::PhyAddrPath ,
memAccessWriteData : output MemoryTypes::MemoryEntryDataPath ,
memAccessRE : output logic ,
memAccessWE : output logic ,
) {
import BasicTypes::*;
import CacheSystemTypes::*;
import MemoryTypes::*;
import MemoryMapTypes::*;
// ICache/DCacheからの要求を受理するか否か
var icAck: logic;
var dcAck: logic;
// メモリアクセスのシリアル番号を保持するカウンタ
// 現在の実装では、読出し
var reqSerial : MemAccessSerial;
var nextReqSerial : MemAccessSerial;
var resultSerial : MemAccessSerial;
var nextResultSerial: MemAccessSerial;
always_ff (port.clk) {
if port.rst {
reqSerial = '0;
resultSerial = '0;
} else {
reqSerial = nextReqSerial;
resultSerial = nextResultSerial;
}
}
// メモリへのアクセス要求
always_comb {
// ICache/DCacheの要求を受けるor何もしない を決定
icAck = FALSE;
dcAck = FALSE;
if !memAccessReadBusy && port.icMemAccessReq.valid {
icAck = TRUE;
} else if !memAccessReadBusy && port.dcMemAccessReq.valid && (port.dcMemAccessReq.we == FALSE) {
dcAck = TRUE;
} else if !memAccessWriteBusy && port.dcMemAccessReq.valid && (port.dcMemAccessReq.we == TRUE) {
dcAck = TRUE;
}
// ICache/DCacheの要求を受ける場合、
// それに従ってメモリへリクエストを送る
if icAck {
memAccessAddr = port.icMemAccessReq.addr;
memAccessWriteData = '0;
memAccessRE = TRUE;
memAccessWE = FALSE;
} else if dcAck {
memAccessAddr = port.dcMemAccessReq.addr;
memAccessWriteData = port.dcMemAccessReq.data;
if port.dcMemAccessReq.we {
memAccessRE = FALSE;
memAccessWE = TRUE;
} else {
memAccessRE = TRUE;
memAccessWE = FALSE;
}
} else {
memAccessAddr = '0;
memAccessWriteData = '0;
memAccessRE = FALSE;
memAccessWE = FALSE;
}
// Ack for Request
port.icMemAccessReqAck.ack = icAck;
port.icMemAccessReqAck.serial = nextMemReadSerial;
port.dcMemAccessReqAck.ack = dcAck;
// D-Cacheの要求は書き込みと読み出しの2種類あり,シリアルは独立に管理されている
port.dcMemAccessReqAck.serial = nextMemReadSerial;
port.dcMemAccessReqAck.wserial = nextMemWriteSerial;
}
// メモリの読出し結果
always_comb {
port.icMemAccessResult.valid = memReadDataReady;
port.icMemAccessResult.serial = memReadSerial;
port.icMemAccessResult.data = memReadData;
port.dcMemAccessResult.valid = memReadDataReady;
port.dcMemAccessResult.serial = memReadSerial;
port.dcMemAccessResult.data = memReadData;
port.dcMemAccessResponse = memAccessResponse;
}
// MemAccessSerial
always_comb {
nextReqSerial = reqSerial;
nextResultSerial = resultSerial;
// 読出要求が来たら、reqSerialをインクリメント
if icAck || (dcAck && port.dcMemAccessReq.we == FALSE) {
nextReqSerial = reqSerial + 1;
}
// 読出結果が来たら、resultSerialをインクリメント
if memReadDataReady {
nextResultSerial = resultSerial + 1;
}
}
// 現在の実装では、キャッシュラインのデータ幅とメモリの入出力データ幅は
// 同じである必要がある。
// NOT_TRANSPILED_TO_VERYL
// `RSD_STATIC_ASSERT(
// $bits(ICacheLinePath) == $bits(MemoryEntryDataPath),
// ("The data width of a cache line(%x) and a memory entry(%x) are not matched.", $bits(ICacheLinePath), $bits(MemoryEntryDataPath))
// );
// NOT_TRANSPILED_TO_VERYL
// `RSD_STATIC_ASSERT(
// $bits(DCacheLinePath) == $bits(MemoryEntryDataPath),
// ("The data width of a cache line(%x) and a memory entry(%x) are not matched.", $bits(DCacheLinePath), $bits(MemoryEntryDataPath))
// );
}
dcf560ce9This file is pinned to the selected release. Download the original to open it in your design tool.