- Project Title and Overview
- Project Objectives and Design Goals
- Processor Architecture and ISA
- Architecture Block Diagram
- Datapath and Pipeline Explanation
- Module-by-Module Documentation
- Instruction Set and Formats
- Control Unit, ALU, Register File, PC, Immediate Generation, Branch Logic, Memory Interface, Forwarding, and Hazard Handling
- Repository Directory Tree
- Testbench Documentation
- Verification Strategy and Limitations
- XDC Constraints Explanation
- Required Tools and Dependencies
- Compilation, Simulation, Synthesis, and Programming Instructions
- Expected Simulation Outputs and Waveform Inspection
- Design Limitations, Known Issues, and Future Improvements
- Performance Metrics
- Project Status, Contribution, Licensing, and Acknowledgments
- Conclusion
This repository contains a Verilog implementation of a 32-bit RISC-V pipelined processor. Based on the supplied source files, the design implements a five-stage pipeline with separate instruction and data memories, a 32-entry register file, forwarding, load-use stalling, and branch/jump flushing.
The top-level module is Pipeline_top in Pipeline_Top.v. It integrates the fetch, decode, execute, memory, and writeback stages, plus a hazard unit. The design targets a subset of the RV32I base integer instruction set. A directed SystemVerilog testbench, tb_pipeline.sv, exercises the processor and checks register values through hierarchical access.
An XDC constraints file, named ## Pipeline_Top.xdc.txt, targets the Digilent Basys3 board (xc7a35tcpg236-1) and maps clk, rst_n, and Result_Debug[15:0] to board pins. The constraints file comments indicate a Vivado 2020.x+ flow.
Important: The instruction memory uses
$readmemh("memfile.mem", mem);. The filememfile.memis not included in the supplied files. The testbench expectations depend on a specific program image in that file.
From the source code, the design goals appear to be:
- Implement a classic five-stage RISC-V pipeline: Fetch, Decode, Execute, Memory, Writeback.
- Support a practical subset of RV32I integer instructions.
- Resolve data hazards using EX/MEM and MEM/WB forwarding.
- Detect load-use hazards and insert a one-cycle stall.
- Resolve branches and jumps in the Execute stage and flush incorrect-path instructions.
- Provide synthesizable RTL for FPGA prototyping on a Basys3 board.
- Provide a directed simulation testbench for functional verification.
The design does not implement caches, exceptions, interrupts, CSRs, virtual memory, or advanced branch prediction.
| Feature | Implementation |
|---|---|
| ISA | RV32I subset |
| Data width | 32 bits |
| Address width | 32 bits |
| Pipeline depth | 5 stages |
| Register file | 32 × 32-bit, x0 hardwired to zero |
| Instruction memory | 1024 × 32-bit words, word-addressed via A[11:2] |
| Data memory | 1024 × 32-bit words, word-addressed via A[11:2] |
| Reset | Active-low rst_n |
| Pipeline registers | IF/ID, ID/EX, EX/MEM, MEM/WB |
| Hazard handling | Forwarding, load-use stall, branch/jump flush |
| Branch resolution | Execute stage |
| Clock constraint | 10 ns in XDC, i.e. 100 MHz requested constraint |
The control decoder supports these opcodes:
- R-type:
0110011 - I-type ALU:
0010011 - LW:
0000011 - SW:
0100011 - Branch:
1100011 - JAL:
1101111 - JALR:
1100111 - LUI:
0110111 - AUIPC:
0010111
The ALU decoder and execute stage support the corresponding ALU operations for these instructions. The processor does not decode or implement byte/halfword loads/stores, CSR instructions, system instructions, FENCE, ECALL, EBREAK, or privileged modes.
graph LR
%% Styles
classDef reg fill:#f9f,stroke:#333,stroke-width:2px;
classDef mux fill:#ff9,stroke:#333,stroke-width:2px;
classDef alu fill:#9cf,stroke:#333,stroke-width:2px;
classDef mem fill:#fcf,stroke:#333,stroke-width:2px;
classDef ctrl fill:#afa,stroke:#333,stroke-width:2px;
subgraph FetchStage [Fetch Stage]
direction LR
PC[PC]:::reg -->|PCF| InstMem[Instruction Memory]:::mem
PC -->|PCF| PCPlus4[PCPlus4]:::alu
PCPlus4 -->|PCPlus4F| Pipe_FD
InstMem -->|InstrF| Pipe_FD
end
subgraph Pipe_FD [IF/ID Pipeline Register]
direction LR
PCD[PCD]:::reg
PCPlus4D[PCPlus4D]:::reg
InstrD[InstrD]:::reg
end
subgraph DecodeStage [Decode Stage]
direction LR
ControlUnit[Control Unit]:::ctrl
RegFile[Register File]:::mem
Extend[Extend]:::alu
InstrD -->|rs1| RegFile
InstrD -->|rs2| RegFile
InstrD -->|rd| RegFile
InstrD -->|op| ControlUnit
InstrD -->|funct3| ControlUnit
InstrD -->|funct7| ControlUnit
InstrD -->|ImmSrcD| Extend
ControlUnit -->|RegWriteD| Pipe_DE
ControlUnit -->|ResultSrcD| Pipe_DE
ControlUnit -->|MemWriteD| Pipe_DE
ControlUnit -->|JumpD| Pipe_DE
ControlUnit -->|BranchD| Pipe_DE
ControlUnit -->|ALUControlD| Pipe_DE
ControlUnit -->|ALUSrcD| Pipe_DE
RegFile -->|RD1| Pipe_DE
RegFile -->|RD2| Pipe_DE
Extend -->|ExtImmD| Pipe_DE
InstrD -->|Rs1D| HazardUnit
InstrD -->|Rs2D| HazardUnit
end
subgraph Pipe_DE [ID/EX Pipeline Register]
direction LR
RD1E[RD1E]:::reg
RD2E[RD2E]:::reg
PCE[PCE]:::reg
Rs1E[Rs1E]:::reg
Rs2E[Rs2E]:::reg
RdE[RdE]:::reg
ExtImmE[ExtImmE]:::reg
PCPlus4E[PCPlus4E]:::reg
%% Control signals pipelined
RegWriteE[RegWriteE]:::reg
ResultSrcE[ResultSrcE]:::reg
MemWriteE[MemWriteE]:::reg
JumpE[JumpE]:::reg
BranchE[BranchE]:::reg
ALUControlE[ALUControlE]:::reg
ALUSrcE[ALUSrcE]:::reg
end
subgraph ExecuteStage [Execute Stage]
direction LR
Mux_ForwardA{Mux}:::mux
Mux_ForwardB{Mux}:::mux
Mux_ALUSrc{Mux}:::mux
ALU[ALU]:::alu
Mux_PCSrc{Mux}:::mux
Add_PCTarget[Add]:::alu
RD1E --> Mux_ForwardA
RD2E --> Mux_ForwardB
ExtImmE --> Mux_ALUSrc
Mux_ForwardB --> Mux_ALUSrc
Mux_ForwardA -->|SrcA| ALU
Mux_ALUSrc -->|SrcB| ALU
ALUControlE --> ALU
ALU -->|ALUResultE| Pipe_EM
ALU -->|ZeroE| AND_PCSrc
BranchE --> AND_PCSrc
AND_PCSrc[AND] --> Mux_PCSrc
PCE --> Add_PCTarget
PCPlus4E --> Add_PCTarget
Add_PCTarget --> Mux_PCSrc
Mux_PCSrc -->|PCSrcE| PC
Mux_ForwardB -->|WriteDataE| Pipe_EM
RdE --> Pipe_EM
ResultSrcE --> Pipe_EM
RegWriteE --> Pipe_EM
MemWriteE --> Pipe_EM
PCPlus4E --> Pipe_EM
end
subgraph Pipe_EM [EX/MEM Pipeline Register]
direction LR
ALUResultM[ALUResultM]:::reg
WriteDataM[WriteDataM]:::reg
RdM[RdM]:::reg
PCPlus4M[PCPlus4M]:::reg
RegWriteM[RegWriteM]:::reg
ResultSrcM[ResultSrcM]:::reg
MemWriteM[MemWriteM]:::reg
end
subgraph MemoryStage [Memory Stage]
direction LR
DataMem[Data Memory]:::mem
Mux_ResultSrcM{Mux}:::mux
ALUResultM --> DataMem
WriteDataM --> DataMem
MemWriteM --> DataMem
DataMem -->|ReadDataM| Mux_ResultSrcM
ALUResultM --> Mux_ResultSrcM
ResultSrcM --> Mux_ResultSrcM
Mux_ResultSrcM --> Pipe_MW
RdM --> Pipe_MW
RegWriteM --> Pipe_MW
PCPlus4M --> Pipe_MW
RdM --> HazardUnit
ResultSrcM --> HazardUnit
MemWriteM --> HazardUnit
RegWriteM --> HazardUnit
end
subgraph Pipe_MW [MEM/WB Pipeline Register]
direction LR
ALUResultW[ALUResultW]:::reg
ReadDataW[ReadDataW]:::reg
RdW[RdW]:::reg
PCPlus4W[PCPlus4W]:::reg
RegWriteW[RegWriteW]:::reg
ResultSrcW[ResultSrcW]:::reg
end
subgraph WritebackStage [Writeback Stage]
direction LR
Mux_ResultW{Mux}:::mux
ALUResultW --> Mux_ResultW
ReadDataW --> Mux_ResultW
ResultSrcW --> Mux_ResultW
Mux_ResultW -->|ResultW| RegFile
RegWriteW --> RegFile
RdW --> HazardUnit
ResultSrcW --> HazardUnit
RegWriteW --> HazardUnit
end
subgraph HazardUnitBlock [Hazard Unit]
HazardUnit[Hazard Unit]:::ctrl
HazardUnit -->|StallF| PC
HazardUnit -->|StallD| Pipe_FD
HazardUnit -->|FlushD| Pipe_FD
HazardUnit -->|FlushE| Pipe_DE
HazardUnit -->|ForwardAE| Mux_ForwardA
HazardUnit -->|ForwardBE| Mux_ForwardB
HazardUnit -->|PCSrcE| Mux_PCSrc
%% Forwarding paths from MEM and WB back to EX
ALUResultM -->|Forwarding from MEM| Mux_ForwardA
ALUResultM -->|Forwarding from MEM| Mux_ForwardB
ResultW -->|Forwarding from WB| Mux_ForwardA
ResultW -->|Forwarding from WB| Mux_ForwardB
end
%% Connections for Muxes inside Execute stage (simplified for Mermaid)
Mux_ForwardA -.->|1| ALUResultM
Mux_ForwardA -.->|2| ResultW
Mux_ForwardB -.->|1| ALUResultM
Mux_ForwardB -.->|2| ResultW
The processor uses a standard five-stage pipeline.
Implemented in fetch_cycle (Fetch_Cycle.v).
PC_MUXselects betweenPCPlus4FandPCTargetEusingPCSrcE.PC_Moduleupdates the program counter on the rising clock edge.Instruction_Memoryreads the instruction word usingPCF[11:2].PC_AddercomputesPCF + 4.- The IF/ID pipeline registers capture
InstrF_r,PCF_r, andPCPlus4F_r. StallFholds the IF/ID register.FlushDinserts a NOP (32'h0000_0013) intoInstrF_rwhile still updatingPCF_randPCPlus4F_r.
Implemented in decode_cycle (Decode_Cycle.v).
Control_Unit_Topdecodes the instruction and generates control signals.Register_Filereadsrs1andrs2.Sign_Extendgenerates the immediate value according toImmSrcD.- The ID/EX pipeline registers capture control signals, register values, immediate,
PCE, andPCPlus4E. FlushEzeroes the ID/EX control and data registers, inserting a bubble.UsesRs1DandUsesRs2Dare combinational and used by the hazard unit for load-use detection.
Implemented in execute_cycle (Execute_Cycle.v).
- Two
Mux_3_by_1blocks implement forwarding forSrc_AandSrc_B. AUIPCEselectsPCEasSrc_Afor AUIPC.ALUSrcEselects the immediate asSrc_Bfor I-type, LW, SW, JALR, and AUIPC.- The
ALUperforms the operation selected byALUControlE. - The branch comparator computes
brEq,brLt, andbrLtUfrom forwarded operands. PCSrcE = JumpE | (BranchE & branch_taken).PCTargetEis eitherPCE + Imm_Ext_Eor the JALR target(Src_A_fwd + Imm_Ext_E) & 32'hFFFF_FFFE.- The EX/MEM pipeline registers capture
RegWriteE,MemWriteE,ResultSrcE,RD_E,PCPlus4E, store data, ALU result, and immediate.
Implemented in memory_cycle (Memory_Cycle.v).
Data_Memoryperforms word-addressed load/store usingALU_ResultM[11:2].- Store data is
WriteDataM, which is the forwardedrs2value. - The MEM/WB pipeline registers capture
RegWriteM,ResultSrcM,RD_M,PCPlus4M,ALU_ResultM,ReadDataM, andImm_ExtM.
Implemented in writeback_cycle (Writeback_Cycle.v).
Mux_4_by_1selectsResultWaccording toResultSrcW:00:ALU_ResultW01:ReadDataW10:PCPlus4W11:Imm_ExtW
ResultWis written back to the register file throughRegister_File.
| Module | File | Role |
|---|---|---|
Pipeline_top |
Pipeline_Top.v |
Top-level integration of all pipeline stages and hazard unit |
Pipeline_top ports:
| Direction | Signal | Width | Description |
|---|---|---|---|
| Input | clk |
1 | System clock |
| Input | rst_n |
1 | Active-low reset |
| Output | Result_Debug |
16 | Lower 16 bits of ResultW |
| Output | Instr_Debug |
32 | Instruction in Decode stage |
| Output | PC_Debug |
32 | PC in Decode stage |
| Output | RegWrite_Debug |
1 | Writeback register write enable |
Internally it instantiates:
fetch_cycle Fetchdecode_cycle Decodeexecute_cycle Executememory_cycle Memorywriteback_cycle WriteBackhazard_unit Hazard
| Module | File | Role |
|---|---|---|
fetch_cycle |
Fetch_Cycle.v |
IF stage, PC, instruction memory, IF/ID registers |
PC_Module |
PC.v |
Program counter register |
Instruction_Memory |
Instruction_Memory.v |
1024 × 32-bit instruction memory |
PC_Adder |
PC_Adder.v |
PC + 4 adder |
Mux |
Mux.v |
PC source mux |
fetch_cycle ports:
| Direction | Signal | Width | Description |
|---|---|---|---|
| Input | clk |
1 | Clock |
| Input | rst_n |
1 | Active-low reset |
| Input | StallF |
1 | Stall fetch |
| Input | FlushD |
1 | Flush Decode input |
| Input | PCSrcE |
1 | PC select from Execute |
| Input | PCTargetE |
32 | Branch/jump target from Execute |
| Output | InstrD |
32 | Instruction to Decode |
| Output | PCD |
32 | PC to Decode |
| Output | PCPlus4D |
32 | PC+4 to Decode |
| Module | File | Role |
|---|---|---|
decode_cycle |
Decode_Cycle.v |
ID stage, control, register file, immediate generation, ID/EX registers |
Control_Unit_Top |
Control_Unit_Top.v |
Control wrapper |
Main_Decoder |
Main_Decoder.v |
Main control decoder |
ALU_Decoder |
ALU_Decoder.v |
ALU control decoder |
Register_File |
Register_File.v |
32 × 32-bit register file |
Sign_Extend |
Sign_Extend.v |
Immediate generator |
decode_cycle ports:
| Direction | Signal | Width | Description |
|---|---|---|---|
| Input | RegWriteW |
1 | Writeback enable |
| Input | clk |
1 | Clock |
| Input | rst_n |
1 | Active-low reset |
| Input | FlushE |
1 | Flush Execute register |
| Input | InstrD |
32 | Instruction from Fetch |
| Input | PCD |
32 | PC from Fetch |
| Input | PCPlus4D |
32 | PC+4 from Fetch |
| Input | ResultW |
32 | Writeback result |
| Input | RDW |
5 | Writeback destination register |
| Output | UsesRs1D |
1 | Instruction uses rs1 |
| Output | UsesRs2D |
1 | Instruction uses rs2 |
| Output | RegWriteE |
1 | Register write enable to Execute |
| Output | ALUSrcE |
1 | ALU source select to Execute |
| Output | MemWriteE |
1 | Memory write enable to Execute |
| Output | BranchE |
1 | Branch enable to Execute |
| Output | JumpE |
1 | Jump enable to Execute |
| Output | JalrE |
1 | JALR enable to Execute |
| Output | AUIPCE |
1 | AUIPC enable to Execute |
| Output | ResultSrcE |
2 | Result source to Execute |
| Output | ALUControlE |
4 | ALU control to Execute |
| Output | funct3E |
3 | funct3 to Execute |
| Output | RD1_E |
32 | rs1 value to Execute |
| Output | RD2_E |
32 | rs2 value to Execute |
| Output | Imm_Ext_E |
32 | Immediate to Execute |
| Output | RS1_E |
5 | rs1 address to Execute |
| Output | RS2_E |
5 | rs2 address to Execute |
| Output | RD_E |
5 | Destination address to Execute |
| Output | PCE |
32 | PC to Execute |
| Output | PCPlus4E |
32 | PC+4 to Execute |
| Module | File | Role |
|---|---|---|
execute_cycle |
Execute_Cycle.v |
EX stage, forwarding, ALU, branch comparator, EX/MEM registers |
ALU |
ALU.v |
32-bit ALU |
Mux_3_by_1 |
Mux.v |
Forwarding muxes |
Mux |
Mux.v |
AUIPC and ALUSrc muxes |
execute_cycle ports:
| Direction | Signal | Width | Description |
|---|---|---|---|
| Input | clk |
1 | Clock |
| Input | rst_n |
1 | Active-low reset |
| Input | RegWriteE |
1 | Register write enable |
| Input | ALUSrcE |
1 | ALU source select |
| Input | MemWriteE |
1 | Memory write enable |
| Input | BranchE |
1 | Branch enable |
| Input | JumpE |
1 | Jump enable |
| Input | JalrE |
1 | JALR enable |
| Input | AUIPCE |
1 | AUIPC enable |
| Input | ResultSrcE |
2 | Result source |
| Input | ForwardA_E |
2 | Forward select for A |
| Input | ForwardB_E |
2 | Forward select for B |
| Input | ALUControlE |
4 | ALU control |
| Input | funct3E |
3 | Branch funct3 |
| Input | RD_E |
5 | Destination register |
| Input | PCE |
32 | PC |
| Input | PCPlus4E |
32 | PC+4 |
| Input | ResultW |
32 | Writeback result |
| Input | RD1_E |
32 | rs1 value |
| Input | RD2_E |
32 | rs2 value |
| Input | Imm_Ext_E |
32 | Immediate |
| Output | PCSrcE |
1 | PC source select |
| Output | RegWriteM |
1 | Register write enable to MEM |
| Output | MemWriteM |
1 | Memory write enable to MEM |
| Output | ResultSrcM |
2 | Result source to MEM |
| Output | RD_M |
5 | Destination to MEM |
| Output | PCPlus4M |
32 | PC+4 to MEM |
| Output | WriteDataM |
32 | Store data to MEM |
| Output | ALU_ResultM |
32 | ALU result to MEM |
| Output | PCTargetE |
32 | Branch/jump target to Fetch |
| Output | Imm_ExtM |
32 | Immediate to MEM |
| Module | File | Role |
|---|---|---|
memory_cycle |
Memory_Cycle.v |
MEM stage, data memory, MEM/WB registers |
Data_Memory |
Data_Memory.v |
1024 × 32-bit data memory |
memory_cycle ports:
| Direction | Signal | Width | Description |
|---|---|---|---|
| Input | clk |
1 | Clock |
| Input | rst_n |
1 | Active-low reset |
| Input | RegWriteM |
1 | Register write enable |
| Input | MemWriteM |
1 | Memory write enable |
| Input | ResultSrcM |
2 | Result source |
| Input | RD_M |
5 | Destination register |
| Input | PCPlus4M |
32 | PC+4 |
| Input | WriteDataM |
32 | Store data |
| Input | ALU_ResultM |
32 | ALU result / address |
| Input | Imm_ExtM |
32 | Immediate |
| Output | RegWriteW |
1 | Register write enable to WB |
| Output | ResultSrcW |
2 | Result source to WB |
| Output | RD_W |
5 | Destination to WB |
| Output | PCPlus4W |
32 | PC+4 to WB |
| Output | ALU_ResultW |
32 | ALU result to WB |
| Output | ReadDataW |
32 | Load data to WB |
| Output | Imm_ExtW |
32 | Immediate to WB |
| Module | File | Role |
|---|---|---|
writeback_cycle |
Writeback_Cycle.v |
WB stage result mux |
Mux_4_by_1 |
Mux.v |
Result source mux |
writeback_cycle ports:
| Direction | Signal | Width | Description |
|---|---|---|---|
| Input | clk |
1 | Clock, unused in current implementation |
| Input | rst_n |
1 | Active-low reset, unused in current implementation |
| Input | ResultSrcW |
2 | Result source select |
| Input | PCPlus4W |
32 | PC+4 |
| Input | ALU_ResultW |
32 | ALU result |
| Input | ReadDataW |
32 | Load data |
| Input | Imm_ExtW |
32 | Immediate |
| Output | ResultW |
32 | Writeback result |
| Module | File | Role |
|---|---|---|
hazard_unit |
Hazard_unit.v |
Forwarding, load-use stall, flush generation |
hazard_unit ports:
| Direction | Signal | Width | Description |
|---|---|---|---|
| Input | rst_n |
1 | Active-low reset |
| Input | RegWriteM |
1 | MEM stage register write |
| Input | RegWriteW |
1 | WB stage register write |
| Input | RD_M |
5 | MEM destination |
| Input | RD_W |
5 | WB destination |
| Input | Rs1_E |
5 | EX rs1 |
| Input | Rs2_E |
5 | EX rs2 |
| Input | Rs1_D |
5 | Decode rs1 |
| Input | Rs2_D |
5 | Decode rs2 |
| Input | RD_E |
5 | EX destination |
| Input | UsesRs1D |
1 | Decode uses rs1 |
| Input | UsesRs2D |
1 | Decode uses rs2 |
| Input | ResultSrcE_load |
1 | EX instruction is a load |
| Input | PCSrcE |
1 | Branch/jump taken |
| Output | ForwardAE |
2 | Forward select A |
| Output | ForwardBE |
2 | Forward select B |
| Output | StallF |
1 | Stall Fetch |
| Output | StallD |
1 | Stall Decode, generated but not used in Pipeline_top |
| Output | FlushD |
1 | Flush Decode |
| Output | FlushE |
1 | Flush Execute |
Mux.v contains:
Mux: 2:1, 32-bit mux.Mux_3_by_1: 3:1, 32-bit mux.Mux_4_by_1: 4:1, 32-bit mux.
These are used for PC selection, forwarding, AUIPC, ALUSrc, and writeback result selection.
The implementation supports these RV32I instructions:
| Format | Instructions | Notes |
|---|---|---|
| R-type | ADD, SUB, AND, OR, XOR, SLT, SLTU, SLL, SRL, SRA |
Decoded by ALU_Decoder using funct3 and funct7[5] |
| I-type ALU | ADDI, SLTI, SLTIU, XORI, ORI, ANDI, SLLI, SRLI, SRAI |
funct7[5] distinguishes SRLI/SRAI |
| Load | LW |
Only word loads; other load funct3 values are not separately decoded |
| Store | SW |
Only word stores; other store funct3 values are not separately decoded |
| Branch | BEQ, BNE, BLT, BGE, BLTU, BGEU |
Branch comparison in Execute stage |
| Jump | JAL, JALR |
JALR clears bit 0 of target |
| Upper immediate | LUI, AUIPC |
AUIPC uses PC + immediate |
Unsupported instructions include LB, LH, LBU, LHU, SB, SH, CSR instructions, ECALL, EBREAK, FENCE, and all privileged instructions.
Sign_Extend supports:
ImmSrc |
Format | Description |
|---|---|---|
3'b000 |
I-type | {{20{In[31]}}, In[31:20]} |
3'b001 |
S-type | {{20{In[31]}}, In[31:25], In[11:7]} |
3'b010 |
B-type | {{19{In[31]}}, In[31], In[7], In[30:25], In[11:8], 1'b0} |
3'b011 |
J-type | {{11{In[31]}}, In[31], In[19:12], In[20], In[30:21], 1'b0} |
3'b100 |
U-type | {In[31:12], 12'b0} |
Control Unit, ALU, Register File, PC, Immediate Generation, Branch Logic, Memory Interface, Forwarding, and Hazard Handling
Control_Unit_Top instantiates Main_Decoder and ALU_Decoder.
Main_Decoder outputs:
RegWriteALUSrcMemWriteBranchJumpJalrAUIPCUsesRs1UsesRs2ImmSrc[2:0]ResultSrc[1:0]ALUOp[1:0]
Opcode decoding:
| Opcode | Instruction type | Key control settings |
|---|---|---|
0110011 |
R-type | RegWrite=1, UsesRs1=1, UsesRs2=1, ResultSrc=00, ALUOp=10 |
0010011 |
I-type ALU | RegWrite=1, ALUSrc=1, UsesRs1=1, ImmSrc=000, ResultSrc=00, ALUOp=10 |
0000011 |
LW | RegWrite=1, ALUSrc=1, UsesRs1=1, ImmSrc=000, ResultSrc=01, ALUOp=00 |
0100011 |
SW | ALUSrc=1, MemWrite=1, UsesRs1=1, UsesRs2=1, ImmSrc=001, ALUOp=00 |
1100011 |
Branch | Branch=1, UsesRs1=1, UsesRs2=1, ImmSrc=010, ALUOp=01 |
1101111 |
JAL | RegWrite=1, Jump=1, ImmSrc=011, ResultSrc=10 |
1100111 |
JALR | RegWrite=1, ALUSrc=1, Jump=1, Jalr=1, UsesRs1=1, ImmSrc=000, ResultSrc=10 |
0110111 |
LUI | RegWrite=1, ImmSrc=100, ResultSrc=11 |
0010111 |
AUIPC | RegWrite=1, AUIPC=1, ALUSrc=1, ImmSrc=100, ResultSrc=00 |
ALU_Decoder maps ALUOp, funct3, funct7, and op to ALUControl[3:0].
ALU.v implements:
ALUControl |
Operation |
|---|---|
0000 |
ADD |
0001 |
SUB |
0010 |
AND |
0011 |
OR |
0100 |
XOR |
0101 |
SLT signed |
0110 |
SLTU unsigned |
0111 |
SLL |
1000 |
SRL |
1001 |
SRA |
Outputs Result, Zero, and Negative. Zero and Negative are connected in execute_cycle but not used by the branch comparator, which computes its own comparison.
Register_File.v implements a 32 × 32-bit register file.
- Asynchronous reads.
- Synchronous write on
posedge clk. - Write disabled when
A3 == 5'h00. - Reads from
x0return32'h0. - Initialized to zero through an
initialblock. - No reset input.
PC_Module in PC.v:
- Active-low asynchronous reset.
- Resets
PCto32'h0000_0000. - Otherwise updates
PC <= PC_Nextonposedge clk.
PC_Adder computes PC + 4.
Sign_Extend.v generates I, S, B, J, and U immediates as described above.
Branch comparison is in execute_cycle:
br_diff = Src_A_fwd - Src_B_fwdbrEq = (br_diff == 0)brLtfor signed comparison.brLtUfor unsigned comparison.branch_takenselected byfunct3E.
Branch encodings:
funct3E |
Branch | Taken condition |
|---|---|---|
000 |
BEQ | brEq |
001 |
BNE | ~brEq |
100 |
BLT | brLt |
101 |
BGE | ~brLt |
110 |
BLTU | brLtU |
111 |
BGEU | ~brLtU |
PCSrcE = JumpE | (BranchE & branch_taken).
- Instruction memory: 1024 × 32-bit, word-addressed by
A[11:2]. - Data memory: 1024 × 32-bit, word-addressed by
A[11:2]. - Instruction memory initializes all words to NOP (
32'h00000013) and loadsmemfile.mem. - Data memory initializes all words to zero.
- No byte enables; only 32-bit word accesses are supported.
The hazard unit generates ForwardAE and ForwardBE:
| Select | Source |
|---|---|
00 |
Original register value from Decode |
01 |
Writeback result ResultW |
10 |
Memory-stage ALU result ALU_ResultM |
Priority is given to the MEM stage over WB stage.
- Load-use hazard:
lwStall = ResultSrcE_load && (RD_E != 0) && ((UsesRs1D && Rs1_D == RD_E) || (UsesRs2D && Rs2_D == RD_E))StallF = lwStallStallD = lwStall(generated but not used inPipeline_top)FlushE = lwStall | PCSrcE
- Control hazard:
FlushD = PCSrcEFlushE = lwStall | PCSrcE
Branches and jumps are resolved in Execute, causing incorrect-path instructions in Decode and Execute to be flushed.
tb_pipeline.sv
Pipeline_top uut (.clk(clk), .rst_n(rst_n));- Clock toggles every 5 ns, giving a 10 ns period (100 MHz simulation clock).
rst_nis held low for 4 clock cycles, then released.- The testbench waits 400 clock cycles before checking results.
- A watchdog triggers
$fatalafter 5000 cycles.
task chk(input int idx, input [31:0] exp, input string nm);It compares uut.Decode.rf.Register[idx] against exp and prints [PASS] or [FAIL].
| Register | Expected value | Label |
|---|---|---|
| x1 | 32'd5 |
ADDI |
| x2 | 32'd3 |
ADDI |
| x3 | 32'd8 |
ADD |
| x4 | 32'd2 |
SUB |
| x5 | 32'd1 |
AND |
| x6 | 32'd7 |
OR |
| x7 | 32'd6 |
XOR |
| x8 | 32'd8 |
LW |
| x10 | 32'd42 |
BEQ-skip |
| x11 | 32'h00000034 |
JAL link |
| x13 | 32'd1 |
post-JAL |
| x14 | 32'hDEADB000 |
LUI |
| x15 | 32'h00000048 |
AUIPC |
The testbench prints a summary line:
PASS=<n> FAIL=<n>
If fail_cnt == 0, it calls $finish(0); otherwise it calls $fatal(1, "FAIL").
- RTL source files for a five-stage RV32I subset are present.
- A directed SystemVerilog testbench is present.
- An XDC and SDC file for Basys3 is present.
memfile.memis Included.
Not specified in the supplied files. A typical contribution process would include:
- Fork the repository.
- Create a feature branch.
- Add tests for new behavior.
- Ensure existing tests still pass.
- Submit a pull request with a clear description.