Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions Readme2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#Hello World
Binary file added repo/.DS_Store
Binary file not shown.
39 changes: 39 additions & 0 deletions repo/rtl/Reg_File.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module Reg_File #(
input logic [4:0] AD1,
input logic [4:0] AD2,
input logic [4:0] AD3,
input logic WE3,
input logic [31:0] WD3,
input logic clk,

output logic [31:0] RD1,
output logic [31:0] RD2,
output logic [31:0] a0
);

logic [31:0] rf[32]; // 32 registers of 32 bits each

//Ensures that all the registers are 0 at the start of simulation
initial begin
for (int i = 0; i < 32; i++) begin
rf[i] = 32'b0;
end
end


always_ff @(posedge clk) begin
if (WE3) begin
//If write is high, write the data
if (AD3 != 5'b0) begin
rf[AD3] <= WD3; // Register 0 is hardwired to 0, block all writes
end
end
end

assign RD1 = rf[AD1]; // Read data from register AD1

assign RD2 = rf[AD2]; // Read data from register AD2

assign a0 = rf[10]; // Output the value of register x10 (a0), hardwired to adress 10 (register a0)

endmodule
22 changes: 22 additions & 0 deletions repo/rtl/alu.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module alu (
input logic [31:0] a,
input logic [31:0] b,
input logic ALUCtrl, // 1 -> a+b, 0 -> a-b (or compare)
output logic [31:0] result,
output logic not_equal // (a != b)
);
logic [31:0] sum, diff;

assign sum = a + b;
assign diff = a - b;

assign not_equal = (a != b);

always_comb begin
if (ALUAdd)
result = sum;
else
result = diff; // used only for subtraction/comparison
end

endmodule
62 changes: 62 additions & 0 deletions repo/rtl/control_unit.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// control_unit.sv
// - ADDI (I-type)
// - BNE (B-type branch)

module control_unit (
input logic [6:0] opcode, // instr[6:0]
input logic [2:0] funct3, // instr[14:12]
output logic RegWrite, // write to rd?
output logic ALUSrc, // 1: use immediate, 0: use rs2
output logic Branch, // is this a branch?
output logic IsBType, // 1: use B-type immediate, 0: I-type
output logic ALUAdd, // 1: ALU does add, 0: ALU does sub/compare
output logic CompareNotEqual // 1: branch on not equal (BNE)
);

// RISC-V opcode constants
localparam OPCODE_OP_IMM = 7'b0010011; // I-type arithmetic (ADDI)
localparam OPCODE_BRANCH = 7'b1100011; // B-type branches (BNE, BEQ, etc)

always_comb begin
RegWrite = 1'b0;
ALUSrc = 1'b0;
Branch = 1'b0;
IsBType = 1'b0;
ALUAdd = 1'b1; // default to ADD
CompareNotEqual = 1'b0;


unique case (opcode)
// ================================
// I-TYPE: ADDI
// ================================
OPCODE_OP_IMM: begin
// ADDI rd, rs1, imm
RegWrite = 1'b1; // write result to rd
ALUSrc = 1'b1; // second ALU operand is immediate
Branch = 1'b0; // not a branch
IsBType = 1'b0; // use I-type immediate
ALUAdd = 1'b1; // ALU does add
CompareNotEqual = 1'b0; // not used
end

// ================================
// B-TYPE: BNE
// ================================
OPCODE_BRANCH: begin
// We only care about BNE here:
// funct3 = 3'b001 => BNE
Branch = 1'b1; // this is a branch
IsBType = 1'b1; // use B-type immediate format
ALUSrc = 1'b0; // compare rs1 and rs2
RegWrite = 1'b0; // branches don't write rd
ALUAdd = 1'b0; // ALU can be used as subtract/compare
CompareNotEqual = (funct3 == 3'b001); // 1 for BNE
end

default: begin
end
endcase
end

endmodule
31 changes: 31 additions & 0 deletions repo/rtl/imm_gen.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module imm_gen (
input logic [31:0] instr,
input logic is_b_type, // 1 for branch, 0 for I-type
output logic [31:0] imm
);
logic [31:0] imm_i;
logic [31:0] imm_b;
logic [12:0] imm_b_raw;

// I-type immediate (addi)
assign imm_i = {{20{instr[31]}}, instr[31:20]};

// B-type immediate (bne)
// imm[12|10:5|4:1|11|0], with bit 0 = 0
assign imm_b_raw = {
instr[31], // imm[12]
instr[7], // imm[11]
instr[30:25], // imm[10:5]
instr[11:8], // imm[4:1]
1'b0 // imm[0]
};
assign imm_b = {{19{imm_b_raw[12]}}, imm_b_raw};

always_comb begin
if (is_b_type)
imm = imm_b;
else
imm = imm_i;
end

endmodule
13 changes: 13 additions & 0 deletions repo/rtl/pc_reg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module pc_reg (
input logic clk,
input logic rst,
input logic [31:0] pc_next,
output logic [31:0] pc
);
always_ff @(posedge clk or posedge rst) begin
if (rst)
pc <= 32'h0000_0000; // start at address 0
else
pc <= pc_next;
end
endmodule
19 changes: 19 additions & 0 deletions repo/rtl/ram.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Asynchronous 32-bit instruction RAM for RISC-V program memory

module ram #(
parameter ADDR_WIDTH = 8, // number of instruction addresses
DATA_WIDTH = 32 // 32-bit RISC-V instructions
)(
input logic [ADDR_WIDTH-1:0] addr, // word address (PC[...:2])
output logic [DATA_WIDTH-1:0] dout // instruction
);

// RAM array: 2^ADDR_WIDTH entries of 32 bits
logic [DATA_WIDTH-1:0] ram_array [0:(2**ADDR_WIDTH)-1];


// Asynchronous read: output changes as soon as addr changes
always_comb begin
dout = ram_array[addr];
end
endmodule
54 changes: 54 additions & 0 deletions repo/rtl/top_ALU.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// This module "wraps" the Register File, the MUX, and the ALU
// as shown in the brown box in your diagram.
module top_ALU (
// --- Inputs to the Block ---
input logic clk, // Clock for Reg File
input logic [4:0] AD1, // Read Address 1 (rs1)
input logic [4:0] AD2, // Read Address 2 (rs2)
input logic [4:0] AD3, // Write Address (rd)
input logic WE3, // Reg Write Enable
input logic ALUSrc, // MUX select signal
input logic ALUCtrl, // ALU control (Add/Sub)
input logic [31:0] ImmOp, // Immediate data from Sign Extend

// --- Outputs from the Block ---
output logic EQ, // EQ flag to Control Unit
output logic [31:0] a0 // Special output for testing
);

// --- 1. INTERNAL WIRES ---
logic [31:0] w_RD1;
logic [31:0] w_RD2;
logic [31:0] w_ALUOut;
logic [31:0] w_ALUop2;


// --- 2. COMPONENT INSTANCES ---

Reg_File rf_inst (
.clk(clk),
.AD1(AD1),
.AD2(AD2),
.AD3(AD3),
.WE3(WE3),
.WD3(w_ALUOut),
.RD1(w_RD1),
.RD2(w_RD2),
.a0(a0)
);


alu alu_inst (
.a(w_RD1),
.b(w_ALUop2),
.ALUCtrl(ALUCtrl),
.result(w_ALUOut),
.EQ(EQ)
);


// --- 3. MUX LOGIC ---
assign w_ALUop2 = (ALUSrc) ? ImmOp : w_RD2;


endmodule
17 changes: 14 additions & 3 deletions repo/tb/doit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,26 @@ for file in "${files[@]}"; do
name="top"
fi

# Automatically detect latest GoogleTest installation under Homebrew
GTEST_BASE=$(brew --prefix googletest 2>/dev/null)
if [ -z "$GTEST_BASE" ]; then
echo "${RED}Error: GoogleTest not found via Homebrew.${RESET}"
exit 1
fi

# Construct include and lib paths dynamically
GTEST_INCLUDE="$GTEST_BASE/include"
GTEST_LIB="$GTEST_BASE/lib"

# Translate Verilog -> C++ including testbench
verilator -Wall --trace \
-cc ${RTL_FOLDER}/${name}.sv \
--exe ${file} \
-y ${RTL_FOLDER} \
--prefix "Vdut" \
-o Vdut \
-CFLAGS "-isystem /opt/homebrew/Cellar/googletest/1.15.2/include"\
-LDFLAGS "-L/opt/homebrew/Cellar/googletest/1.15.2/lib -lgtest -lgtest_main -lpthread" \
-CFLAGS "-std=c++17 -isystem ${GTEST_INCLUDE}" \
-LDFLAGS "-L${GTEST_LIB} -lgtest -lgtest_main -lpthread"

# Build C++ project with automatically generated Makefile
make -j -C obj_dir/ -f Vdut.mk
Expand All @@ -71,4 +82,4 @@ else
total=$((passes + fails))
echo "${RED}Failure! Only ${passes} test(s) passed out of ${total}."
exit 1
fi
fi