diff --git a/pipelined/regression/wave-dos/ahb-muldiv.do b/pipelined/regression/wave-dos/ahb-muldiv.do index 98df30a71..bd212f774 100644 --- a/pipelined/regression/wave-dos/ahb-muldiv.do +++ b/pipelined/regression/wave-dos/ahb-muldiv.do @@ -67,6 +67,7 @@ add wave -hex /testbench/dut/core/ebu/HTRANS add wave -hex /testbench/dut/core/ebu/HRDATA add wave -hex /testbench/dut/core/ebu/HWRITE add wave -hex /testbench/dut/core/ebu/HWDATA +add wave -hex /testbench/dut/core/ebu/HBURST add wave -hex /testbench/dut/core/ebu/CaptureDataM add wave -divider diff --git a/pipelined/regression/wave.do b/pipelined/regression/wave.do index ecfc06d11..b8d2d4484 100644 --- a/pipelined/regression/wave.do +++ b/pipelined/regression/wave.do @@ -473,6 +473,7 @@ add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUBusRead add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUBusAdr add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUBusAck add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUBusHRDATA +add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUTransComplete add wave -noupdate -group ifu -expand -group spill /testbench/dut/core/ifu/SpillSupport/spillsupport/SpillF add wave -noupdate -group ifu -expand -group spill /testbench/dut/core/ifu/SpillSupport/spillsupport/CurrState add wave -noupdate -group ifu -expand -group spill /testbench/dut/core/ifu/SpillSupport/spillsupport/SpillDataLine0 diff --git a/pipelined/src/ebu/ahblite.sv b/pipelined/src/ebu/ahblite.sv index 35b3797bb..41305090d 100644 --- a/pipelined/src/ebu/ahblite.sv +++ b/pipelined/src/ebu/ahblite.sv @@ -45,6 +45,10 @@ module ahblite ( input logic IFUBusRead, output logic [`XLEN-1:0] IFUBusHRDATA, output logic IFUBusAck, + output logic IFUBusInit, + input logic [2:0] IFUBurstType, + input logic [1:0] IFUTransType, + input logic IFUTransComplete, // Signals from Data Cache input logic [`PA_BITS-1:0] LSUBusAdr, input logic LSUBusRead, @@ -52,7 +56,11 @@ module ahblite ( input logic [`XLEN-1:0] LSUBusHWDATA, output logic [`XLEN-1:0] LSUBusHRDATA, input logic [2:0] LSUBusSize, + input logic [2:0] LSUBurstType, + input logic [1:0] LSUTransType, + input logic LSUTransComplete, output logic LSUBusAck, + output logic LSUBusInit, // AHB-Lite external signals (* mark_debug = "true" *) input logic [`AHBW-1:0] HRDATA, (* mark_debug = "true" *) input logic HREADY, HRESP, @@ -87,6 +95,9 @@ module ahblite ( // Data accesses have priority over instructions. However, if a data access comes // while an instruction read is occuring, the instruction read finishes before // the data access can take place. + // *** This is no longer true when adding burst mode. We need to finish the current + // read before doing another read. Need to work this out, but preliminarily we can + // store the current read type in a flop and use that to figure out what burst type to use. flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState); @@ -100,19 +111,21 @@ module ahblite ( // interface that might be used in place of the ahblite. always_comb case (BusState) - IDLE: if (LSUBusRead) NextBusState = MEMREAD; // Memory has priority over instructions - else if (LSUBusWrite)NextBusState = MEMWRITE; - else if (IFUBusRead) NextBusState = INSTRREAD; - else NextBusState = IDLE; - MEMREAD: if (~HREADY) NextBusState = MEMREAD; - else if (IFUBusRead) NextBusState = INSTRREAD; - else NextBusState = IDLE; - MEMWRITE: if (~HREADY) NextBusState = MEMWRITE; - else if (IFUBusRead) NextBusState = INSTRREAD; - else NextBusState = IDLE; - INSTRREAD: if (~HREADY) NextBusState = INSTRREAD; - else NextBusState = IDLE; // if (IFUBusRead still high) *** need to wait? - default: NextBusState = IDLE; + IDLE: if (LSUBusRead) NextBusState = MEMREAD; // Memory has priority over instructions + else if (LSUBusWrite) NextBusState = MEMWRITE; + else if (IFUBusRead) NextBusState = INSTRREAD; + else NextBusState = IDLE; + MEMREAD: if (LSUTransComplete & IFUBusRead) NextBusState = INSTRREAD; + else if (LSUTransComplete) NextBusState = IDLE; + else NextBusState = MEMREAD; + MEMWRITE: if (LSUTransComplete & IFUBusRead) NextBusState = INSTRREAD; + else if (LSUTransComplete) NextBusState = IDLE; + else NextBusState = MEMWRITE; + INSTRREAD: if (IFUTransComplete & LSUBusRead) NextBusState = MEMREAD; + else if (IFUTransComplete & LSUBusWrite) NextBusState = MEMWRITE; + else if (IFUTransComplete) NextBusState = IDLE; + else NextBusState = INSTRREAD; + default: NextBusState = IDLE; endcase @@ -122,7 +135,7 @@ module ahblite ( assign #1 HADDR = AccessAddress; assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway assign HSIZE = (GrantData) ? {1'b0, LSUBusSize[1:0]} : ISize; - assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH + assign HBURST = (GrantData) ? LSUBurstType : IFUBurstType; // If doing memory accesses, use LSUburst, else use Instruction burst. /* Cache burst read/writes case statement (hopefully) WRAPS only have access to 4 wraps. X changes position based on HSIZE. 000: Single (SINGLE) @@ -133,15 +146,16 @@ module ahblite ( 101: 8-beat incrementing burst (INCR8) 110: 16-beat wrapping burst (WRAP16) [wraps if X in 0X000000] 111: 16-beat incrementing burst (INCR16) - */ + *** Remove if not necessary + */ assign HPROT = 4'b0011; // not used; see Section 3.7 - assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise + assign HTRANS = (GrantData) ? LSUTransType : IFUTransType; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise assign HMASTLOCK = 0; // no locking supported - assign HWRITE = NextBusState == MEMWRITE; + assign HWRITE = (NextBusState == MEMWRITE); // delay write data by one cycle for - flop #(`XLEN) wdreg(HCLK, LSUBusHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN + flopen #(`XLEN) wdreg(HCLK, (LSUBusAck | LSUBusInit), LSUBusHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN // delay signals for subword writes flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD); flop #(4) sizereg(HCLK, {UnsignedLoadM, HSIZE}, HSIZED); @@ -153,7 +167,9 @@ module ahblite ( assign IFUBusHRDATA = HRDATA; assign LSUBusHRDATA = HRDATA; - assign IFUBusAck = (BusState == INSTRREAD) & (NextBusState != INSTRREAD); - assign LSUBusAck = (BusState == MEMREAD) & (NextBusState != MEMREAD) | (BusState == MEMWRITE) & (NextBusState != MEMWRITE); + assign IFUBusInit = (BusState != INSTRREAD) & (NextBusState == INSTRREAD); + assign LSUBusInit = (((BusState != MEMREAD) & (NextBusState == MEMREAD)) | (BusState != MEMWRITE) & (NextBusState == MEMWRITE)); + assign IFUBusAck = HREADY & (BusState == INSTRREAD); + assign LSUBusAck = HREADY & ((BusState == MEMREAD) | (BusState == MEMWRITE)); endmodule diff --git a/pipelined/src/ifu/ifu.sv b/pipelined/src/ifu/ifu.sv index 8fa351022..29d07cc2c 100644 --- a/pipelined/src/ifu/ifu.sv +++ b/pipelined/src/ifu/ifu.sv @@ -38,9 +38,13 @@ module ifu ( // Bus interface (* mark_debug = "true" *) input logic [`XLEN-1:0] IFUBusHRDATA, (* mark_debug = "true" *) input logic IFUBusAck, +(* mark_debug = "true" *) input logic IFUBusInit, (* mark_debug = "true" *) output logic [`PA_BITS-1:0] IFUBusAdr, (* mark_debug = "true" *) output logic IFUBusRead, (* mark_debug = "true" *) output logic IFUStallF, +(* mark_debug = "true" *) output logic [2:0] IFUBurstType, +(* mark_debug = "true" *) output logic [1:0] IFUTransType, +(* mark_debug = "true" *) output logic IFUTransComplete, (* mark_debug = "true" *) output logic [`XLEN-1:0] PCF, // Execute output logic [`XLEN-1:0] PCLinkE, @@ -201,8 +205,8 @@ module ifu ( busdp #(WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED) busdp(.clk, .reset, - .LSUBusHRDATA(IFUBusHRDATA), .LSUBusAck(IFUBusAck), .LSUBusWrite(), .LSUBusWriteCrit(), - .LSUBusRead(IFUBusRead), .LSUBusSize(), + .LSUBusHRDATA(IFUBusHRDATA), .LSUBusAck(IFUBusAck), .LSUBusInit(IFUBusInit), .LSUBusWrite(), .LSUBusWriteCrit(), + .LSUBusRead(IFUBusRead), .LSUBusSize(), .LSUBurstType(IFUBurstType), .LSUTransType(IFUTransType), .LSUTransComplete(IFUTransComplete), .LSUFunct3M(3'b010), .LSUBusAdr(IFUBusAdr), .DCacheBusAdr(ICacheBusAdr), .WordCount(), .DCacheFetchLine(ICacheFetchLine), diff --git a/pipelined/src/lsu/busdp.sv b/pipelined/src/lsu/busdp.sv index e80de5bde..5139efdc1 100644 --- a/pipelined/src/lsu/busdp.sv +++ b/pipelined/src/lsu/busdp.sv @@ -40,9 +40,13 @@ module busdp #(parameter WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED) // bus interface input logic [`XLEN-1:0] LSUBusHRDATA, input logic LSUBusAck, + input logic LSUBusInit, output logic LSUBusWrite, output logic LSUBusRead, - output logic [2:0] LSUBusSize, + output logic [2:0] LSUBusSize, + output logic [2:0] LSUBurstType, + output logic [1:0] LSUTransType, // For AHBLite + output logic LSUTransComplete, input logic [2:0] LSUFunct3M, output logic [`PA_BITS-1:0] LSUBusAdr, // ** change name to HADDR to make ahb lite. output logic [LOGWPL-1:0] WordCount, @@ -66,13 +70,15 @@ module busdp #(parameter WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED) localparam integer WordCountThreshold = CACHE_ENABLED ? WORDSPERLINE - 1 : 0; logic [`PA_BITS-1:0] LocalLSUBusAdr; + logic [LOGWPL-1:0] WordCountDelayed; + // *** implement flops as an array if feasbile; DCacheBusWriteData might be a problem // *** better name than DCacheBusWriteData genvar index; for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer logic [WORDSPERLINE-1:0] CaptureWord; - assign CaptureWord[index] = LSUBusAck & LSUBusRead & (index == WordCount); + assign CaptureWord[index] = LSUBusAck & LSUBusRead & (index == WordCountDelayed); flopen #(`XLEN) fb(.clk, .en(CaptureWord[index]), .d(LSUBusHRDATA), .q(DCacheBusWriteData[(index+1)*`XLEN-1:index*`XLEN])); end @@ -83,6 +89,6 @@ module busdp #(parameter WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED) busfsm #(WordCountThreshold, LOGWPL, CACHE_ENABLED) busfsm( .clk, .reset, .IgnoreRequest, .LSURWM, .DCacheFetchLine, .DCacheWriteLine, - .LSUBusAck, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusWriteCrit, .LSUBusRead, - .DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount); + .LSUBusAck, .LSUBusInit, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusWriteCrit, .LSUBusRead, + .LSUBurstType, .LSUTransType, .LSUTransComplete, .DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount, .WordCountDelayed); endmodule diff --git a/pipelined/src/lsu/busfsm.sv b/pipelined/src/lsu/busfsm.sv index f3860c0d6..225f2de6d 100644 --- a/pipelined/src/lsu/busfsm.sv +++ b/pipelined/src/lsu/busfsm.sv @@ -41,6 +41,7 @@ module busfsm #(parameter integer WordCountThreshold, input logic DCacheFetchLine, input logic DCacheWriteLine, input logic LSUBusAck, + input logic LSUBusInit, // This might be better as LSUBusLock, or to send this using LSUBusAck. input logic CPUBusy, input logic CacheableM, @@ -48,10 +49,13 @@ module busfsm #(parameter integer WordCountThreshold, output logic LSUBusWrite, output logic LSUBusWriteCrit, output logic LSUBusRead, + output logic [2:0] LSUBurstType, + output logic LSUTransComplete, + output logic [1:0] LSUTransType, output logic DCacheBusAck, output logic BusCommittedM, output logic SelUncachedAdr, - output logic [LOGWPL-1:0] WordCount); + output logic [LOGWPL-1:0] WordCount, WordCountDelayed); @@ -61,7 +65,8 @@ module busfsm #(parameter integer WordCountThreshold, logic CntReset; logic WordCountFlag; logic [LOGWPL-1:0] NextWordCount; - logic UnCachedAccess; + logic UnCachedAccess, UnCachedRW; + logic [2:0] LocalBurstType; typedef enum logic [2:0] {STATE_BUS_READY, @@ -75,18 +80,27 @@ module busfsm #(parameter integer WordCountThreshold, (* mark_debug = "true" *) busstatetype BusCurrState, BusNextState; - + // Used to send address for address stage of AHB. flopenr #(LOGWPL) WordCountReg(.clk(clk), .reset(reset | CntReset), .en(CntEn), .d(NextWordCount), - .q(WordCount)); + .q(WordCount)); + + // Used to store data from data phase of AHB. + flopenr #(LOGWPL) + WordCountDelayedReg(.clk(clk), + .reset(reset | CntReset), + .en(CntEn), + .d(WordCount), + .q(WordCountDelayed)); assign NextWordCount = WordCount + 1'b1; - assign WordCountFlag = (WordCount == WordCountThreshold[LOGWPL-1:0]); - assign CntEn = PreCntEn & LSUBusAck; + assign PreCntEn = (BusCurrState == STATE_BUS_FETCH) | (BusCurrState == STATE_BUS_WRITE); + assign WordCountFlag = (WordCountDelayed == WordCountThreshold[LOGWPL-1:0]); // Detect when we are waiting on the final access. + assign CntEn = (PreCntEn & LSUBusAck | (LSUBusInit)) & ~WordCountFlag & ~UnCachedRW; // Want to count when doing cache accesses and we aren't wrapping up. assign UnCachedAccess = ~CACHE_ENABLED | ~CacheableM; @@ -120,14 +134,29 @@ module busfsm #(parameter integer WordCountThreshold, endcase end + always_comb begin + case(WordCountThreshold) + 0: LocalBurstType = 3'b000; + 3: LocalBurstType = 3'b011; // INCR4 + 7: LocalBurstType = 3'b101; // INCR8 + 15: LocalBurstType = 3'b111; // INCR16 + default: LocalBurstType = 3'b001; // INCR without end. + endcase + end - assign CntReset = BusCurrState == STATE_BUS_READY; + // Would these be better as always_comb statements or muxes? + assign LSUBurstType = (UnCachedRW) ? 3'b0 : LocalBurstType; // Don't want to use burst when doing an Uncached Access. + assign LSUTransComplete = (UnCachedRW) ? LSUBusAck : WordCountFlag & LSUBusAck; + // Use SEQ if not doing first word, NONSEQ if doing the first read/write, and IDLE if finishing up. + assign LSUTransType = (|WordCount) & ~UnCachedRW ? 2'b11 : (LSUBusRead | LSUBusWrite) & (~LSUTransComplete) ? 2'b10 : 2'b00; + // Reset if we aren't initiating a transaction or if we are finishing a transaction. + assign CntReset = BusCurrState == STATE_BUS_READY & ~(DCacheFetchLine | DCacheWriteLine) | LSUTransComplete; + assign BusStall = (BusCurrState == STATE_BUS_READY & ~IgnoreRequest & ((UnCachedAccess & (|LSURWM)) | DCacheFetchLine | DCacheWriteLine)) | (BusCurrState == STATE_BUS_UNCACHED_WRITE) | (BusCurrState == STATE_BUS_UNCACHED_READ) | (BusCurrState == STATE_BUS_FETCH) | (BusCurrState == STATE_BUS_WRITE); - assign PreCntEn = BusCurrState == STATE_BUS_FETCH | BusCurrState == STATE_BUS_WRITE; assign UnCachedLSUBusWrite = (BusCurrState == STATE_BUS_READY & UnCachedAccess & LSURWM[0] & ~IgnoreRequest) | (BusCurrState == STATE_BUS_UNCACHED_WRITE); assign LSUBusWrite = UnCachedLSUBusWrite | (BusCurrState == STATE_BUS_WRITE); @@ -139,6 +168,10 @@ module busfsm #(parameter integer WordCountThreshold, (BusCurrState == STATE_BUS_UNCACHED_READ); assign LSUBusRead = UnCachedLSUBusRead | (BusCurrState == STATE_BUS_FETCH) | (BusCurrState == STATE_BUS_READY & DCacheFetchLine); + + // Makes bus only do uncached reads/writes when we actually do uncached reads/writes. Needed because CacheableM is 0 when flushing cache. + assign UnCachedRW = UnCachedLSUBusWrite | UnCachedLSUBusRead; + assign DCacheBusAck = (BusCurrState == STATE_BUS_FETCH & WordCountFlag & LSUBusAck) | (BusCurrState == STATE_BUS_WRITE & WordCountFlag & LSUBusAck); assign BusCommittedM = BusCurrState != STATE_BUS_READY; diff --git a/pipelined/src/lsu/lsu.sv b/pipelined/src/lsu/lsu.sv index 72beea1b4..dbd043d76 100644 --- a/pipelined/src/lsu/lsu.sv +++ b/pipelined/src/lsu/lsu.sv @@ -66,9 +66,13 @@ module lsu ( (* mark_debug = "true" *) output logic LSUBusRead, (* mark_debug = "true" *) output logic LSUBusWrite, (* mark_debug = "true" *) input logic LSUBusAck, + (* mark_debug = "true" *) input logic LSUBusInit, (* mark_debug = "true" *) input logic [`XLEN-1:0] LSUBusHRDATA, (* mark_debug = "true" *) output logic [`XLEN-1:0] LSUBusHWDATA, (* mark_debug = "true" *) output logic [2:0] LSUBusSize, + (* mark_debug = "true" *) output logic [2:0] LSUBurstType, + (* mark_debug = "true" *) output logic [1:0] LSUTransType, + (* mark_debug = "true" *) output logic LSUTransComplete, // page table walker input logic [`XLEN-1:0] SATP_REGW, // from csr input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, @@ -211,7 +215,7 @@ module lsu ( busdp #(WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED) busdp( .clk, .reset, - .LSUBusHRDATA, .LSUBusAck, .LSUBusWrite, .LSUBusRead, .LSUBusSize, + .LSUBusHRDATA, .LSUBusAck, .LSUBusInit, .LSUBusWrite, .LSUBusRead, .LSUBusSize, .LSUBurstType, .LSUTransType, .LSUTransComplete, .WordCount, .LSUBusWriteCrit, .LSUFunct3M, .LSUBusAdr, .DCacheBusAdr, .DCacheFetchLine, .DCacheWriteLine, .DCacheBusAck, .DCacheBusWriteData, .LSUPAdrM, diff --git a/pipelined/src/wally/wallypipelinedcore.sv b/pipelined/src/wally/wallypipelinedcore.sv index 0e9cd5660..e1040ee7a 100644 --- a/pipelined/src/wally/wallypipelinedcore.sv +++ b/pipelined/src/wally/wallypipelinedcore.sv @@ -134,13 +134,16 @@ module wallypipelinedcore ( logic [`PA_BITS-1:0] IFUBusAdr; logic [`XLEN-1:0] IFUBusHRDATA; logic IFUBusRead; - logic IFUBusAck; + logic IFUBusAck, IFUBusInit; + logic [2:0] IFUBurstType; + logic [1:0] IFUTransType; + logic IFUTransComplete; // AHB LSU interface logic [`PA_BITS-1:0] LSUBusAdr; logic LSUBusRead; logic LSUBusWrite; - logic LSUBusAck; + logic LSUBusAck, LSUBusInit; logic [`XLEN-1:0] LSUBusHRDATA; logic [`XLEN-1:0] LSUBusHWDATA; @@ -152,6 +155,9 @@ module wallypipelinedcore ( logic [4:0] InstrClassM; logic InstrAccessFaultF; logic [2:0] LSUBusSize; + logic [2:0] LSUBurstType; + logic [1:0] LSUTransType; + logic LSUTransComplete; logic DCacheMiss; logic DCacheAccess; @@ -166,8 +172,8 @@ module wallypipelinedcore ( .StallF, .StallD, .StallE, .StallM, .FlushF, .FlushD, .FlushE, .FlushM, // Fetch - .IFUBusHRDATA, .IFUBusAck, .PCF, .IFUBusAdr, - .IFUBusRead, .IFUStallF, + .IFUBusHRDATA, .IFUBusAck, .IFUBusInit, .PCF, .IFUBusAdr, + .IFUBusRead, .IFUStallF, .IFUBurstType, .IFUTransType, .IFUTransComplete, .ICacheAccess, .ICacheMiss, // Execute @@ -247,8 +253,8 @@ module wallypipelinedcore ( .IEUAdrE, .IEUAdrM, .WriteDataE, .ReadDataM, .FlushDCacheM, // connected to ahb (all stay the same) - .LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusAck, - .LSUBusHRDATA, .LSUBusHWDATA, .LSUBusSize, + .LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusAck, .LSUBusInit, + .LSUBusHRDATA, .LSUBusHWDATA, .LSUBusSize, .LSUBurstType, .LSUTransType, .LSUTransComplete, // connect to csr or privilege and stay the same. .PrivilegeModeW, .BigEndianM, // connects to csr @@ -279,13 +285,22 @@ module wallypipelinedcore ( ahblite ebu(// IFU connections .clk, .reset, .UnsignedLoadM(1'b0), .AtomicMaskedM(2'b00), - .IFUBusAdr, - .IFUBusRead, .IFUBusHRDATA, .IFUBusAck, + .IFUBusAdr, .IFUBusRead, + .IFUBusHRDATA, + .IFUBurstType, + .IFUTransType, + .IFUTransComplete, + .IFUBusAck, + .IFUBusInit, // Signals from Data Cache .LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusHWDATA, .LSUBusHRDATA, .LSUBusSize, + .LSUBurstType, + .LSUTransType, + .LSUTransComplete, .LSUBusAck, + .LSUBusInit, .HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST, diff --git a/pipelined/testbench/testbench.sv b/pipelined/testbench/testbench.sv index 64629d0d8..796dc2d2f 100644 --- a/pipelined/testbench/testbench.sv +++ b/pipelined/testbench/testbench.sv @@ -418,6 +418,7 @@ module riscvassertions; //assert (`DMEM == `MEM_CACHE | `DBUS ==0) else $error("Dcache rquires DBUS."); //assert (`IMEM == `MEM_CACHE | `IBUS ==0) else $error("Icache rquires IBUS."); assert (`DCACHE_LINELENINBITS <= `XLEN*16 | (`DMEM != `MEM_CACHE)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1"); + assert (`DCACHE_LINELENINBITS % 4 == 0) else $error("DCACHE_LINELENINBITS must hold 4, 8, or 16 words"); end endmodule