diff --git a/rtl/alu.v b/rtl/alu.v index 9607a2c..b159d3e 100644 --- a/rtl/alu.v +++ b/rtl/alu.v @@ -1,17 +1,18 @@ module alu (input [31:0] input_a, input_b, - input [2:0] op_code, + input [3:0] op_code, output reg [31:0] out); always@ (*) begin case (op_code) - 3'b000 : out <= input_a + input_b; - 3'b001 : out <= input_a << input_b; - 3'b010 : out <= (input_a < input_b) ? 1 : 0; - 3'b011 : out <= input_a ^ input_b; - 3'b100 : out <= input_a >> input_b; - 3'b101 : out <= input_a >>> input_b; - 3'b110 : out <= input_a | input_b; - 3'b111 : out <= input_a & input_b; + 4'b0000 : out <= input_a + input_b; + 4'b0001 : out <= input_a - input_b; + 4'b0010 : out <= input_a << input_b; + 4'b0011 : out <= (input_a < input_b) ? 1 : 0; + 4'b0100 : out <= input_a ^ input_b; + 4'b0101 : out <= input_a >> input_b; + 4'b0111 : out <= input_a >>> input_b; + 4'b1000 : out <= input_a | input_b; + 4'b1001 : out <= input_a & input_b; default : out <= 32'b0; endcase end diff --git a/rtl/decoder.v b/rtl/decoder.v index ffc8254..9312975 100644 --- a/rtl/decoder.v +++ b/rtl/decoder.v @@ -1,19 +1,243 @@ module decoder (input [31:0] instruction, - output immediate, - output we_reg, adder_pc, - output [1:0] input_reg, - output [4:0] select_a, select_b, select_d, - output source_alu, - output [2:0] op_code_alu, - output mem_we, - output [31:0] mem_address - output jmp_pc, b_pc); + output reg [31:0] immediate, + output reg we_reg, adder_pc, data_out, + output reg [1:0] input_reg, + output reg [4:0] select_a, select_b, select_d, + output reg source_alu, + output reg [3:0] op_code_alu, + output reg mem_we, + output reg [1:0] jmp_pc, + output reg b_pc, alu_not); + +function [3:0] get_op_code_alu(input [2:0] op_code, input arithmetic); + begin + case (op_code) + 3'b000 : get_op_code_alu = arithmetic ? 4'b0000 : 4'b0001; + 3'b001 : get_op_code_alu = 4'b0010; + 3'b010 : get_op_code_alu = 4'b0011; + 3'b011 : get_op_code_alu = 4'b0011; + 3'b100 : get_op_code_alu = 4'b0100; + 3'b101 : get_op_code_alu = arithmetic ? 4'b0101 : 4'b0111; + 3'b110 : get_op_code_alu = 4'b1000; + 3'b111 : get_op_code_alu = 4'b1010; + 3'b111 : get_op_code_alu = 4'b1011; + default : get_op_code_alu= 4'b0000; + endcase + end +endfunction + +function [3:0] get_op_code_alu_imm(input [2:0] op_code, input arithmetic); + begin + case (op_code) + 3'b000 : get_op_code_alu_imm = 4'b0000; + 3'b001 : get_op_code_alu_imm = 4'b0010; + 3'b010 : get_op_code_alu_imm = 4'b0011; + 3'b011 : get_op_code_alu_imm = 4'b0100; + 3'b100 : get_op_code_alu_imm = 4'b0101; + 3'b101 : get_op_code_alu_imm = arithmetic ? 4'b0111 : 4'b1000; + 3'b110 : get_op_code_alu_imm = 4'b1001; + 3'b111 : get_op_code_alu_imm = 4'b1010; + 3'b111 : get_op_code_alu_imm = 4'b1011; + default : get_op_code_alu_imm = 4'b0000; + endcase + end +endfunction + +function [3:0] branch_op_code(input [2:0] op_code); + begin + case (op_code) + 3'b000 : branch_op_code = 4'b0001; + 3'b001 : branch_op_code = 4'b0001; + 3'b010 : branch_op_code = 4'b0011; + 3'b011 : branch_op_code = 4'b0011; + 3'b100 : branch_op_code = 4'b0011; + 3'b101 : branch_op_code = 4'b0011; + default : branch_op_code = 4'b0000; + endcase + end +endfunction + +function branch_not(input [2:0] op_code); + begin + case (op_code) + 3'b000 : branch_not = 1; + 3'b001 : branch_not = 0; + 3'b010 : branch_not = 0; + 3'b011 : branch_not = 1; + 3'b100 : branch_not = 0; + 3'b101 : branch_not = 1; + default : branch_not = 0; + endcase + end +endfunction + + // TODO - Manage ALU OP CODE and IMM Extension + always @(*) begin - if (reset == 1) - registers[0] <= 32'b0; - else if (we == 1) - registers[select_d] <= input_d; + case (instruction[6:2]) + 5'b01100 : begin // OP - Add, ... + immediate = 0; + we_reg = 1; + adder_pc = 0; + data_out = 0; + input_reg = 2'b01; + select_a = instruction[19:15]; + select_b = instruction[24:20]; + select_d = instruction[11:7]; + source_alu = 0; + op_code_alu = get_op_code_alu(instruction[14:12], instruction[30]); + mem_we = 0; + jmp_pc = 2'b00; + b_pc = 0; + alu_not = 0; + alu_not = 0; + end + 5'b00100 : begin // OP-IMM - Addi, ... + immediate = instruction[31:20]; + we_reg = 1; + adder_pc = 0; + data_out = 0; + input_reg = 2'b01; + select_a = instruction[19:15]; + select_b = 5'b00000; + select_d = instruction[11:7]; + source_alu = 1; + op_code_alu = get_op_code_alu_imm(instruction[14:12], instruction[30]); + mem_we = 0; + jmp_pc = 2'b00; + b_pc = 0; + alu_not = 0; + end + 5'b00000 : begin // LOAD - Lw, ... + immediate = instruction[31:20]; + we_reg = 1; + adder_pc = 0; + data_out = 0; + input_reg = 2'b10; + select_a = instruction[19:15]; + select_b = 5'b00000; + select_d = instruction[11:7]; + source_alu = 1; + op_code_alu = 3'b000; + mem_we = 0; + jmp_pc = 2'b00; + b_pc = 0; + alu_not = 0; + end + 5'b01000 : begin // STORE - Sw, ... + immediate = {instruction[31:25], instruction[11:7]}; + we_reg = 0; + adder_pc = 0; + data_out = 0; + input_reg = 2'b01; + select_a = instruction[19:15]; + select_b = instruction[24:20]; + select_d = 5'b00000; + source_alu = 1; + op_code_alu = 3'b000; + mem_we = 1; + jmp_pc = 2'b00; + b_pc = 0; + alu_not = 0; + end + 5'b11000 : begin // BRANCH - Beq, ... + immediate = {instruction[31:25], instruction[11:7]}; + we_reg = 0; + adder_pc = 0; + data_out = 0; + input_reg = 2'b01; + select_a = instruction[19:15]; + select_b = instruction[24:20]; + select_d = 5'b00000; + source_alu = 0; + op_code_alu = branch_op_code(instruction[14:12]); + mem_we = 0; + jmp_pc = 2'b00; + b_pc = 1; + alu_not = branch_not(instruction[14:12]); + end + 5'b11011 : begin // JUMP - Jal + immediate = instruction[31:12]; + we_reg = 1; + adder_pc = 0; + data_out = 0; + input_reg = 2'b00; + select_a = 5'b00000; + select_b = 5'b00000; + select_d = instruction[11:7]; + source_alu = 0; + op_code_alu = 3'b000; + mem_we = 0; + jmp_pc = 2'b01; + b_pc = 0; + alu_not = 0; + end + 5'b11001 : begin // JUMP REG - Jalr + immediate = instruction[31:20]; + we_reg = 1; + adder_pc = 0; + data_out = 0; + input_reg = 2'b00; + select_a = instruction[19:15]; + select_b = 5'b00000; + select_d = instruction[11:7]; + source_alu = 0; + op_code_alu = 3'b000; + mem_we = 0; + jmp_pc = 2'b10; + b_pc = 0; + alu_not = 0; + end + 5'b01101 : begin // LUI - lui + immediate = instruction[31:12] << 12; + we_reg = 1; + adder_pc = 0; + data_out = 1; + input_reg = 2'b01; + select_a = 5'b00000; + select_b = 5'b00000; + select_d = instruction[11:7]; + source_alu = 1; + op_code_alu = 3'b000; + mem_we = 0; + jmp_pc = 2'b00; + b_pc = 0; + alu_not = 0; + end + 5'b00101 : begin // AUIPC - auipc + immediate = instruction[31:12] << 12; + we_reg = 1; + adder_pc = 1; + data_out = 1; + input_reg = 2'b00; + select_a = 5'b00000; + select_b = 5'b00000; + select_d = instruction[11:7]; + source_alu = 0; + op_code_alu = 3'b000; + mem_we = 0; + jmp_pc = 2'b00; + b_pc = 0; + alu_not = 0; + end + default : begin // NOP + immediate = 32'b0; + we_reg = 0; + adder_pc = 0; + data_out = 0; + input_reg = 2'b00; + select_a = 5'b00000; + select_b = 5'b00000; + select_d = 5'b00000; + source_alu = 0; + op_code_alu = 3'b000; + mem_we = 0; + jmp_pc = 2'b00; + b_pc = 0; + alu_not = 0; + end + endcase end endmodule diff --git a/rtl/memory.v b/rtl/memory.v index a19b913..bde7231 100644 --- a/rtl/memory.v +++ b/rtl/memory.v @@ -1,7 +1,7 @@ -module instruction (input clock, reset, +module memory (input clock, reset, input we, input [31:0] address, - input [31:0] data_in + input [31:0] data_in, output [31:0] data_out); reg [63:0] memory [31:0]; diff --git a/rtl/mux2_1.v b/rtl/mux2_1.v index 3711974..267a48e 100644 --- a/rtl/mux2_1.v +++ b/rtl/mux2_1.v @@ -1,6 +1,7 @@ -module mux2_1 (input [31:0] A, B, - input S, - output [31:0] O); +module mux2_1 #(parameter BUS_SIZE = 32) + (input [BUS_SIZE - 1:0] A, B, + input S, + output [BUS_SIZE - 1:0] O); assign O = S ? B : A; diff --git a/rtl/mux4_1.v b/rtl/mux4_1.v index 80c50ab..49de354 100644 --- a/rtl/mux4_1.v +++ b/rtl/mux4_1.v @@ -1,6 +1,7 @@ -module mux4_1 (input [31:0] A, B, C, D, - input [1:0] S, - output [31:0] O); +module mux4_1 #(parameter BUS_SIZE = 32) + (input [BUS_SIZE - 1:0] A, B, C, D, + input [1:0] S, + output [BUS_SIZE - 1:0] O); assign O = S[0] ? (S[1] ? D : C) : (S[1] ? B : A); diff --git a/rtl/risc-v_cpu.v b/rtl/risc-v_cpu.v deleted file mode 100644 index e69de29..0000000 diff --git a/rtl/risc_v_cpu.v b/rtl/risc_v_cpu.v new file mode 100644 index 0000000..a67059f --- /dev/null +++ b/rtl/risc_v_cpu.v @@ -0,0 +1,127 @@ +module risc_v_cpu (input clock, reset, output [31:0] out); + + wire [31:0] in_b; + wire [31:0] alu_out; + + wire [31:0] instruction; + wire we_reg, adder_pc, data_out; + wire [1:0] input_reg; + wire [4:0] select_a, select_b, select_d; + wire source_alu; + wire [3:0] op_code_alu; + wire mem_we; + wire [1:0] jmp_pc; + wire b_pc, alu_not; + + wire [31:0] input_d; + wire [31:0] output_a, output_b; + + wire [31:0] immediate; + + wire [31:0] pc; + wire [31:0] new_pc; + + wire [1:0] pc_in; + + wire [31:0] memory_out; + + wire [31:0] pc_store; + + decoder decoder ( + .instruction(instruction), + .immediate(immediate), + .we_reg(we_reg), + .adder_pc(adder_pc), + .data_out(data_out), + .input_reg(input_reg), + .select_a(select_a), + .select_b(select_b), + .select_d(select_d), + .source_alu(source_alu), + .op_code_alu(op_code_alu), + .mem_we(mem_we), + .jmp_pc(jmp_pc), + .b_pc(b_pc), + .alu_not(alu_not) + ); + + registers_bank registers_bank ( + .clock(clock), + .reset(reset), + .we(we_reg), + .select_d(select_d), + .select_a(select_a), + .select_b(select_b), + .input_d(input_d), + .output_a(output_a), + .output_b(output_b) + ); + + mux2_1 mux2_1_1 ( + .A(output_b), + .B(immediate), + .S(source_alu), + .O(in_b) + ); + + alu alu ( + .input_a(output_a), + .input_b(in_b), + .op_code(op_code_alu), + .out(alu_out) + ); + + mux2_1 #(2) mux2_1_2 ( + .A(jmp_pc), + .B({alu_out[1], (alu_not ? ~alu_out[0] : alu_out[0])}), + .S(b_pc), + .O(pc_in) + ); + + mux4_1 mux4_1_1 ( + .A(pc + 4), + .B(pc + immediate), + .C(alu_out), + .D(0), + .S(pc_in), + .O(new_pc) + ); + + program_counter program_counter ( + .clock(clock), + .reset(clock), + .new_pc(new_pc), + .pc(pc) + ); + + instruction uut_instruction ( + .address(pc), + .instruction(instruction) + ); + + memory memory ( + .clock(clock), + .reset(reset), + .we(mem_we), + .address(alu_out), + .data_in(output_b), + .data_out(memory_out) + ); + + mux2_1 mux2_1_3 ( + .A(4), + .B(alu_out), + .S(adder_pc), + .O(pc_store) + ); + + mux4_1 mux4_1_2 ( + .A(pc_store + pc), + .B(alu_out), + .C(memory_out), + .D(0), + .S(input_reg), + .O(input_d) + ); + +endmodule diff --git a/tb/tb_risc-v_cpu.v b/tb/tb_risc-v_cpu.v deleted file mode 100644 index e69de29..0000000 diff --git a/tb/tb_risc_v_cpu.v b/tb/tb_risc_v_cpu.v new file mode 100644 index 0000000..b5c5139 --- /dev/null +++ b/tb/tb_risc_v_cpu.v @@ -0,0 +1,31 @@ +`timescale 1ns / 1ps + +module tb_risc_v_cpu (); +// Clock and reset signals +reg clk; +reg reset; + +// Design Inputs and outputs +wire [31:0] out; + +// DUT instantiation +risc_v_cpu risc_v_cpu ( + .clock(clk), + .reset(reset), + .out(out) +); + +// generate the clock +initial begin + clk = 1'b0; + forever #1 clk = ~clk; +end + +// Generate the reset +initial begin + reset = 1'b1; + #10 + reset = 1'b0; +end + +endmodule : tb_risc_v_cpu