2021-01-29 06:07:17 +00:00
|
|
|
///////////////////////////////////////////
|
|
|
|
// ahblite.sv
|
|
|
|
//
|
|
|
|
// Written: David_Harris@hmc.edu 9 January 2021
|
|
|
|
// Modified:
|
|
|
|
//
|
|
|
|
// Purpose: AHB Lite External Bus Unit
|
|
|
|
// See ARM_HIH0033A_AMBA_AHB-Lite_SPEC 1.0
|
|
|
|
// Arbitrates requests from instruction and data streams
|
|
|
|
// Connects hart to peripherals and I/O pins on SOC
|
|
|
|
// Bus width presently matches XLEN
|
|
|
|
// Anticipate replacing this with an AXI bus interface to communicate with FPGA DRAM/Flash controllers
|
|
|
|
//
|
|
|
|
// A component of the Wally configurable RISC-V project.
|
|
|
|
//
|
|
|
|
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
|
|
|
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
|
|
|
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
|
|
|
// is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included 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 WARRANTIES
|
|
|
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
|
|
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
|
|
|
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
///////////////////////////////////////////
|
|
|
|
|
|
|
|
`include "wally-config.vh"
|
|
|
|
|
2021-04-18 21:48:51 +00:00
|
|
|
package ahbliteState;
|
2021-05-04 19:21:01 +00:00
|
|
|
typedef enum logic [3:0] {IDLE, MEMREAD, MEMWRITE, INSTRREAD, ATOMICREAD, ATOMICWRITE, MMUTRANSLATE} statetype;
|
2021-04-18 21:48:51 +00:00
|
|
|
endpackage
|
|
|
|
|
2021-01-29 06:07:17 +00:00
|
|
|
module ahblite (
|
2021-07-09 20:16:38 +00:00
|
|
|
input logic clk, reset,
|
|
|
|
input logic StallW,
|
2021-01-30 04:43:48 +00:00
|
|
|
// Load control
|
2021-07-09 20:16:38 +00:00
|
|
|
input logic UnsignedLoadM,
|
|
|
|
input logic [1:0] AtomicMaskedM,
|
|
|
|
input logic [6:0] Funct7M,
|
2021-01-29 06:07:17 +00:00
|
|
|
// Signals from Instruction Cache
|
2021-07-09 20:16:38 +00:00
|
|
|
input logic [`PA_BITS-1:0] InstrPAdrF, // *** rename these to match block diagram
|
|
|
|
input logic InstrReadF,
|
|
|
|
output logic [`XLEN-1:0] InstrRData,
|
|
|
|
output logic InstrAckF,
|
2021-01-29 06:07:17 +00:00
|
|
|
// Signals from Data Cache
|
2021-07-09 20:16:38 +00:00
|
|
|
input logic [`PA_BITS-1:0] DCtoAHBPAdrM,
|
|
|
|
input logic DCtoAHBReadM,
|
|
|
|
input logic DCtoAHBWriteM,
|
|
|
|
input logic [`XLEN-1:0] DCtoAHBWriteData,
|
|
|
|
output logic [`XLEN-1:0] DCfromAHBReadData,
|
|
|
|
input logic [1:0] MemSizeM, // *** remove
|
|
|
|
output logic DCfromAHBAck,
|
2021-01-30 06:57:51 +00:00
|
|
|
// Return from bus
|
2021-07-17 06:15:24 +00:00
|
|
|
// output logic [`XLEN-1:0] HRDATAW,
|
2021-01-29 06:07:17 +00:00
|
|
|
// AHB-Lite external signals
|
2021-07-09 20:16:38 +00:00
|
|
|
input logic [`AHBW-1:0] HRDATA,
|
|
|
|
input logic HREADY, HRESP,
|
|
|
|
output logic HCLK, HRESETn,
|
|
|
|
output logic [31:0] HADDR,
|
|
|
|
output logic [`AHBW-1:0] HWDATA,
|
|
|
|
output logic HWRITE,
|
|
|
|
output logic [2:0] HSIZE,
|
|
|
|
output logic [2:0] HBURST,
|
|
|
|
output logic [3:0] HPROT,
|
|
|
|
output logic [1:0] HTRANS,
|
|
|
|
output logic HMASTLOCK,
|
2021-02-15 15:10:50 +00:00
|
|
|
// Delayed signals for writes
|
2021-07-09 20:16:38 +00:00
|
|
|
output logic [2:0] HADDRD,
|
|
|
|
output logic [3:0] HSIZED,
|
|
|
|
output logic HWRITED,
|
2021-01-30 06:43:49 +00:00
|
|
|
// Stalls
|
2021-07-09 20:16:38 +00:00
|
|
|
output logic CommitM
|
2021-01-29 06:07:17 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
logic GrantData;
|
2021-03-25 06:48:40 +00:00
|
|
|
logic [31:0] AccessAddress;
|
|
|
|
logic [2:0] AccessSize, PTESize, ISize;
|
2021-07-09 20:16:38 +00:00
|
|
|
logic [`AHBW-1:0] HRDATAMasked, ReadDataM, HRDATANext, CapturedHRDATAMasked, WriteData;
|
2021-01-30 06:43:49 +00:00
|
|
|
logic IReady, DReady;
|
2021-04-26 11:43:16 +00:00
|
|
|
logic CaptureDataM,CapturedDataAvailable;
|
2021-01-29 06:07:17 +00:00
|
|
|
|
|
|
|
assign HCLK = clk;
|
|
|
|
assign HRESETn = ~reset;
|
|
|
|
|
2021-03-05 06:22:53 +00:00
|
|
|
// *** initially support AHBW = XLEN
|
2021-01-29 06:07:17 +00:00
|
|
|
|
2021-02-08 04:21:55 +00:00
|
|
|
// track bus state
|
2021-02-15 15:10:50 +00:00
|
|
|
// 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.
|
2021-04-18 21:48:51 +00:00
|
|
|
import ahbliteState::*;
|
2021-07-09 20:16:38 +00:00
|
|
|
statetype BusState, NextBusState;
|
2021-02-15 15:10:50 +00:00
|
|
|
|
2021-03-10 19:14:02 +00:00
|
|
|
flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState);
|
2021-02-15 15:10:50 +00:00
|
|
|
|
2021-04-29 06:20:39 +00:00
|
|
|
// This case statement computes the desired next state for the AHBlite,
|
|
|
|
// prioritizing address translations, then atomics, then data accesses, and
|
|
|
|
// finally instructions. This proposition controls HADDR so the PMA and PMP
|
|
|
|
// checkers can determine whether the access is allowed. If not, the actual
|
|
|
|
// NextWalkerState is set to IDLE.
|
|
|
|
|
|
|
|
// *** This ability to squash accesses must be replicated by any bus
|
|
|
|
// interface that might be used in place of the ahblite.
|
2021-02-15 15:10:50 +00:00
|
|
|
always_comb
|
|
|
|
case (BusState)
|
2021-07-09 20:16:38 +00:00
|
|
|
IDLE: if (AtomicMaskedM[1]) NextBusState = ATOMICREAD;
|
|
|
|
else if (DCtoAHBReadM) NextBusState = MEMREAD; // Memory has priority over instructions
|
|
|
|
else if (DCtoAHBWriteM) NextBusState = MEMWRITE;
|
|
|
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
|
|
|
else NextBusState = IDLE;
|
|
|
|
ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD;
|
|
|
|
else NextBusState = ATOMICWRITE;
|
|
|
|
ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE;
|
|
|
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
|
|
|
else NextBusState = IDLE;
|
|
|
|
MEMREAD: if (~HREADY) NextBusState = MEMREAD;
|
|
|
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
|
|
|
else NextBusState = IDLE;
|
|
|
|
MEMWRITE: if (~HREADY) NextBusState = MEMWRITE;
|
|
|
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
|
|
|
else NextBusState = IDLE;
|
|
|
|
INSTRREAD: if (~HREADY) NextBusState = INSTRREAD;
|
|
|
|
else NextBusState = IDLE; // if (InstrReadF still high)
|
|
|
|
default: NextBusState = IDLE;
|
2021-02-15 15:10:50 +00:00
|
|
|
endcase
|
|
|
|
|
2021-03-25 06:48:40 +00:00
|
|
|
|
2021-02-15 15:10:50 +00:00
|
|
|
// bus outputs
|
2021-07-09 20:16:38 +00:00
|
|
|
assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
|
|
|
|
(NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE);
|
|
|
|
assign #1 AccessAddress = (GrantData) ? DCtoAHBPAdrM[31:0] : InstrPAdrF[31:0];
|
2021-06-24 19:42:59 +00:00
|
|
|
//assign #1 HADDR = (MMUTranslate) ? MMUPAdr[31:0] : AccessAddress;
|
|
|
|
assign #1 HADDR = AccessAddress;
|
2021-03-25 06:48:40 +00:00
|
|
|
generate
|
|
|
|
if (`XLEN == 32) assign PTESize = 3'b010; // in rv32, PTEs are 4 bytes
|
|
|
|
else assign PTESize = 3'b011; // in rv64, PTEs are 8 bytes
|
|
|
|
endgenerate
|
2021-02-26 06:03:47 +00:00
|
|
|
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway
|
2021-03-25 06:48:40 +00:00
|
|
|
assign #1 AccessSize = (GrantData) ? {1'b0, MemSizeM} : ISize;
|
2021-06-24 19:42:59 +00:00
|
|
|
//assign #1 HSIZE = (MMUTranslate) ? PTESize : AccessSize;
|
|
|
|
assign #1 HSIZE = AccessSize;
|
2021-02-15 15:10:50 +00:00
|
|
|
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
|
|
|
|
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 HMASTLOCK = 0; // no locking supported
|
2021-03-11 05:11:31 +00:00
|
|
|
assign HWRITE = (NextBusState == MEMWRITE) || (NextBusState == ATOMICWRITE);
|
2021-03-31 02:19:27 +00:00
|
|
|
// delay write data by one cycle for
|
2021-03-11 05:11:31 +00:00
|
|
|
flop #(`XLEN) wdreg(HCLK, WriteData, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
|
2021-02-15 15:10:50 +00:00
|
|
|
// delay signals for subword writes
|
|
|
|
flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD);
|
|
|
|
flop #(4) sizereg(HCLK, {UnsignedLoadM, HSIZE}, HSIZED);
|
|
|
|
flop #(1) writereg(HCLK, HWRITE, HWRITED);
|
|
|
|
|
2021-02-22 18:48:30 +00:00
|
|
|
// Route signals to Instruction and Data Caches
|
|
|
|
// *** assumes AHBW = XLEN
|
2021-02-24 12:25:03 +00:00
|
|
|
|
2021-06-24 19:42:59 +00:00
|
|
|
//assign MMUReady = (BusState == MMUTRANSLATE && HREADY);
|
2021-03-25 06:48:40 +00:00
|
|
|
|
2021-02-24 12:25:03 +00:00
|
|
|
assign InstrRData = HRDATA;
|
2021-07-09 20:16:38 +00:00
|
|
|
assign DCfromAHBReadData = HRDATA;
|
2021-04-30 10:26:31 +00:00
|
|
|
assign InstrAckF = (BusState == INSTRREAD) && (NextBusState != INSTRREAD);
|
2021-06-08 16:32:46 +00:00
|
|
|
assign CommitM = (BusState == MEMREAD) || (BusState == MEMWRITE) || (BusState == ATOMICREAD) || (BusState == ATOMICWRITE);
|
|
|
|
// *** Bracker 6/5/21: why is this W stage?
|
2021-07-09 20:16:38 +00:00
|
|
|
assign DCfromAHBAck = (BusState == MEMREAD) && (NextBusState != MEMREAD) || (BusState == MEMWRITE) && (NextBusState != MEMWRITE);
|
2021-06-24 19:42:59 +00:00
|
|
|
//assign MMUReadPTE = HRDATA;
|
2021-04-26 11:43:16 +00:00
|
|
|
// Carefully decide when to update ReadDataW
|
|
|
|
// ReadDataMstored holds the most recent memory read.
|
|
|
|
// We need to wait until the pipeline actually advances before we can update the contents of ReadDataW
|
|
|
|
// (or else the W stage will accidentally get the M stage's data when the pipeline does advance).
|
2021-03-11 05:11:31 +00:00
|
|
|
assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) ||
|
2021-04-26 11:43:16 +00:00
|
|
|
((BusState == ATOMICREAD) && (NextBusState != ATOMICREAD));
|
2021-06-23 21:43:22 +00:00
|
|
|
flopenr #(`XLEN) ReadDataNewWReg(clk, reset, CaptureDataM, HRDATAMasked, CapturedHRDATAMasked);
|
2021-04-26 11:43:16 +00:00
|
|
|
|
|
|
|
always @(posedge HCLK, negedge HRESETn)
|
|
|
|
if (~HRESETn)
|
|
|
|
CapturedDataAvailable <= #1 1'b0;
|
|
|
|
else
|
|
|
|
CapturedDataAvailable <= #1 (StallW) ? (CaptureDataM | CapturedDataAvailable) : 1'b0;
|
2021-01-30 04:43:48 +00:00
|
|
|
|
2021-07-17 06:10:57 +00:00
|
|
|
// *** AMO portion will go away when it is moved into the LSU
|
2021-03-11 05:11:31 +00:00
|
|
|
// Handle AMO instructions if applicable
|
2021-07-04 22:52:16 +00:00
|
|
|
generate
|
2021-03-11 05:11:31 +00:00
|
|
|
if (`A_SUPPORTED) begin
|
|
|
|
logic [`XLEN-1:0] AMOResult;
|
2021-07-17 06:15:24 +00:00
|
|
|
logic [`XLEN-1:0] HRDATAW;
|
2021-07-09 20:16:38 +00:00
|
|
|
amoalu amoalu(.srca(HRDATAW), .srcb(DCtoAHBWriteData), .funct(Funct7M), .width(MemSizeM),
|
2021-03-11 05:11:31 +00:00
|
|
|
.result(AMOResult));
|
2021-07-09 20:16:38 +00:00
|
|
|
mux2 #(`XLEN) wdmux(DCtoAHBWriteData, AMOResult, AtomicMaskedM[1], WriteData);
|
2021-03-11 05:11:31 +00:00
|
|
|
end else
|
2021-07-09 20:16:38 +00:00
|
|
|
assign WriteData = DCtoAHBWriteData;
|
2021-03-11 05:11:31 +00:00
|
|
|
endgenerate
|
2021-01-29 06:07:17 +00:00
|
|
|
|
2021-03-11 05:11:31 +00:00
|
|
|
endmodule
|