RISC-V base implementation #1

Merged
BriceBoisson merged 17 commits from risc-v into main 2023-10-24 12:20:46 +00:00
11 changed files with 140 additions and 191 deletions
Showing only changes of commit 72d688018b - Show all commits

View File

@ -1,18 +1,18 @@
module alu (input [31:0] input_a, input_b, module alu (input [31:0] in_a, in_b,
input [3: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)
4'b0000 : out <= input_a + input_b; 4'b0000 : out <= in_a + in_b;
4'b0001 : out <= input_a - input_b; 4'b0001 : out <= in_a - in_b;
4'b0010 : out <= input_a << input_b; 4'b0010 : out <= in_a << in_b;
4'b0011 : out <= (input_a < input_b) ? 1 : 0; 4'b0011 : out <= (in_a < in_b) ? 1 : 0;
4'b0100 : out <= input_a ^ input_b; 4'b0100 : out <= in_a ^ in_b;
4'b0101 : out <= input_a >> input_b; 4'b0101 : out <= in_a >> in_b;
4'b0111 : out <= input_a >>> input_b; 4'b0111 : out <= in_a >>> in_b;
4'b1000 : out <= input_a | input_b; 4'b1000 : out <= in_a | in_b;
4'b1001 : out <= input_a & input_b; 4'b1001 : out <= in_a & in_b;
default : out <= 32'b0; default : out <= 32'b0;
endcase endcase
end end

View File

@ -1,5 +1,5 @@
module instruction (input [31:0] address, module instruction (input [31:0] address,
output [31:0] instruction); output [31:0] instruction);
reg [31:0] memory [63:0]; reg [31:0] memory [63:0];
@ -30,20 +30,3 @@ module instruction (input [31:0] address,
assign instruction = memory[address]; assign instruction = memory[address];
endmodule endmodule
// -- result(1) := "00000000001100110000010000010000";
// -- "000000000000_00000_000_00110_0010000"
// result(0) := "00000000000100000000001100010000";
// -- "000000000001_00000_000_00111_0010000"
// result(1) := "00000000000000000000001110010000";
// -- "000000000000_00110_000_01000_0010000"
// result(2) := "00000000000000110000010000010000";
// -- "0000000_00111_00110_000_00110_0110000"
// result(3) := "00000000011100110000001100110000";
// -- "000000000000_01000_000_00111_0010000"
// result(4) := "00000000000001000000001110010000";
// -- 111111111111_11111_110_00111_1101100
// result(5) := "11111111111111111101001111101100";

View File

@ -1,8 +1,8 @@
module memory (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,8 +1,8 @@
module mux2_1 #(parameter BUS_SIZE = 32) module mux2_1 #(parameter BUS_SIZE = 32)
(input [BUS_SIZE - 1:0] A, B, (input [BUS_SIZE - 1:0] in_1, in_2,
input S, input sel,
output [BUS_SIZE - 1:0] O); output [BUS_SIZE - 1:0] out);
assign O = S ? B : A; assign out = sel ? in_2 : in_1;
endmodule endmodule

View File

@ -1,9 +1,9 @@
module mux4_1 #(parameter BUS_SIZE = 32) module mux4_1 #(parameter BUS_SIZE = 32)
(input [BUS_SIZE - 1:0] A, B, C, D, (input [BUS_SIZE - 1:0] in_1, in_2, in_3, in_4,
input [1:0] S, input [1:0] sel,
output [BUS_SIZE - 1:0] O); output [BUS_SIZE - 1:0] out);
assign O = S[1] ? (S[0] ? D : C) assign out = sel[1] ? (sel[0] ? in_4 : in_3)
: (S[0] ? B : A); : (sel[0] ? in_2 : in_1);
endmodule endmodule

View File

@ -1,6 +1,6 @@
module program_counter (input clock, reset, module program_counter (input clock, reset,
input [31:0] pc_new_addr, input [31:0] pc_new_addr,
output reg [31:0] pc_addr); output reg [31:0] pc_addr);
always @ (posedge clock, posedge reset) begin always @ (posedge clock, posedge reset) begin
if (reset == 1'b1) if (reset == 1'b1)

View File

@ -1,6 +1,6 @@
module registers_bank (input clock, reset, we, module registers_bank (input clock, reset, we,
input [4:0] sel_in, sel_out_a, sel_out_b, input [4:0] sel_in, sel_out_a, sel_out_b,
input [31:0] data_in, input [31:0] data_in,
output [31:0] data_out_a, data_out_b); output [31:0] data_out_a, data_out_b);
reg [31:0] registers[31:0]; reg [31:0] registers[31:0];

View File

@ -1,4 +1,5 @@
module risc_v_cpu (input clock, reset, output [31:0] out); module risc_v_cpu (input clock, reset,
output [31:0] out);
wire [31:0] instruction; wire [31:0] instruction;
@ -48,34 +49,34 @@ module risc_v_cpu (input clock, reset, output [31:0] out);
.data_out_b(reg_data_out_b) .data_out_b(reg_data_out_b)
); );
mux2_1 mux2_1_1 ( mux2_1 mux2_alu_in_b (
.A(reg_data_out_b), .in_1(reg_data_out_b),
.B(imm), .in_2(imm),
.S(alu_src), .sel(alu_src),
.O(alu_in_b) .out(alu_in_b)
); );
alu alu ( alu alu (
.input_a(reg_data_out_a), .in_a(reg_data_out_a),
.input_b(alu_in_b), .in_b(alu_in_b),
.op_code(alu_func), .op_code(alu_func),
.out(alu_out) .out(alu_out)
); );
mux2_1 #(2) mux2_1_2 ( mux2_1 #(2) mux2_pc_sel_branch (
.A(pc_is_branch), .in_1(pc_is_branch),
.B({alu_out[1], (alu_not ? ~alu_out[0] : alu_out[0])}), .in_2({alu_out[1], (alu_not ? ~alu_out[0] : alu_out[0])}),
.S(pc_is_jmp), .sel(pc_is_jmp),
.O(pc_sel_in) .out(pc_sel_in)
); );
mux4_1 mux4_1_1 ( mux4_1 mux4_pc_sel_in (
.A(pc_addr + 4), .in_1(pc_addr + 4),
.B(pc_addr + imm), .in_2(pc_addr + imm),
.C(alu_out), .in_3(alu_out),
.D(0), .in_4(0),
.S(pc_sel_in), .sel(pc_sel_in),
.O(pc_new_addr) .out(pc_new_addr)
); );
program_counter program_counter ( program_counter program_counter (
@ -99,13 +100,13 @@ module risc_v_cpu (input clock, reset, output [31:0] out);
.data_out(mem_out) .data_out(mem_out)
); );
mux4_1 mux4_1_2 ( mux4_1 mux4_reg_sel_data_in (
.A(alu_out), .in_1(alu_out),
.B(mem_out), .in_2(mem_out),
.C(pc_addr + 4), .in_3(pc_addr + 4),
.D(pc_addr + alu_out), .in_4(pc_addr + alu_out),
.S(reg_sel_data_in), .sel(reg_sel_data_in),
.O(reg_data_in) .out(reg_data_in)
); );
endmodule endmodule

