Merged bus into main

This commit is contained in:
David Harris 2021-02-25 00:28:41 -05:00
commit cd4ba8831c
24 changed files with 418 additions and 219 deletions

View File

@ -61,7 +61,7 @@
// Bus Interface width
`define AHBW 64
// Peripheral Addresses
// Peripheral Physiccal Addresses
// Peripheral memory space extends from BASE to BASE+RANGE
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits

View File

@ -45,11 +45,14 @@ view wave
add wave /testbench/clk
add wave /testbench/reset
add wave -divider
add wave /testbench/dut/hart/ebu/IReadF
#add wave /testbench/dut/hart/ebu/IReadF
add wave /testbench/dut/hart/DataStall
add wave /testbench/dut/hart/InstrStall
add wave /testbench/dut/hart/StallF
add wave /testbench/dut/hart/StallD
add wave /testbench/dut/hart/StallE
add wave /testbench/dut/hart/StallM
add wave /testbench/dut/hart/StallW
add wave /testbench/dut/hart/FlushD
add wave /testbench/dut/hart/FlushE
add wave /testbench/dut/hart/FlushM
@ -59,26 +62,27 @@ add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCF
add wave -hex /testbench/dut/hart/ifu/InstrF
add wave /testbench/InstrFName
#add wave -hex /testbench/dut/hart/ifu/PCD
add wave -hex /testbench/dut/hart/ifu/PCD
add wave -hex /testbench/dut/hart/ifu/InstrD
add wave /testbench/InstrDName
add wave -divider
#add wave -hex /testbench/dut/hart/ifu/PCE
#add wave -hex /testbench/dut/hart/ifu/InstrE
add wave -hex /testbench/dut/hart/ifu/PCE
add wave -hex /testbench/dut/hart/ifu/InstrE
add wave /testbench/InstrEName
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
add wave /testbench/dut/hart/ieu/dp/PCSrcE
add wave -divider
#add wave -hex /testbench/dut/hart/ifu/PCM
#add wave -hex /testbench/dut/hart/ifu/InstrM
add wave -hex /testbench/dut/hart/ifu/PCM
add wave -hex /testbench/dut/hart/ifu/InstrM
add wave /testbench/InstrMName
add wave /testbench/dut/uncore/dtim/memwrite
add wave -hex /testbench/dut/uncore/HADDR
add wave -hex /testbench/dut/uncore/HWDATA
add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCW
add wave -hex /testbench/dut/hart/ifu/InstrW
add wave /testbench/InstrWName
add wave /testbench/dut/hart/ieu/dp/RegWriteW
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
@ -101,6 +105,6 @@ configure wave -childrowmargin 2
set DefaultRadix hexadecimal
-- Run the Simulation
#run 1000
run -all
run 2000
#run -all
#quit

View File

@ -30,19 +30,19 @@
module dmem (
input logic clk, reset,
input logic FlushW,
output logic DataStall,
//output logic DataStall,
// Memory Stage
input logic [1:0] MemRWM,
input logic [`XLEN-1:0] MemAdrM,
input logic [2:0] Funct3M,
input logic [`XLEN-1:0] ReadDataM,
//input logic [`XLEN-1:0] ReadDataW,
input logic [`XLEN-1:0] WriteDataM,
output logic [`XLEN-1:0] MemPAdrM,
output logic [1:0] MemRWAlignedM,
output logic MemReadM, MemWriteM,
output logic DataMisalignedM,
// Writeback Stage
input logic MemAckW,
output logic [`XLEN-1:0] ReadDataW,
input logic [`XLEN-1:0] ReadDataW,
// faults
input logic DataAccessFaultM,
output logic LoadMisalignedFaultM, LoadAccessFaultM,
@ -52,9 +52,6 @@ module dmem (
// Initially no MMU
assign MemPAdrM = MemAdrM;
// Pipeline register *** AHB data will eventually come back in W anyway
floprc #(`XLEN) ReadDataWReg(clk, reset, FlushW, ReadDataM, ReadDataW);
// Determine if an Unaligned access is taking place
always_comb
case(Funct3M[1:0])
@ -66,7 +63,9 @@ module dmem (
// Squash unaligned data accesses
// *** this is also the place to squash if the cache is hit
assign MemRWAlignedM = MemRWM & {2{~DataMisalignedM}};
assign MemReadM = MemRWM[1] & ~DataMisalignedM;
assign MemWriteM = MemRWM[0] & ~DataMisalignedM;
// assign MemRWAlignedM = MemRWM & {2{~DataMisalignedM}};
// Determine if address is valid
assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1];
@ -75,7 +74,7 @@ module dmem (
assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0];
// Data stall
assign DataStall = 0;
//assign DataStall = 0;
endmodule

View File

@ -32,21 +32,21 @@
module ahblite (
input logic clk, reset,
input logic StallW, FlushW,
// Load control
input logic UnsignedLoadM,
// Signals from Instruction Cache
input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram
input logic IReadF,
output logic [`XLEN-1:0] IRData,
// output logic IReady,
input logic InstrReadF,
// input logic ResolveBranchD,
output logic [`XLEN-1:0] InstrRData,
// Signals from Data Cache
input logic [`XLEN-1:0] MemPAdrM,
input logic DReadM, DWriteM,
input logic MemReadM, MemWriteM,
input logic [`XLEN-1:0] WriteDataM,
input logic [1:0] DSizeM,
input logic [1:0] MemSizeM,
// Return from bus
output logic [`XLEN-1:0] DRData,
// output logic DReady,
output logic [`XLEN-1:0] ReadDataW,
// AHB-Lite external signals
input logic [`AHBW-1:0] HRDATA,
input logic HREADY, HRESP,
@ -59,48 +59,176 @@ module ahblite (
output logic [3:0] HPROT,
output logic [1:0] HTRANS,
output logic HMASTLOCK,
// Acknowledge
output logic InstrAckD, MemAckW
// Delayed signals for writes
output logic [2:0] HADDRD,
output logic [3:0] HSIZED,
output logic HWRITED,
// Stalls
// output logic InstrStall, DataStall
output logic InstrStall,/*InstrUpdate, */DataStall
);
logic GrantData;
logic [2:0] ISize;
logic [`AHBW-1:0] HRDATAMasked;
logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataPreW;
logic IReady, DReady;
logic CaptureDataM;
// logic [3:0] HSIZED; // size delayed by one cycle for reads
// logic [2:0] HADDRD; // address delayed for subword reads
assign HCLK = clk;
assign HRESETn = ~reset;
// Arbitrate requests by giving data priority over instructions
assign GrantData = DReadM | DWriteM;
// *** initially support HABW = XLEN
// track bus state
// 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.
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADMEMPENDING} statetype;
statetype BusState, NextBusState;
always_ff @(posedge HCLK, negedge HRESETn)
if (~HRESETn) BusState <= #1 IDLE;
else BusState <= #1 NextBusState;
always_comb
case (BusState)
IDLE: if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions
else if (MemWriteM) NextBusState = MEMWRITE;
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 & (MemReadM | MemWriteM)) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
if (~HREADY) NextBusState = INSTRREAD;
else NextBusState = IDLE;
INSTRREADMEMPENDING: if (~HREADY) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
else if (MemReadM) NextBusState = MEMREAD;
else NextBusState = MEMWRITE; // must be write if not a read. Don't return to idle.
endcase
// stall signals
assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || (NextBusState == INSTRREADMEMPENDING);
assign #1 InstrStall = (NextBusState == INSTRREAD);
// assign InstrUpdate = (BusState == INSTRREADMEMPENDING) && (NextBusState != INSTRREADMEMPENDING);
// DH 2/20/22: A cyclic path presently exists
// HREADY->NextBusState->GrantData->HSIZE->HSELUART->HREADY
// This is because the peripherals assert HREADY on the same cycle
// When memory is working, also fix the peripherals to respond on the subsequent cycle
// and this path should be fixed.
// bus outputs
assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE);
assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0];
assign #1 HSIZE = GrantData ? {1'b0, MemSizeM} : ISize;
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
assign HWRITE = (NextBusState == MEMWRITE);
// delay write data by one cycle for
flop #(`XLEN) wdreg(HCLK, WriteDataM, 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);
flop #(1) writereg(HCLK, HWRITE, HWRITED);
// Route signals to Instruction and Data Caches
// *** assumes AHBW = XLEN
// fix harris 2/24/21 to read all WLEN bits directly for instruction
assign InstrRData = HRDATA;
assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
assign CaptureDataM = (BusState == MEMREAD) && (NextBusState != MEMREAD);
flopenr #(`XLEN) ReadDataPreWReg(clk, reset, CaptureDataM, ReadDataM, ReadDataPreW); // *** this may break when there is no instruction read after data read
flopenr #(`XLEN) ReadDataWReg(clk, reset, ~StallW, ReadDataPreW, ReadDataW);
/*
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD} statetype;
statetype AdrState, DataState, NextAdrState; // what is happening in the first and second phases of the bus
always_ff @(posedge HCLK, negedge HRESETn)
if (~HRESETn) begin
AdrState <= IDLE; DataState <= IDLE;
HWDATA <= 0; // unnecessary but avoids x at startup
HSIZED <= 0;
HADDRD <= 0;
HWRITED <= 0;
end else begin
if (HREADY || (DataState == IDLE)) begin // only advance bus state if bus is idle or previous transaction returns ready
DataState <= AdrState;
AdrState <= NextAdrState;
if (HWRITE) HWDATA <= WriteDataM;
HSIZED <= {UnsignedLoadM, HSIZE};
HADDRD <= HADDR[2:0];
HWRITED <= HWRITE;
end
end
always_comb
if (MemReadM) NextAdrState = MEMREAD;
else if (MemWriteM) NextAdrState = MEMWRITE;
else if (InstrReadF) NextAdrState = INSTRREAD;
// else if (1) NextAdrState = INSTRREAD; // dm 2/9/2021 testing
else NextAdrState = IDLE;
// Generate acknowledges based on bus state and ready
assign MemAckW = (AdrState == MEMREAD || AdrState == MEMWRITE) && HREADY;
assign InstrAckD = (AdrState == INSTRREAD) && HREADY;
// State machines for stalls (probably can merge with FSM above***)
// Idle, DataBusy, InstrBusy. Stall while in busystate add suffixes
logic MemState, NextMemState, InstrState, NextInstrState;
flopr #(1) msreg(HCLK, ~HRESETn, NextMemState, MemState);
flopr #(1) isreg(HCLK, ~HRESETn, NextInstrState, InstrState);
/* always_ff @(posedge HCLK, negedge HRESETn)
if (~HRESETn) MemState <= 0;
else MemState <= NextMemState;
assign NextMemState = (MemState == 0 && InstrState == 0 && (MemReadM || MemWriteM)) || (MemState == 1 && ~MemAckW);
assign DataStall = NextMemState;
/* always_ff @(posedge HCLK, negedge HRESETn)
if (~HRESETn) InstrState <= 0;
else InstrState <= NextInstrState;
assign NextInstrState = (InstrState == 0 && MemState == 0 && (~MemReadM && ~MemWriteM && InstrReadF)) ||
(InstrState == 1 && ~InstrAckD) ||
(InstrState == 1 && ResolveBranchD); // dh 2/8/2021 fixing; delete this later
/* assign NextInstrState = (InstrState == 0 && MemState == 0 && (~MemReadM && ~MemWriteM)) ||
(InstrState == 1 && ~InstrAckD); // *** removed InstrReadF above dh 2/9/20
assign InstrStall = NextInstrState | MemState | NextMemState; // *** check this, explain better
// temporarily turn off stalls and check it works
//assign DataStall = 0;
//assign InstrStall = 0;
assign DReady = HREADY & GrantData; // ***unused?
assign IReady = HREADY & InstrReadF & ~GrantData; // maybe unused?***
*/
// Choose ISize based on XLen
generate
if (`AHBW == 32) assign ISize = 3'b010; // 32-bit transfers
else assign ISize = 3'b011; // 64-bit transfers
//if (`AHBW == 32) assign ISize = 3'b010; // 32-bit transfers
//else assign ISize = 3'b011; // 64-bit transfers
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width
endgenerate
/*
// drive bus outputs
assign HADDR = GrantData ? MemPAdrM[31:0] : InstrPAdrF[31:0];
assign HWDATA = WriteDataM;
//assign HWDATA = WriteDataW;
//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 HWRITE = MemWriteM;
assign HSIZE = GrantData ? {1'b0, MemSizeM} : 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 = IReadF | DReadM | DWriteM ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
assign HTRANS = InstrReadF | MemReadM | MemWriteM ? 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 & IReadF & ~GrantData; // maybe unused?***
assign DRData = HRDATAMasked;
assign DReady = HREADY & GrantData; // ***unused?
*/
// stalls
// Stall MEM stage if data is being accessed and bus isn't yet ready

