From 7449625627d308995b6af82633df0d7d96903d8a Mon Sep 17 00:00:00 2001 From: dylanbenzi Date: Sat, 19 Sep 2026 23:34:01 -0400 Subject: [PATCH] initial module setup and declaration --- src/verilog/cpu/control_unit.sv | 155 ++++++++++++++++++++++++++++++++ src/verilog/cpu/cpu_top.sv | 51 ++++++++++- src/verilog/cpu/decode.sv | 59 ++++++++++++ src/verilog/cpu/execute.sv | 55 ++++++++++++ src/verilog/cpu/sign_extend.sv | 18 ++++ src/verilog/sram_wrapper.sv | 64 ++++++------- 6 files changed, 369 insertions(+), 33 deletions(-) create mode 100644 src/verilog/cpu/control_unit.sv create mode 100644 src/verilog/cpu/decode.sv create mode 100644 src/verilog/cpu/execute.sv create mode 100644 src/verilog/cpu/sign_extend.sv diff --git a/src/verilog/cpu/control_unit.sv b/src/verilog/cpu/control_unit.sv new file mode 100644 index 0000000..287b5fe --- /dev/null +++ b/src/verilog/cpu/control_unit.sv @@ -0,0 +1,155 @@ +module main_decoder ( + input logic [6:0] opcode_i, + + output logic branch_o, // branch or not + output logic result_src_o, // + output logic mem_write_o, // write to data memory or not + output logic alu_src_o, // alu use rd2 or ext imm + output logic [1:0] imm_src_o, // + output logic reg_write_o, // write to register or not + output logic [1:0] alu_op_o, // operation for alu to perform + output logic instr_invld_o // invalid or unsupported instruction +); + + always_comb begin + case (opcode_i) + // lw + 7'b0000011: begin + reg_write_o = 1'b1; + imm_src_o = 2'b00; + alu_src_o = 1'b1; + mem_write_o = 1'b0; + result_src_o = 1'b1; + branch_o = 1'b0; + alu_op_o = 2'b00; + end + // sw + 7'b0100011: begin + reg_write_o = 1'b0; + imm_src_o = 2'b01; + alu_src_o = 1'b1; + mem_write_o = 1'b1; + branch_o = 1'b0; + alu_op_o = 2'b00; + end + // R type (add, sub, sll, srl) + 7'b0110011: begin + reg_write_o = 1'b1; + alu_src_o = 1'b0; + mem_write_o = 1'b0; + result_src_o = 1'b0; + branch_o = 1'b0; + alu_op_o = 2'b10; + end + // beq + 7'b0110011: begin + reg_write_o = 1'b0; + imm_src_o = 2'b10; + alu_src_o = 1'b0; + mem_write_o = 1'b0; + branch_o = 1'b1; + alu_op_o = 2'b01; + end + // invalid or unsupported instruction + default: instr_invld_o = 1'b1; + endcase + end + +endmodule + +module alu_decoder ( + input logic [6:0] opcode_i, + input logic [2:0] funct3_i, + input logic funct7_i, + input logic [1:0] alu_op_i, + + output logic [1:0] alu_control_o, + output logic instr_invld_o // invalid or unsupported instruction +); + + always_comb begin + case (alu_op_i) + // lw, sw (alu add) + 2'b00: alu_control_o = 2'b00; + // beq (alu sub) + 2'b01: alu_control_o = 2'b01; + // R type + 2'b10: begin + case (funct3_i) + // add, sub + 3'b000: begin + case ({ + opcode_i[5], funct7_i + }) + // sub + 2'b11: alu_control_o = 2'b01; + // add (00, 01, 10 cases) + default: alu_control_o = 2'b00; + endcase + end + // sll + 3'b001: begin + alu_control = 2'b10; + end + // srl + 3'b101: begin + alu_control = 2'b11; + end + default: instr_invld_o = 1'b1; + endcase + end + default: instr_invld_o = 1'b1; + endcase + end + +endmodule + +module control_unit ( + input logic [31:0] instr_i, + input logic zero_flag_i, + + output logic pc_src_o, + output logic result_src_o, + output logic mem_write_o, + output logic alu_src_o, + output logic [1:0] imm_src_o, + output logic reg_write_o, + output logic [1:0] alu_control_o, + output logic instr_invld_o +); + + logic [6:0] opcode = instr_i[6:0]; + logic [2:0] funct3 = instr_i[14:12]; + logic funct7 = instr_i[30]; + logic [1:0] alu_op; + logic instr_invld_md; + logic instr_invld_ad; + + main_decoder md ( + .opcode_i(opcode), + .branch_o(branch_o), + .result_src_o(result_src_o), + .alu_src_o(alu_src_o), + .imm_src_o(imm_src_o), + .reg_write_o(reg_write_o), + .mem_write_o(mem_write_o), + .alu_op_o(alu_op), + .instr_invld_o(instr_invld_md) + ); + + alu_decoder ad ( + .opcode_i(opcode), + .funct3_i(funct3), + .funct7_i(funct7), + .alu_op_i(alu_op), + .alu_control_o(alu_control_o), + .instr_invld_o(instr_invld_ad) + ); + + always_comb begin + pc_src_o = zero_flag_i & branch_o; + instr_invld_o = instr_invld_md | instr_invld_ad; + end + +endmodule + diff --git a/src/verilog/cpu/cpu_top.sv b/src/verilog/cpu/cpu_top.sv index fd4659e..497f736 100644 --- a/src/verilog/cpu/cpu_top.sv +++ b/src/verilog/cpu/cpu_top.sv @@ -61,6 +61,17 @@ module cpu_top ( .branch_taken_i(branch_taken) ); + logic alu_zero; + logic result_src; + logic mem_write; + logic alu_src; + logic [1:0] alu_control; + logic [31:0] imm_ext; + logic [31:0] rs1_data; + logic [31:0] rs2_data; + logic instr_invld_decode; + logic [31:0] alu_result; + //tied off, do fix assign branch_vld = 1'b0; assign branch_trgt = '0; @@ -80,9 +91,47 @@ module cpu_top ( // Disconnect this once you instantiate reg_file and connect reg_file's output to it instead //assign reg_crossbar_o = '{default: '0}; - assign reg_crossbar_o = registers; + initial begin + for (int i = 0; i < 32; i++) begin + reg_crossbar_o[i] = reg_values_o[i]; + end + end // instantiate the other modules you make here// + decode decode ( + .clk_i(clk_i), + .rst_i(rst_i), + .instr_i(instr), + .instr_vld_i(instr_vld), + .alu_zero_i(alu_zero), + .rd_data_i(result), + .pc_src_o(), + .result_src_o(result_src), + .mem_write_o(dsram_write_en_o), + .alu_src_o(alu_src), + .alu_control_o(alu_control), + .imm_ext_o(imm_ext), + .rs1_data_o(rs1_data), + .rs2_data_o(rs2_data), + .instr_invld_o(instr_invld_decode) + ); + + execute execute ( + .clk_i(clk_i), + .alu_src_i(alu_src), + .imm_ext_i(imm_ext), + .alu_control_i(alu_control), + .current_pc_i(current_pc), + .rs1_data_i(rs1_data), + .rs2_data_i(rs2_data), + .alu_zero_o(alu_zero), + .alu_result_o(alu_result), + .pc_target_o() + ); + + assign dsram_addr_o = alu_result[9:0]; + logic [31:0] result = result_src ? dsram_rdata_i : alu_result; + endmodule diff --git a/src/verilog/cpu/decode.sv b/src/verilog/cpu/decode.sv new file mode 100644 index 0000000..139f3a0 --- /dev/null +++ b/src/verilog/cpu/decode.sv @@ -0,0 +1,59 @@ +module decode ( + input logic clk_i, + input logic rst_i, + input logic [31:0] instr_i, // instruction to decode + input logic instr_vld_i, // is instruction passed valid + input logic alu_zero_i, + input logic [31:0] rd_data_i, + + output logic pc_src_o, + output logic result_src_o, + output logic mem_write_o, + output logic alu_src_o, + output logic [1:0] alu_control_o, + output logic [31:0] imm_ext_o, + output logic [31:0] rs1_data_o, + output logic [31:0] rs2_data_o, + output logic instr_invld_o +); + + logic [1:0] imm_src; + logic reg_write; + logic cu_invld; + logic se_invld; + + assign instr_invld_o = ~instr_vld_i | cu_invld | se_invld; // instruction is invalid if provided invalid or decoded invalid + + control_unit cu ( + .instr_i(instr_i), + .zero_flag_i(alu_zero_i), + .pc_src_o(pc_src_o), + .result_src_o(result_src_o), + .mem_write_o(mem_write_o), + .alu_src_o(alu_src_o), + .imm_src_o(imm_src), + .reg_write_o(reg_write), + .alu_control_o(alu_control_o), + .instr_invld_o(cu_invld) + ); + + reg_file rf ( + .clk_i(clk_i), + .rst_i(rst_i), + .rs1_addr_i(instr_i[19:15]), + .rs2_addr_i(instr_i[24:20]), + .rs1_data_o(rs1_data_o), + .rs2_data_o(rs2_data_o), + .rd_write_en_i(reg_write), + .rd_addr_i(instr_i[11:7]), + .rd_data_i(rd_data_i) + ); + + sign_extend se ( + .instr_i(instr_i), + .imm_src_i(imm_src), + .imm_ext_o(imm_ext_o), + .instr_invld_o(se_invld) + ); + +endmodule diff --git a/src/verilog/cpu/execute.sv b/src/verilog/cpu/execute.sv new file mode 100644 index 0000000..8781a65 --- /dev/null +++ b/src/verilog/cpu/execute.sv @@ -0,0 +1,55 @@ +module alu ( + input logic [31:0] a_i, + input logic [31:0] b_i, + input logic [ 1:0] alu_control_i, + + output logic alu_zero_o, + output logic [31:0] alu_result_o +); + + logic [31:0] result; + + always_comb begin + unique case (alu_control_i) + // add + 2'b00: result = a + b; + // sub + 2'b01: result = a - b; + // sll + 2'b10: result = a << b; + // srl + 2'b11: result = a >> b; + endcase + + assign alu_zero_o = (result == 1'b0); + end +endmodule + +module execute ( + input logic clk_i, + input logic alu_src_i, + input logic [31:0] imm_ext_i, + input logic [1:0] alu_control_i, + input logic [31:0] current_pc_i, + input logic [31:0] rs1_data_i, + input logic [31:0] rs2_data_i, + + output logic alu_zero_o, + output logic [31:0] alu_result_o, + output logic [31:0] pc_target_o +); + + logic [31:0] a = rs1_data; + logic [31:0] b = alu_src_i ? imm_ext_i : rs2_data; + + assign pc_target_o = current_pc_i + imm_ext_i; + + alu alu ( + .a_i(a), + .b_i(b), + .alu_control_i(alu_control_i), + .alu_zero_o(alu_zero_o), + .alu_result_o(alu_result_o) + ); +endmodule + diff --git a/src/verilog/cpu/sign_extend.sv b/src/verilog/cpu/sign_extend.sv new file mode 100644 index 0000000..cf8286b --- /dev/null +++ b/src/verilog/cpu/sign_extend.sv @@ -0,0 +1,18 @@ +module sign_extend ( + input logic [31:0] instr_i, + input logic [ 1:0] imm_src_i, + + output logic [31:0] imm_ext_o, + output logic instr_invld_o +); + + always_comb begin + case (imm_src_i) + 2'b00: imm_ext_o = {{20{instr_i[31]}}, instr_i[31:20]}; + 2'b01: imm_ext_o = {{20{instr_i[31]}}, instr_i[31:25], instr[11:7]}; + 2'b10: imm_ext_o = {{20{instr_i[31]}}, instr_i[7], instr[30:25], instr_i[11:8], 1'b0}; + default: instr_invld_o = 1'b1; + endcase + end + +endmodule diff --git a/src/verilog/sram_wrapper.sv b/src/verilog/sram_wrapper.sv index 07f9a20..0914dc3 100644 --- a/src/verilog/sram_wrapper.sv +++ b/src/verilog/sram_wrapper.sv @@ -4,46 +4,46 @@ //DO NOT MODIFY// module sram_wrapper ( input logic clk_i, - input logic rst_i, + input logic rst_i, input logic en_i, input logic write_en_i, - input logic [9:0] addr_i, + input logic [ 9:0] addr_i, input logic [31:0] wdata_i, output logic [31:0] rdata_o, - output logic rready_o + output logic rready_o ); - CF_SRAM_1024x32_macro u_sram ( - .DO (rdata_o), - .DI (wdata_i), - .AD (addr_i), - .CLKin (clk_i), - .EN (en_i), - .R_WB (~write_en_i), - .BEN (32'hFFFF_FFFF), - .TM (1'b0), - .SM (1'b0), - .WLBI (1'b0), - .WLOFF (1'b0), - .ScanInCC (1'b0), - .ScanInDL (1'b0), - .ScanInDR (1'b0), - .ScanOutCC (), - .vpwrac (1'b1), - .vpwrpc (1'b1) - ); - + CF_SRAM_1024x32_macro u_sram ( + .DO (rdata_o), + .DI (wdata_i), + .AD (addr_i), + .CLKin (clk_i), + .EN (en_i), + .R_WB (~write_en_i), + .BEN (32'hFFFF_FFFF), + .TM (1'b0), + .SM (1'b0), + .WLBI (1'b0), + .WLOFF (1'b0), + .ScanInCC (1'b0), + .ScanInDL (1'b0), + .ScanInDR (1'b0), + .ScanOutCC(), + .vpwrac (1'b1), + .vpwrpc (1'b1) + ); - logic rdata_valid; - always_ff @(posedge clk_i) begin - if(rst_i) begin - rdata_valid <= 1'b0; - end else begin - rdata_valid <= en_i; - end - end + logic rdata_valid; - assign rready_o = rdata_valid; + always_ff @(posedge clk_i) begin + if (rst_i) begin + rdata_valid <= 1'b0; + end else begin + rdata_valid <= en_i; + end + end + + assign rready_o = rdata_valid; endmodule