Add: assembly of risc-v cpu

This commit is contained in:
brice.boisson 2023-10-21 22:57:58 +09:00
parent b3fd2a827d
commit f717284c47
9 changed files with 415 additions and 30 deletions

View File

@ -1,17 +1,18 @@
module alu (input [31:0] input_a, input_b, module alu (input [31:0] input_a, input_b,
input [2:0] op_code, input [3:0] op_code,
output reg [31:0] out); output reg [31:0] out);
always@ (*) begin always@ (*) begin
case (op_code) case (op_code)
3'b000 : out <= input_a + input_b; 4'b0000 : out <= input_a + input_b;
3'b001 : out <= input_a << input_b; 4'b0001 : out <= input_a - input_b;
3'b010 : out <= (input_a < input_b) ? 1 : 0; 4'b0010 : out <= input_a << input_b;
3'b011 : out <= input_a ^ input_b; 4'b0011 : out <= (input_a < input_b) ? 1 : 0;
3'b100 : out <= input_a >> input_b; 4'b0100 : out <= input_a ^ input_b;
3'b101 : out <= input_a >>> input_b; 4'b0101 : out <= input_a >> input_b;
3'b110 : out <= input_a | input_b; 4'b0111 : out <= input_a >>> input_b;
3'b111 : out <= input_a & input_b; 4'b1000 : out <= input_a | input_b;
4'b1001 : out <= input_a & input_b;
default : out <= 32'b0; default : out <= 32'b0;
endcase endcase
end end

View File

@ -1,19 +1,243 @@
module decoder (input [31:0] instruction, module decoder (input [31:0] instruction,
output immediate, output reg [31:0] immediate,
output we_reg, adder_pc, output reg we_reg, adder_pc, data_out,
output [1:0] input_reg, output reg [1:0] input_reg,
output [4:0] select_a, select_b, select_d, output reg [4:0] select_a, select_b, select_d,
output source_alu, output reg source_alu,
output [2:0] op_code_alu, output reg [3:0] op_code_alu,
output mem_we, output reg mem_we,
output [31:0] mem_address output reg [1:0] jmp_pc,
output jmp_pc, b_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 always @(*) begin
if (reset == 1) case (instruction[6:2])
registers[0] <= 32'b0; 5'b01100 : begin // OP - Add, ...
else if (we == 1) immediate = 0;
registers[select_d] <= input_d; 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 end
endmodule endmodule

View File

@ -1,7 +1,7 @@
module instruction (input clock, reset, module memory (input clock, reset,
input we, input we,
input [31:0] address, input [31:0] address,
input [31:0] data_in input [31:0] data_in,
output [31:0] data_out); output [31:0] data_out);
reg [63:0] memory [31:0]; reg [63:0] memory [31:0];

View File

@ -1,6 +1,7 @@
module mux2_1 (input [31:0] A, B, module mux2_1 #(parameter BUS_SIZE = 32)
input S, (input [BUS_SIZE - 1:0] A, B,
output [31:0] O); input S,
output [BUS_SIZE - 1:0] O);
assign O = S ? B : A; assign O = S ? B : A;

View File

@ -1,6 +1,7 @@
module mux4_1 (input [31:0] A, B, C, D, module mux4_1 #(parameter BUS_SIZE = 32)
input [1:0] S, (input [BUS_SIZE - 1:0] A, B, C, D,
output [31:0] O); input [1:0] S,
output [BUS_SIZE - 1:0] O);
assign O = S[0] ? (S[1] ? D : C) assign O = S[0] ? (S[1] ? D : C)
: (S[1] ? B : A); : (S[1] ? B : A);

View File

127
rtl/risc_v_cpu.v Normal file
View File

@ -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

View File

31
tb/tb_risc_v_cpu.v Normal file
View File

@ -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