View File

@ -28,9 +28,9 @@
module subwordread (
// from AHB Interface
input logic [`XLEN-1:0] HRDATA,
input logic [31:0] HADDR,
input logic UnsignedLoadM,
input logic [2:0] HSIZE,
input logic [2:0] HADDRD,
//input logic UnsignedLoadM,
input logic [3:0] HSIZED,
// to ifu/dmems
output logic [`XLEN-1:0] HRDATAMasked
);
@ -42,7 +42,7 @@ module subwordread (
if (`XLEN == 64) begin
// ByteMe mux
always_comb
case(HADDR[2:0])
case(HADDRD[2:0])
3'b000: ByteM = HRDATA[7:0];
3'b001: ByteM = HRDATA[15:8];
3'b010: ByteM = HRDATA[23:16];
@ -55,7 +55,7 @@ module subwordread (
// halfword mux
always_comb
case(HADDR[2:1])
case(HADDRD[2:1])
2'b00: HalfwordM = HRDATA[15:0];
2'b01: HalfwordM = HRDATA[31:16];
2'b10: HalfwordM = HRDATA[47:32];
@ -65,14 +65,14 @@ module subwordread (
logic [31:0] WordM;
always_comb
case(HADDR[2])
case(HADDRD[2])
1'b0: WordM = HRDATA[31:0];
1'b1: WordM = HRDATA[63:32];
endcase
// sign extension
always_comb
case({UnsignedLoadM, HSIZE[1:0]})
case({HSIZED[3], HSIZED[1:0]}) // HSIZED[3] indicates unsigned load
3'b000: HRDATAMasked = {{56{ByteM[7]}}, ByteM}; // lb
3'b001: HRDATAMasked = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: HRDATAMasked = {{32{WordM[31]}}, WordM[31:0]}; // lw
@ -85,7 +85,7 @@ module subwordread (
end else begin // 32-bit
// byte mux
always_comb
case(HADDR[1:0])
case(HADDRD[1:0])
2'b00: ByteM = HRDATA[7:0];
2'b01: ByteM = HRDATA[15:8];
2'b10: ByteM = HRDATA[23:16];
@ -94,14 +94,14 @@ module subwordread (
// halfword mux
always_comb
case(HADDR[1])
case(HADDRD[1])
1'b0: HalfwordM = HRDATA[15:0];
1'b1: HalfwordM = HRDATA[31:16];
endcase
// sign extension
always_comb
case({UnsignedLoadM, HSIZE[1:0]})
case({HSIZED[3], HSIZED[1:0]})
3'b000: HRDATAMasked = {{24{ByteM[7]}}, ByteM}; // lb
3'b001: HRDATAMasked = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: HRDATAMasked = HRDATA; // lw

View File

@ -47,6 +47,16 @@ module flopr #(parameter WIDTH = 8) (
else q <= #1 d;
endmodule
// flop with enable
module flopen #(parameter WIDTH = 8) (
input logic clk, en,
input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk)
if (en) q <= #1 d;
endmodule
// flop with enable, asynchronous reset, synchronous clear
module flopenrc #(parameter WIDTH = 8) (
input logic clk, reset, clear, en,

View File

@ -34,12 +34,14 @@ module hazard(
input logic LoadStallD, MulDivStallD,
input logic InstrStall, DataStall,
// Stall outputs
output logic StallF, StallD, FlushD, FlushE, FlushM, FlushW
output logic StallF, StallD, StallE, StallM, StallW,
output logic FlushD, FlushE, FlushM, FlushW
);
logic BranchFlushDE;
logic StallDCause, StallFCause, StallWCause;
logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause;
logic FirstUnstalledD, FirstUnstalledE, FirstUnstalledM, FirstUnstalledW;
// stalls and flushes
// loads: stall for one cycle if the subsequent instruction depends on the load
// branches and jumps: flush the next two instructions if the branch is taken in EXE
@ -54,14 +56,32 @@ module hazard(
assign BranchFlushDE = PCSrcE | RetM | TrapM;
assign StallDCause = LoadStallD | MulDivStallD;
assign StallFCause = InstrStall | CSRWritePendingDEM;
assign StallWCause = DataStall; // *** not yet used
// changed 2/22/21 harris to turn off stallF when RetM or TrapM
// changed 2/23/21 harris to BranchFlushDEM to solve bug in ECALL about JAL being ignored
// assign StallFCause = /*InstrStall | */ CSRWritePendingDEM; // stall at fetch if unable to get the instruction,
// assign StallFCause = /*InstrStall | */ CSRWritePendingDEM & ~(RetM | TrapM); // stall at fetch if unable to get the instruction,
assign StallFCause = /*InstrStall | */ CSRWritePendingDEM & ~(BranchFlushDE); // stall at fetch if unable to get the instruction,
// or if a CSR will be written and may change system behavior
assign StallDCause = LoadStallD | MulDivStallD; // stall in decode if instruction is a load dependent on previous
assign StallECause = 0;
assign StallMCause = 0; // sDataStall; // not yet used***
assign StallWCause = DataStall | InstrStall;
assign StallD = StallDCause;
// Each stage stalls if the next stage is stalled or there is a cause to stall this stage.
assign StallF = StallD | StallFCause;
assign FlushD = BranchFlushDE | StallFCause; // PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM;
assign FlushE = StallD | BranchFlushDE; //LoadStallD | PCSrcE | RetM | TrapM;
assign FlushM = RetM | TrapM;
assign FlushW = TrapM;
assign StallD = StallE | StallDCause;
assign StallE = StallM | StallECause;
assign StallM = StallW | StallMCause;
assign StallW = StallWCause;
assign FirstUnstalledD = (~StallD & StallF);
assign FirstUnstalledE = (~StallE & StallD);
assign FirstUnstalledM = (~StallM & StallE);
assign FirstUnstalledW = (~StallW & StallM);;
// Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush
assign FlushD = FirstUnstalledD || BranchFlushDE; // PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM;
assign FlushE = FirstUnstalledE || BranchFlushDE; //LoadStallD | PCSrcE | RetM | TrapM;
assign FlushM = FirstUnstalledM || RetM || TrapM;
assign FlushW = FirstUnstalledW | TrapM;
endmodule

View File

@ -37,8 +37,8 @@ module controller(
input logic IllegalIEUInstrFaultD,
output logic IllegalBaseInstrFaultD,
// Execute stage control signals
input logic FlushE,
input logic [2:0] FlagsE,
input logic StallE, FlushE,
input logic [2:0] FlagsE,
output logic PCSrcE, // for datapath and Hazard Unit
output logic [4:0] ALUControlE,
output logic ALUSrcAE, ALUSrcBE,
@ -47,14 +47,14 @@ module controller(
output logic [2:0] Funct3E,
output logic MulDivE, W64E,
// Memory stage control signals
input logic FlushM,
input logic StallM, FlushM,
input logic DataMisalignedM,
output logic [1:0] MemRWM,
output logic CSRWriteM, PrivilegedM,
output logic [2:0] Funct3M,
output logic RegWriteM, // for Hazard Unit
// Writeback stage control signals
input logic FlushW,
input logic StallW, FlushW,
output logic RegWriteW, // for datapath and Hazard Unit
output logic [2:0] ResultSrcW,
output logic InstrValidW,
@ -145,7 +145,7 @@ module controller(
endcase
// Execute stage pipeline control register and logic
floprc #(24) controlregE(clk, reset, FlushE,
flopenrc #(24) controlregE(clk, reset, FlushE, ~StallE,
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, TargetSrcD, CSRWriteD, PrivilegedD, Funct3D, W64D, MulDivD, 1'b1},
{RegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, CSRWriteE, PrivilegedE, Funct3E, W64E, MulDivE, InstrValidE});
@ -168,12 +168,12 @@ module controller(
assign MemReadE = MemRWE[1];
// Memory stage pipeline control register
floprc #(12) controlregM(clk, reset, FlushM,
flopenrc #(12) controlregM(clk, reset, FlushM, ~StallM,
{RegWriteE, ResultSrcE, MemRWE, CSRWriteE, PrivilegedE, Funct3E, InstrValidE},
{RegWriteM, ResultSrcM, MemRWM, CSRWriteM, PrivilegedM, Funct3M, InstrValidM});
// Writeback stage pipeline control register
floprc #(5) controlregW(clk, reset, FlushW,
flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW,
{RegWriteM, ResultSrcM, InstrValidM},
{RegWriteW, ResultSrcW, InstrValidW});

View File

@ -32,7 +32,7 @@ module datapath (
input logic [2:0] ImmSrcD,
input logic [31:0] InstrD,
// Execute stage signals
input logic FlushE,
input logic StallE, FlushE,
input logic [1:0] ForwardAE, ForwardBE,
input logic PCSrcE,
input logic [4:0] ALUControlE,
@ -43,13 +43,13 @@ module datapath (
output logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] SrcAE, SrcBE,
// Memory stage signals
input logic FlushM,
input logic StallM, FlushM,
input logic [2:0] Funct3M,
input logic RetM, TrapM,
output logic [`XLEN-1:0] SrcAM,
output logic [`XLEN-1:0] WriteDataM, MemAdrM,
// Writeback stage signals
input logic FlushW,
input logic StallW, FlushW,
input logic RegWriteW,
input logic [2:0] ResultSrcW,
input logic [`XLEN-1:0] PCLinkW,
@ -85,12 +85,12 @@ module datapath (
extend ext(.InstrD(InstrD[31:7]), .*);
// Execute stage pipeline register and logic
floprc #(`XLEN) RD1EReg(clk, reset, FlushE, RD1D, RD1E);
floprc #(`XLEN) RD2EReg(clk, reset, FlushE, RD2D, RD2E);
floprc #(`XLEN) ExtImmEReg(clk, reset, FlushE, ExtImmD, ExtImmE);
floprc #(5) Rs1EReg(clk, reset, FlushE, Rs1D, Rs1E);
floprc #(5) Rs2EReg(clk, reset, FlushE, Rs2D, Rs2E);
floprc #(5) RdEReg(clk, reset, FlushE, RdD, RdE);
flopenrc #(`XLEN) RD1EReg(clk, reset, FlushE, ~StallE, RD1D, RD1E);
flopenrc #(`XLEN) RD2EReg(clk, reset, FlushE, ~StallE, RD2D, RD2E);
flopenrc #(`XLEN) ExtImmEReg(clk, reset, FlushE, ~StallE, ExtImmD, ExtImmE);
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
mux3 #(`XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE);
mux3 #(`XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE);
@ -101,15 +101,15 @@ module datapath (
assign PCTargetE = ExtImmE + TargetBaseE;
// Memory stage pipeline register
floprc #(`XLEN) SrcAMReg(clk, reset, FlushM, SrcAE, SrcAM);
floprc #(`XLEN) ALUResultMReg(clk, reset, FlushM, ALUResultE, ALUResultM);
flopenrc #(`XLEN) SrcAMReg(clk, reset, FlushM, ~StallM, SrcAE, SrcAM);
flopenrc #(`XLEN) ALUResultMReg(clk, reset, FlushM, ~StallM, ALUResultE, ALUResultM);
assign MemAdrM = ALUResultM;
floprc #(`XLEN) WriteDataMReg(clk, reset, FlushM, WriteDataE, WriteDataM);
floprc #(5) RdMEg(clk, reset, FlushM, RdE, RdM);
flopenrc #(`XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, WriteDataE, WriteDataM);
flopenrc #(5) RdMEg(clk, reset, FlushM, ~StallM, RdE, RdM);
// Writeback stage pipeline register and logic
floprc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ALUResultM, ALUResultW);
floprc #(5) RdWEg(clk, reset, FlushW, RdM, RdW);
flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW);
flopenrc #(5) RdWEg(clk, reset, FlushW, ~StallW, RdM, RdW);
mux5 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, MulDivResultW, ResultSrcW, ResultW);
endmodule