View File

@ -1,41 +1,36 @@
`timescale 1ns / 1ps `timescale 1ns / 1ps
module tb_alu (); module tb_alu ();
// Design Inputs and outputs reg [31:0] in_a;
reg [31:0] in_a; reg [31:0] in_b;
reg [31:0] in_b; reg [2:0] op_code;
reg [2:0] op_code; wire [31:0] out;
wire [31:0] out;
// DUT instantiation alu alu (
alu alu ( .in_a(in_a),
.input_a(in_a), .in_b(in_b),
.input_b(in_b), .op_code(op_code),
.op_code(op_code), .out(out)
.out(out) );
);
// Test stimulus initial begin
initial begin $monitor("time=%3d, in_a=%d, in_b=%d, ctrl=%b, q=%d \n",
// Use the monitor task to display the FPGA IO $time, in_a, in_b, op_code, out);
$monitor("time=%3d, in_a=%d, in_b=%d, ctrl=%b, q=%d \n",
$time, in_a, in_b, op_code, out);
// Generate each input with a 20 ns delay between them in_a = 1'b0;
in_a = 1'b0; in_b = 1'b0;
in_b = 1'b0; op_code = 3'b000;
op_code = 3'b000; #20
#20 if (out !== 0) $display("[FAILED] output should be 0");
if (out !== 0) $display("[FAILED] output should be 0"); in_a = 1'b1;
in_a = 1'b1; #20
#20 if (out !== 1) $display("[FAILED] output should be 1");
if (out !== 1) $display("[FAILED] output should be 1"); in_b = 1'b1;
in_b = 1'b1; #20
#20 if (out !== 2) $display("[FAILED] output should be 2");
if (out !== 2) $display("[FAILED] output should be 2"); op_code = 3'b001;
op_code = 3'b001; #20
#20 if (out !== 2) $display("[FAILED] output should be 2");
if (out !== 2) $display("[FAILED] output should be 2"); end
end
endmodule : tb_alu endmodule : tb_alu

View File

@ -1,61 +1,39 @@
`timescale 1ns / 1ps `timescale 1ns / 1ps
module tb_mux2_1 (); module tb_mux2_1 ();
// Clock and reset signals reg ctrl;
reg clk; reg [31:0] in_a;
reg reset; reg [31:0] in_b;
wire [31:0] out;
// Design Inputs and outputs mux2_1 mux (
reg [31:0] in_a; .S(ctrl),
reg [31:0] in_b; .A(in_a),
reg ctrl; .B(in_b),
wire [31:0] out; .O(out)
);
// DUT instantiation initial begin
mux2_1 mux ( $monitor("time=%3d, in_a=%d, in_b=%d, ctrl=%b, q=%d \n",
.S(ctrl), $time, in_a, in_b, ctrl, out);
.A(in_a),
.B(in_b),
.O(out)
);
// generate the clock in_a = 1'b0;
initial begin in_b = 1'b0;
clk = 1'b0; ctrl = 1'b0;
// forever #1 clk = ~clk; #20
end if (out !== 0) $display("[FAILED] output should be 0");
in_a = 1'b1;
// Generate the reset #20
initial begin if (out !== 1) $display("[FAILED] output should be 1");
reset = 1'b1; ctrl = 1'b1;
#10 in_a = 1'b0;
reset = 1'b0; in_b = 1'b1;
end #20
if (out !== 1) $display("[FAILED] output should be 1");
// Test stimulus ctrl = 1'b0;
initial begin in_a = 1'b1;
// Use the monitor task to display the FPGA IO #20
$monitor("time=%3d, in_a=%d, in_b=%d, ctrl=%b, q=%d \n", if (out !== 1) $display("[FAILED] output should be 1");
$time, in_a, in_b, ctrl, out); end
// Generate each input with a 20 ns delay between them
in_a = 1'b0;
in_b = 1'b0;
ctrl = 1'b0;
#20
if (out !== 0) $display("[FAILED] output should be 0");
in_a = 1'b1;
#20
if (out !== 1) $display("[FAILED] output should be 1");
ctrl = 1'b1;
in_a = 1'b0;
in_b = 1'b1;
#20
if (out !== 1) $display("[FAILED] output should be 1");
ctrl = 1'b0;
in_a = 1'b1;
#20
if (out !== 1) $display("[FAILED] output should be 1");
end
endmodule : tb_mux2_1 endmodule : tb_mux2_1

View File

@ -1,36 +1,28 @@
`timescale 1ns / 1ps `timescale 1ns / 1ps
module tb_risc_v_cpu (); module tb_risc_v_cpu ();
integer i; reg clk;
reg reset;
integer i;
wire [31:0] out;
// Clock and reset signals risc_v_cpu risc_v_cpu (
reg clk; .clock(clk),
reg reset; .reset(reset),
.out(out)
);
// Design Inputs and outputs initial begin
wire [31:0] out; reset = 1'b1;
#10
// DUT instantiation reset = 1'b0;
risc_v_cpu risc_v_cpu ( end
.clock(clk),
.reset(reset), initial begin
.out(out) clk = 1'b0;
); for (i = 0; i < 100; i = i + 1) begin
#1 clk = ~clk;
// Generate the reset end
initial begin
reset = 1'b1;
#10
reset = 1'b0;
end
// generate the clock
initial begin
clk = 1'b0;
for (i = 0; i < 100; i = i + 1) begin
#1 clk = ~clk;
end end
end
endmodule : tb_risc_v_cpu endmodule : tb_risc_v_cpu