diff --git a/wally-pipelined/src/ahblite.sv b/wally-pipelined/src/ahblite.sv index b6a7b828c..4266bc369 100644 --- a/wally-pipelined/src/ahblite.sv +++ b/wally-pipelined/src/ahblite.sv @@ -35,17 +35,17 @@ module ahblite ( // Load control input logic UnsignedLoadM, // Signals from Instruction Cache - input logic [`XLEN-1:0] IPAdrD, - input logic IReadD, + input logic [`XLEN-1:0] IPAdrF, + input logic IReadF, output logic [`XLEN-1:0] IRData, - output logic IReady, +// output logic IReady, // Signals from Data Cache input logic [`XLEN-1:0] DPAdrM, input logic DReadM, DWriteM, input logic [`XLEN-1:0] DWDataM, input logic [1:0] DSizeM, output logic [`XLEN-1:0] DRData, - output logic DReady, +// output logic DReady, // AHB-Lite external signals input logic [`AHBW-1:0] HRDATA, input logic HREADY, HRESP, @@ -57,12 +57,15 @@ module ahblite ( output logic [2:0] HBURST, output logic [3:0] HPROT, output logic [1:0] HTRANS, - output logic HMASTLOCK + output logic HMASTLOCK, + // Stalls + output logic InstrStall, DataStall ); logic GrantData; logic [2:0] ISize; logic [`AHBW-1:0] HRDATAMasked; + logic IReady, DReady; assign HCLK = clk; assign HRESETn = ~reset; @@ -79,22 +82,28 @@ module ahblite ( endgenerate // drive bus outputs - assign HADDR = GrantData ? DPAdrM[31:0] : IPAdrD[31:0]; + assign HADDR = GrantData ? DPAdrM[31:0] : IPAdrF[31:0]; assign HWDATA = DWDataM; //flop #(`XLEN) wdreg(HCLK, DWDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN assign HWRITE = DWriteM; assign HSIZE = GrantData ? {1'b0, DSizeM} : ISize; assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfHPROT assign HPROT = 4'b0011; // not used; see Section 3.7 - assign HTRANS = IReadD | DReadM | DWriteM ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise + assign HTRANS = IReadF | DReadM | DWriteM ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise assign HMASTLOCK = 0; // no locking supported // Route signals to Instruction and Data Caches // *** assumes AHBW = XLEN assign IRData = HRDATAMasked; - assign IReady = HREADY & IReadD & ~GrantData; + assign IReady = HREADY & IReadF & ~GrantData; // maybe unused?*** assign DRData = HRDATAMasked; - assign DReady = HREADY & GrantData; + assign DReady = HREADY & GrantData; // ***unused? + + // stalls + // Stall MEM stage if data is being accessed and bus isn't yet ready + assign DataStall = GrantData & ~HREADY; + // Stall Fetch stage if instruction should be read but reading data or bus isn't ready + assign InstrStall = IReadF & (GrantData | ~HREADY); // *** consider adding memory access faults based on HRESP being high // InstrAccessFaultF, DataAccessFaultM, diff --git a/wally-pipelined/src/dcu.sv b/wally-pipelined/src/dcu.sv index eae6224ed..e6f01bd49 100644 --- a/wally-pipelined/src/dcu.sv +++ b/wally-pipelined/src/dcu.sv @@ -42,7 +42,6 @@ module dcu ( output logic StoreMisalignedFaultM, StoreAccessFaultM ); -// memdp memdp(.*); // Determine if an Unaligned access is taking place always_comb diff --git a/wally-pipelined/src/dtim.sv b/wally-pipelined/src/dtim.sv index 27ec6704b..a3f69ee47 100644 --- a/wally-pipelined/src/dtim.sv +++ b/wally-pipelined/src/dtim.sv @@ -39,11 +39,35 @@ module dtim ( // logic [`XLEN-1:0] write; logic [15:0] entry; logic memread, memwrite; +// logic busy; + logic [3:0] busycount; + + // busy FSM to extend READY signal + always_ff @(posedge HCLK, negedge HRESETn) + if (~HRESETn) begin +// busy <= 0; + HREADYTim <= 1; + end else begin +// if (~busy & HSELTim) begin + if (HREADYTim & HSELTim) begin +// busy <= 1; + busycount <= 0; + HREADYTim <= 0; +// end else if (busy) begin + end else if (~HREADYTim) begin + busycount <= busycount + 1; + if (busycount == 4) begin // TIM latency, for testing purposes +// busy <= 0; + HREADYTim <= 1; + end + end + end + assign memread = MemRWtim[1]; assign memwrite = MemRWtim[0]; assign HRESPTim = 0; // OK - assign HREADYTim = 1; // Respond immediately; *** extend this +// assign HREADYTim = 1; // Respond immediately; *** extend this // word aligned reads generate diff --git a/wally-pipelined/src/hazard.sv b/wally-pipelined/src/hazard.sv index d454e5e0c..1fbd9115d 100644 --- a/wally-pipelined/src/hazard.sv +++ b/wally-pipelined/src/hazard.sv @@ -29,6 +29,7 @@ module hazard( input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW, input logic PCSrcE, MemReadE, input logic RegWriteM, RegWriteW, CSRWritePendingDEM, RetM, TrapM, + input logic InstrStall, DataStall, output logic [1:0] ForwardAE, ForwardBE, output logic StallF, StallD, FlushD, FlushE, FlushM, FlushW, output logic LoadStallD); @@ -54,11 +55,24 @@ module hazard( // Exceptions: flush entire pipeline // Ret instructions: occur in M stage. Might be possible to move earlier, but be careful about hazards + // General stall and flush rules: + // A stage must stall if the next stage is stalled + // If any stages are stalled, the first stage that isn't stalled must flush. + assign LoadStallD = MemReadE & ((Rs1D == RdE) | (Rs2D == RdE)); assign StallD = LoadStallD; - assign StallF = LoadStallD | CSRWritePendingDEM; - assign FlushD = PCSrcE | CSRWritePendingDEM | RetM | TrapM; + assign StallF = StallD | InstrStall | CSRWritePendingDEM; + assign FlushD = PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM; assign FlushE = LoadStallD | PCSrcE | RetM | TrapM; assign FlushM = RetM | TrapM; assign FlushW = TrapM; + +/* + assign LoadStallD = MemReadE & ((Rs1D == RdE) | (Rs2D == RdE)); + assign StallD = LoadStallD; + assign StallF = StallD | CSRWritePendingDEM; + assign FlushD = PCSrcE | CSRWritePendingDEM | RetM | TrapM; + assign FlushE = LoadStallD | PCSrcE | RetM | TrapM; + assign FlushM = RetM | TrapM; + assign FlushW = TrapM; */ endmodule diff --git a/wally-pipelined/src/wallypipelinedhart.sv b/wally-pipelined/src/wallypipelinedhart.sv index 909cbee10..1f1f15108 100644 --- a/wally-pipelined/src/wallypipelinedhart.sv +++ b/wally-pipelined/src/wallypipelinedhart.sv @@ -87,16 +87,17 @@ module wallypipelinedhart ( logic [2:0] Funct3M; logic [`XLEN-1:0] DataAdrM, WriteDataM; logic [`XLEN-1:0] ReadDataM; + logic DataStall, InstrStall; ifu ifu(.*); // instruction fetch unit: PC, branch prediction, instruction cache ieu ieu(.*); // inteber execution unit: integer register file, datapath and controller dcu dcu(/*.Funct3M(InstrM[14:12]),*/ .*); // data cache unit - ahblite ebu( - .IPAdrD(zero), .IReadD(1'b0), .IRData(), .IReady(), + ahblite ebu( // *** make IRData InstrF + .IPAdrF(PCF), .IReadF(1'b0), .IRData(), //.IReady(), .DPAdrM(DataAdrM), .DReadM(MemRWdcuoutM[1]), .DWriteM(MemRWdcuoutM[0]), .DWDataM(WriteDataM), - .DSizeM(Funct3M[1:0]), .DRData(ReadDataM), .DReady(), + .DSizeM(Funct3M[1:0]), .DRData(ReadDataM), //.DReady(), .UnsignedLoadM(Funct3M[2]), .*); // assign UnsignedLoadM = Funct3M[2]; // *** maybe move read extension to dcu