View File

@ -30,7 +30,7 @@ module forward(
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
input logic MemReadE, MulDivE,
input logic RegWriteM, RegWriteW,
// Forwaring controls
// Forwarding controls
output logic [1:0] ForwardAE, ForwardBE,
output logic LoadStallD, MulDivStallD
);

View File

@ -49,7 +49,8 @@ module ieu (
input logic [`XLEN-1:0] PCLinkW,
output logic InstrValidW,
// hazards
input logic StallD, FlushD, FlushE, FlushM, FlushW,
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW,
input logic RetM, TrapM,
output logic LoadStallD, MulDivStallD,
output logic PCSrcE,

View File

@ -28,13 +28,16 @@
module ifu (
input logic clk, reset,
input logic StallF, StallD, FlushD, FlushE, FlushM, FlushW,
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW,
// Fetch
input logic [31:0] InstrF,
input logic [`XLEN-1:0] InstrInF,
output logic [`XLEN-1:0] PCF,
output logic [`XLEN-1:0] InstrPAdrF,
output logic InstrReadF,
// Decode
output logic InstrStall,
//output logic InstrStall,
output logic ResolveBranchD,
// Execute
input logic PCSrcE,
input logic [`XLEN-1:0] PCTargetE,
@ -50,7 +53,9 @@ module ifu (
input logic IllegalBaseInstrFaultD,
output logic IllegalIEUInstrFaultD,
output logic InstrMisalignedFaultM,
output logic [`XLEN-1:0] InstrMisalignedAdrM
output logic [`XLEN-1:0] InstrMisalignedAdrM,
// bogus
input logic [15:0] rd2
);
logic [`XLEN-1:0] UnalignedPCNextF, PCNextF;
@ -59,20 +64,25 @@ module ifu (
logic IllegalCompInstrD;
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkE, PCLinkM;
logic CompressedF;
logic [31:0] InstrRawD, InstrE;
logic [31:0] InstrF, InstrRawD, InstrE, InstrW;
logic [31:0] nop = 32'h00000013; // instruction for NOP
// *** put memory interface on here, InstrF becomes output
assign InstrStall = 0; // ***
assign InstrPAdrF = PCF; // *** no MMU
//assign InstrReadF = ~StallD; // *** & ICacheMissF; add later
assign InstrReadF = 1; // *** & ICacheMissF; add later
assign PrivilegedChangePCM = RetM | TrapM;
assign StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
//assign StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
// dh 2/8/2022 keep in instruction fetch stall mode when taking branch
//flopr #(1) rbreg(clk, reset, (PCSrcE | PrivilegedChangePCM), ResolveBranchD);
mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
flopenl #(`XLEN) pcreg(clk, reset, ~StallExceptResolveBranchesF, PCNextF, `RESET_VECTOR, PCF);
// flopenl #(`XLEN) pcreg(clk, reset, ~StallExceptResolveBranchesF, PCNextF, `RESET_VECTOR, PCF);
flopenl #(`XLEN) pcreg(clk, reset, ~StallF, PCNextF, `RESET_VECTOR, PCF);
// pcadder
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
@ -86,6 +96,15 @@ module ifu (
else PCPlus2or4F = {PCF[`XLEN-1:2], 2'b10};
else PCPlus2or4F = {PCPlusUpperF, PCF[1:0]}; // add 4
// harris 2/23/21 Add code to fetch instruction split across two words
generate
if (`XLEN==32) begin
assign InstrF = PCF[1] ? {rd2[15:0], InstrInF[31:16]} : InstrInF;
end else begin
assign InstrF = PCF[2] ? (PCF[1] ? {rd2[15:0], InstrInF[63:48]} : InstrInF[63:32])
: (PCF[1] ? InstrInF[47:16] : InstrInF[31:0]);
end
endgenerate
// Decode stage pipeline register and logic
flopenl #(32) InstrDReg(clk, reset, ~StallD, (FlushD ? nop : InstrF), nop, InstrRawD);
@ -107,25 +126,26 @@ module ifu (
// pipeline misaligned faults to M stage
assign BranchMisalignedFaultE = misaligned & PCSrcE; // E-stage (Branch/Jump) misaligned
flopr #(1) InstrMisalginedReg(clk, reset, BranchMisalignedFaultE, BranchMisalignedFaultM);
flopr #(`XLEN) InstrMisalignedAdrReg(clk, reset, PCNextF, InstrMisalignedAdrM);
flopenr #(1) InstrMisalginedReg(clk, reset, ~StallM, BranchMisalignedFaultE, BranchMisalignedFaultM);
flopenr #(`XLEN) InstrMisalignedAdrReg(clk, reset, ~StallM, PCNextF, InstrMisalignedAdrM);
assign TrapMisalignedFaultM = misaligned & PrivilegedChangePCM;
assign InstrMisalignedFaultM = BranchMisalignedFaultM; // | TrapMisalignedFaultM; *** put this back in without causing a cyclic path
flopr #(32) InstrEReg(clk, reset, FlushE ? nop : InstrD, InstrE);
flopr #(32) InstrMReg(clk, reset, FlushM ? nop : InstrE, InstrM);
flopr #(`XLEN) PCEReg(clk, reset, PCD, PCE);
flopr #(`XLEN) PCMReg(clk, reset, PCE, PCM);
flopr #(`XLEN) PCWReg(clk, reset, PCM, PCW); // *** probably not needed; delete later
flopenr #(32) InstrEReg(clk, reset, ~StallE, FlushE ? nop : InstrD, InstrE);
flopenr #(32) InstrMReg(clk, reset, ~StallM, FlushM ? nop : InstrE, InstrM);
flopenr #(32) InstrWReg(clk, reset, ~StallW, FlushW ? nop : InstrM, InstrW); // just for testbench, delete later
flopenr #(`XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later
// seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL.
// either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or
// have dedicated adder in Mem stage based on PCM + 2 or 4
// *** redo this
flopr #(`XLEN) PCPDReg(clk, reset, PCPlus2or4F, PCLinkD);
flopr #(`XLEN) PCPEReg(clk, reset, PCLinkD, PCLinkE);
flopr #(`XLEN) PCPMReg(clk, reset, PCLinkE, PCLinkM);
flopr #(`XLEN) PCPWReg(clk, reset, PCLinkM, PCLinkW);
flopenr #(`XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD);
flopenr #(`XLEN) PCPEReg(clk, reset, ~StallE, PCLinkD, PCLinkE);
flopenr #(`XLEN) PCPMReg(clk, reset, ~StallM, PCLinkE, PCLinkM);
flopenr #(`XLEN) PCPWReg(clk, reset, ~StallW, PCLinkM, PCLinkW);
endmodule

View File

@ -28,7 +28,7 @@
module csr (
input logic clk, reset,
input logic FlushW,
input logic FlushW, StallW,
input logic [31:0] InstrM,
input logic [`XLEN-1:0] PCM, SrcAM,
input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
@ -102,7 +102,9 @@ module csr (
// merge CSR Reads
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM | CSRNReadValM;
floprc #(`XLEN) CSRValWReg(clk, reset, FlushW, CSRReadValM, CSRReadValW);
// *** add W stall 2/22/21 dh to try fixing memory stalls
// floprc #(`XLEN) CSRValWReg(clk, reset, FlushW, CSRReadValM, CSRReadValW);
flopenrc #(`XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 && PrivilegeModeW != `M_MODE) ||

View File

@ -27,7 +27,7 @@
`include "wally-config.vh"
module csrsr (
input logic clk, reset,
input logic clk, reset, StallW,
input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM,
input logic TrapM, FloatRegWriteW,
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
@ -118,7 +118,7 @@ module csrsr (
STATUS_MIE <= 0; // Per Priv 3.3
STATUS_SIE <= `S_SUPPORTED;
STATUS_UIE <= `U_SUPPORTED;
end else begin
end else if (~StallW) begin
if (WriteMSTATUSM) begin
STATUS_SUM_INT <= CSRWriteValM[18];
STATUS_MPRV_INT <= CSRWriteValM[17];

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////
// exceptions.sv
// privileged.sv
//
// Written: David_Harris@hmc.edu 5 January 2021
// Modified:
@ -45,7 +45,7 @@ module privileged (
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
input logic [4:0] SetFflagsM,
output logic [2:0] FRM_REGW,
input logic FlushD, FlushE, FlushM, StallD
input logic FlushD, FlushE, FlushM, StallD, StallW
);
logic [1:0] NextPrivilegeModeM, PrivilegeModeW;
@ -81,8 +81,8 @@ module privileged (
// PrivilegeMode FSM
always_comb
if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode)
else if (mretM) NextPrivilegeModeM = STATUS_MPP;
/* if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode) // moved reset to flop
else */ if (mretM) NextPrivilegeModeM = STATUS_MPP;
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
else if (uretM) NextPrivilegeModeM = `U_MODE;
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
@ -96,7 +96,7 @@ module privileged (
else NextPrivilegeModeM = `M_MODE;
end else NextPrivilegeModeM = PrivilegeModeW;
flop #(2) privmodereg(clk, NextPrivilegeModeM, PrivilegeModeW);
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, `M_MODE, PrivilegeModeW);
///////////////////////////////////////////
// decode privileged instructions

View File

@ -54,6 +54,11 @@ module clint (
assign #2 entry = {HADDR[15:2], 2'b00};
endgenerate
// DH 2/20/21: Eventually allow MTIME to run off a separate clock
// This will require synchronizing MTIME to the system clock
// before it is read or compared to MTIMECMP.
// It will also require synchronizing the write to MTIMECMP.
// Use req and ack signals synchronized across the clock domains.
// register access
generate

View File

@ -36,6 +36,9 @@ module dtim (
);
logic [`XLEN-1:0] RAM[0:65535];
logic [18:0] HWADDR;
logic [`XLEN-1:0] HREADTim0;
// logic [`XLEN-1:0] write;
logic [15:0] entry;
logic memread, memwrite;
@ -48,74 +51,56 @@ module dtim (
end else begin
if (HREADYTim & HSELTim) begin
busycount <= 0;
HREADYTim <= 0;
HREADYTim <= #1 0;
end else if (~HREADYTim) begin
if (busycount == 0) begin // TIM latency, for testing purposes
HREADYTim <= 1;
end else
if (busycount == 2) begin // TIM latency, for testing purposes
HREADYTim <= #1 1;
end else begin
busycount <= busycount + 1;
end
end
end
/* always_ff @(posedge HCLK, negedge HRESETn)
if (~HRESETn) begin
HREADYTim <= 0;
end else begin
HREADYTim <= HSELTim; // always respond one cycle later
end */
assign memread = MemRWtim[1];
assign memwrite = MemRWtim[0];
// always_ff @(posedge HCLK)
// memwrite <= MemRWtim[0]; // delay memwrite to write phase
assign HRESPTim = 0; // OK
// assign HREADYTim = 1; // Respond immediately; *** extend this
// Model memory read and write
// word aligned reads
generate
if (`XLEN==64)
assign #2 entry = HADDR[18:3];
else
assign #2 entry = HADDR[17:2];
endgenerate
assign HREADTim = RAM[entry];
// assign HREADTim = HREADYTim ? RAM[entry] : ~RAM[entry]; // *** temproary mess up read value before ready
// write each byte based on the byte mask
// UInstantiate a byte-writable memory here if possible
// and drop tihs masking logic. Otherwise, use the masking
// from dmem
/*generate
if (`XLEN==64) begin
always_comb begin
write=HREADTim;
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
if (ByteMaskM[4]) write[39:32] = HWDATA[39:32];
if (ByteMaskM[5]) write[47:40] = HWDATA[47:40];
if (ByteMaskM[6]) write[55:48] = HWDATA[55:48];
if (ByteMaskM[7]) write[63:56] = HWDATA[63:56];
end
always_ff @(posedge clk)
if (memwrite) RAM[HADDR[18:3]] <= write;
end else begin // 32-bit
always_comb begin
write=HREADTim;
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
end
always_ff @(posedge clk)
if (memwrite) RAM[HADDR[17:2]] <= write;
if (`XLEN == 64) begin
// always_ff @(negedge HCLK)
// if (memwrite) RAM[HWADDR[17:3]] <= HWDATA;
always_ff @(posedge HCLK) begin
//if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
HWADDR <= HADDR;
HREADTim0 <= RAM[HADDR[17:3]];
if (memwrite && HREADYTim) RAM[HWADDR[17:3]] <= HWDATA;
end
end else begin
// always_ff @(negedge HCLK)
// if (memwrite) RAM[HWADDR[17:2]] <= HWDATA;
always_ff @(posedge HCLK) begin
//if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
HWADDR <= HADDR;
HREADTim0 <= RAM[HADDR[17:2]];
if (memwrite && HREADYTim) RAM[HWADDR[17:2]] <= HWDATA;
end
end
endgenerate */
generate
if (`XLEN == 64)
always_ff @(posedge HCLK) begin
if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
// HREADTim <= RAM[HADDR[17:3]];
end
else
always_ff @(posedge HCLK) begin
if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
// HREADTim <= RAM[HADDR[17:2]];
end
endgenerate
assign HREADTim = HREADYTim ? HREADTim0 : 'bz;
endmodule

View File

@ -28,6 +28,7 @@
module imem (
input logic [`XLEN-1:1] AdrF,
output logic [31:0] InstrF,
output logic [15:0] rd2, // bogus, delete when real multicycle fetch works
output logic InstrAccessFaultF);
/* verilator lint_off UNDRIVEN */
@ -35,7 +36,7 @@ module imem (
/* verilator lint_on UNDRIVEN */
logic [15:0] adrbits;
logic [`XLEN-1:0] rd;
logic [15:0] rd2;
// logic [15:0] rd2;
generate
if (`XLEN==32) assign adrbits = AdrF[17:2];

View File

@ -27,37 +27,35 @@
module subwordwrite (
input logic [`XLEN-1:0] HRDATA,
input logic [31:0] HADDR,
input logic [2:0] HSIZE,
input logic [2:0] HADDRD,
input logic [3:0] HSIZED,
input logic [`XLEN-1:0] HWDATAIN,
output logic [`XLEN-1:0] HWDATA
);
logic [7:0] ByteM; // *** declare locally to generate as either 4 or 8 bits
logic [15:0] HalfwordM;
logic [`XLEN-1:0] WriteDataSubwordDuplicated;
logic [7:0] ByteMaskM;
generate
if (`XLEN == 64) begin
logic [7:0] ByteMaskM;
// Compute write mask
always_comb
case(HSIZE[1:0])
2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDR[2:0]] = 1; end // sb
2'b01: case (HADDR[2:1])
case(HSIZED[1:0])
2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDRD[2:0]] = 1; end // sb
2'b01: case (HADDRD[2:1])
2'b00: ByteMaskM = 8'b00000011;
2'b01: ByteMaskM = 8'b00001100;
2'b10: ByteMaskM = 8'b00110000;
2'b11: ByteMaskM = 8'b11000000;
endcase
2'b10: if (HADDR[2]) ByteMaskM = 8'b11110000;
2'b10: if (HADDRD[2]) ByteMaskM = 8'b11110000;
else ByteMaskM = 8'b00001111;
2'b11: ByteMaskM = 8'b11111111;
endcase
// Handle subword writes
always_comb
case(HSIZE[1:0])
case(HSIZED[1:0])
2'b00: WriteDataSubwordDuplicated = {8{HWDATAIN[7:0]}}; // sb
2'b01: WriteDataSubwordDuplicated = {4{HWDATAIN[15:0]}}; // sh
2'b10: WriteDataSubwordDuplicated = {2{HWDATAIN[31:0]}}; // sw
@ -77,19 +75,20 @@ module subwordwrite (
end
end else begin // 32-bit
logic [3:0] ByteMaskM;
// Compute write mask
always_comb
case(HSIZE[1:0])
2'b00: begin ByteMaskM = 8'b0000; ByteMaskM[{1'b0, HADDR[1:0]}] = 1; end // sb
2'b01: if (HADDR[1]) ByteMaskM = 8'b1100;
else ByteMaskM = 8'b0011;
2'b10: ByteMaskM = 8'b1111;
default: ByteMaskM = 8'b111; // shouldn't happen
case(HSIZED[1:0])
2'b00: begin ByteMaskM = 4'b0000; ByteMaskM[HADDRD[1:0]] = 1; end // sb
2'b01: if (HADDRD[1]) ByteMaskM = 4'b1100;
else ByteMaskM = 4'b0011;
2'b10: ByteMaskM = 4'b1111;
default: ByteMaskM = 4'b111; // shouldn't happen
endcase
// Handle subword writes
always_comb
case(HSIZE[1:0])
case(HSIZED[1:0])
2'b00: WriteDataSubwordDuplicated = {4{HWDATAIN[7:0]}}; // sb
2'b01: WriteDataSubwordDuplicated = {2{HWDATAIN[15:0]}}; // sh
2'b10: WriteDataSubwordDuplicated = HWDATAIN; // sw

View File

@ -6,6 +6,7 @@
//
// Purpose: Universial Asynchronous Receiver/ Transmitter with FIFOs
// Emulates interface of Texas Instruments PC16550D
// https://media.digikey.com/pdf/Data%20Sheets/Texas%20Instruments%20PDFs/PC16550D.pdf
// Compatible with UART in Imperas Virtio model ***
//
// Compatible with most of PC16550D with the following known exceptions:

View File

@ -43,6 +43,10 @@ module uncore (
input logic HREADYEXT, HRESPEXT,
output logic [`AHBW-1:0] HRDATA,
output logic HREADY, HRESP,
// delayed signals
input logic [2:0] HADDRD,
input logic [3:0] HSIZED,
input logic HWRITED,
// bus interface
output logic DataAccessFaultM,
// peripheral pins
@ -71,7 +75,7 @@ module uncore (
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
// Enable read or write based on decoded address
assign MemRW = {~HWRITE, HWRITE};
assign MemRW = {~HWRITE, HWRITED};
assign MemRWtim = MemRW & {2{HSELTim}};
assign MemRWclint = MemRW & {2{HSELCLINT}};
assign MemRWgpio = MemRW & {2{HSELGPIO}};

View File

@ -29,12 +29,13 @@
module wallypipelinedhart (
input logic clk, reset,
output logic [`XLEN-1:0] PCF,
input logic [31:0] InstrF,
// input logic [31:0] InstrF,
// Privileged
input logic TimerIntM, ExtIntM, SwIntM,
input logic InstrAccessFaultF,
input logic DataAccessFaultM,
// Bus Interface
input logic [15:0] rd2, // bogus, delete when real multicycle fetch works
input logic [`AHBW-1:0] HRDATA,
input logic HREADY, HRESP,
output logic HCLK, HRESETn,
@ -45,11 +46,16 @@ module wallypipelinedhart (
output logic [2:0] HBURST,
output logic [3:0] HPROT,
output logic [1:0] HTRANS,
output logic HMASTLOCK
output logic HMASTLOCK,
// Delayed signals for subword write
output logic [2:0] HADDRD,
output logic [3:0] HSIZED,
output logic HWRITED
);
logic [1:0] ForwardAE, ForwardBE;
logic StallF, StallD, FlushD, FlushE, FlushM, FlushW;
// logic [1:0] ForwardAE, ForwardBE;
logic StallF, StallD, StallE, StallM, StallW;
logic FlushD, FlushE, FlushM, FlushW;
logic RetM, TrapM;
// new signals that must connect through DP
@ -73,6 +79,7 @@ module wallypipelinedhart (
logic StoreMisalignedFaultM, StoreAccessFaultM;
logic [`XLEN-1:0] InstrMisalignedAdrM;
logic [`XLEN-1:0] zero = 0;
logic ResolveBranchD;
logic PCSrcE;
logic CSRWritePendingDEM;
@ -82,26 +89,35 @@ module wallypipelinedhart (
logic FloatRegWriteW;
// bus interface to dmem
logic [1:0] MemRWAlignedM;
logic [2:0] Funct3M;
logic MemReadM, MemWriteM;
logic [2:0] Funct3M;
logic [`XLEN-1:0] MemAdrM, MemPAdrM, WriteDataM;
logic [`XLEN-1:0] ReadDataM, ReadDataW;
logic [`XLEN-1:0] ReadDataW;
logic [`XLEN-1:0] InstrPAdrF;
logic [`XLEN-1:0] InstrRData;
logic InstrReadF;
logic DataStall, InstrStall;
logic InstrAckD, MemAckW;
ifu ifu(.*); // instruction fetch unit: PC, branch prediction, instruction cache
ifu ifu(.InstrInF(InstrRData), .*); // instruction fetch unit: PC, branch prediction, instruction cache
ieu ieu(.*); // inteber execution unit: integer register file, datapath and controller
dmem dmem(/*.Funct3M(InstrM[14:12]),*/ .*); // data cache unit
dmem dmem(.*); // data cache unit
ahblite ebu( // *** make IRData InstrF
.IReadF(1'b1), .IRData(), //.IReady(),
.DReadM(MemRWAlignedM[1]), .DWriteM(MemRWAlignedM[0]),
.DSizeM(Funct3M[1:0]), .DRData(ReadDataM), //.DReady(),
.UnsignedLoadM(Funct3M[2]),
ahblite ebu(
//.InstrReadF(1'b0),
//.InstrRData(InstrF), // hook up InstrF later
.MemSizeM(Funct3M[1:0]), .UnsignedLoadM(Funct3M[2]),
.*);
//assign InstrF = ReadDataM[31:0];
// changing from this to the line above breaks the program. auipc at 104 fails; seems to be flushed.
// Would need to insertinstruction as InstrD, not InstrF
/*ahblite ebu(
.InstrReadF(1'b0),
.InstrRData(), // hook up InstrF later
.MemSizeM(Funct3M[1:0]), .UnsignedLoadM(Funct3M[2]),
.*); */
muldiv mdu(.*); // multiply and divide unit

View File

@ -64,6 +64,10 @@ module wallypipelinedsoc (
logic InstrAccessFaultF, DataAccessFaultM;
logic TimerIntM, SwIntM; // from CLINT
logic ExtIntM = 0; // not yet connected
logic [2:0] HADDRD;
logic [3:0] HSIZED;
logic HWRITED;
logic [15:0] rd2; // bogus, delete when real multicycle fetch works
// instantiate processor and memories
wallypipelinedhart hart(.*);

View File

@ -35,7 +35,7 @@ module testbench();
logic [`XLEN-1:0] signature[0:10000];
logic [`XLEN-1:0] testadr;
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
//logic [31:0] InstrW;
logic [`XLEN-1:0] meminit;
string tests64m[] = '{
"rv64m/I-MUL-01", "3000",
@ -90,7 +90,6 @@ string tests64iNOc[] = {
"rv64i/I-MISALIGN_JMP-01","2000"
};
string tests64i[] = '{
"rv64i/I-LW-01", "4110",
"rv64i/I-ADD-01", "3000",
"rv64i/I-ADDI-01", "3000",
"rv64i/I-ADDIW-01", "3000",
@ -198,7 +197,6 @@ string tests64iNOc[] = {
// "rv32m/I-REMU-01", "2000"
};
string tests32ic[] = '{
// "rv32ic/WALLY-C-ADHOC-01", "2000",
"rv32ic/I-C-ADD-01", "2000",
"rv32ic/I-C-ADDI-01", "2000",
"rv32ic/I-C-AND-01", "2000",
@ -347,9 +345,9 @@ string tests32i[] = {
// Track names of instructions
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
dut.hart.ifu.InstrM, InstrW,
InstrDName, InstrEName, InstrMName, InstrWName);
dut.hart.ifu.InstrF, dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
dut.hart.ifu.InstrM, dut.hart.ifu.InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// initialize tests
initial
@ -452,14 +450,16 @@ endmodule
module instrTrackerTB(
input logic clk, reset, FlushE,
input logic [31:0] InstrD,
input logic [31:0] InstrF, InstrD,
input logic [31:0] InstrE, InstrM,
output logic [31:0] InstrW,
output string InstrDName, InstrEName, InstrMName, InstrWName);
input logic [31:0] InstrW,
// output logic [31:0] InstrW,
output string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// stage Instr to Writeback for visualization
flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
// flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
instrNameDecTB fdec(InstrF, InstrFName);
instrNameDecTB ddec(InstrD, InstrDName);
instrNameDecTB edec(InstrE, InstrEName);
instrNameDecTB mdec(InstrM, InstrMName);