Add: assembly of risc-v cpu
This commit is contained in:
parent
b3fd2a827d
commit
f717284c47
19
rtl/alu.v
19
rtl/alu.v
|
@ -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
|
||||||
|
|
250
rtl/decoder.v
250
rtl/decoder.v
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module mux2_1 (input [31:0] A, B,
|
module mux2_1 #(parameter BUS_SIZE = 32)
|
||||||
|
(input [BUS_SIZE - 1:0] A, B,
|
||||||
input S,
|
input S,
|
||||||
output [31:0] O);
|
output [BUS_SIZE - 1:0] O);
|
||||||
|
|
||||||
assign O = S ? B : A;
|
assign O = S ? B : A;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module mux4_1 (input [31:0] A, B, C, D,
|
module mux4_1 #(parameter BUS_SIZE = 32)
|
||||||
|
(input [BUS_SIZE - 1:0] A, B, C, D,
|
||||||
input [1:0] S,
|
input [1:0] S,
|
||||||
output [31:0] O);
|
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);
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue