This commit is contained in:
hladu357 2024-03-10 15:52:06 +01:00
commit d478a3f7cc
5 changed files with 42752 additions and 0 deletions

657
CPU.v Normal file
View File

@ -0,0 +1,657 @@
`default_nettype none
module processor( input clk, reset, //
output [31:0] PC, //
input [31:0] instruction, //
output WE, //
output [31:0] address_to_mem, //
output [31:0] data_to_mem, //
input [31:0] data_from_mem
);
wire [31:0] pc_adress;
assign PC = pc_adress;
wire [31:0] pc_adress_next;
assign WE = data_mem_write_enabled;
wire reg_we;
wire [4:0] reg_address_read1;
wire [4:0] reg_address_read2;
wire [4:0] reg_address_write;
wire [31:0] reg_data_in;
wire [31:0] reg_data_out1;
wire [31:0] reg_data_out2;
wire mem_to_reg;
wire alu_src_select; // select ? rd2 : imm
wire [3:0] alu_code;
wire [31:0] alu_src_a;
wire [31:0] alu_src_b;
wire [31:0] alu_result;
wire alu_zero_flag;
wire data_mem_write_enabled;
wire [31:0] data_mem_address;
wire [31:0] data_mem_read_data;
wire [31:0] data_mem_write_data;
assign WE = data_mem_write_enabled;
assign address_to_mem = data_mem_address;
assign data_to_mem = data_mem_write_data;
assign data_mem_read_data = data_from_mem;
wire [31:0] imm_decoded;
wire [2:0] imm_control;
wire [31:0] next_address_nojump;
wire [31:0] next_address_jump;
wire branch_beq;
wire branch_jal;
wire branch_jalr;
wire pc_jump;
wire auipc;
control_unit_module control_unit( instruction, branch_beq, branch_jal, branch_jalr, reg_we, mem_to_reg, data_mem_write_enabled, alu_src_select, auipc, imm_control, alu_code);
mux2_1 pc_mux(next_address_nojump, next_address_jump, pc_jump, pc_adress_next);
pc_adder_module pc_adder(pc_adress, next_address_nojump);
register pc(pc_adress_next, clk, reset, pc_adress);
assign pc_jump = (alu_zero_flag && branch_beq) || branch_jal || branch_jalr; // <---
wire [31:0]jump_adder_output;
adder_module32 jump_adder(imm_decoded, pc_adress, jump_adder_output);
mux2_1 jump_adder_jalr(jump_adder_output, alu_result, branch_jalr, next_address_jump);
// program_counter pc(clk, pc_adress);
// inst_mem instruction_memory(pc_adress[7:0], instruction);
// data_mem data_memory(clk, data_mem_write_enabled, data_mem_address, data_mem_write_data, data_mem_read_data);
assign reg_address_read1 = instruction[19:15];
assign reg_address_read2 = instruction[24:20];
assign reg_address_write = instruction[11:7];
assign data_mem_address = alu_result;
assign data_mem_write_data = reg_data_out2;
register_unit_32x32 registers(clk, reg_we, reg_data_in, reg_address_read1, reg_address_read2, reg_address_write, reg_data_out1, reg_data_out2);
immDecode decored(instruction[31:7], imm_control, imm_decoded);
mux2_1 auipc_mux(reg_data_out1, pc_adress, auipc, alu_src_a);
mux2_1 alu_srcrc_mux(reg_data_out2, imm_decoded, alu_src_select, alu_src_b);
aluModule alu(alu_code, alu_src_a, alu_src_b, alu_result, alu_zero_flag);
wire [31:0] mux_connection;
mux2_1 jump_alu_mux(alu_result, next_address_nojump, branch_jal || branch_jalr, mux_connection);
mux2_1 register_write_data_mux(mux_connection, data_mem_read_data, mem_to_reg, reg_data_in);
endmodule
module aluModule( input [3:0] code, input [31:0] srcA, srcB, output reg [31:0] result, output zeroFlag );
always @(*)
case (code)
'b 0100: begin // add
result <= srcA + srcB;
end
'b 1100: begin // sub
result <= srcA - srcB;
end
'b 0001: begin // div
result <= srcA / srcB;
end
'b 1001: begin // mod
result <= srcA % srcB;
end
'b 0010: begin // and
result <= srcA & srcB;
end
'b 0110: begin // or
result <= srcA | srcB;
end
'b 1010: begin // less
result <= $signed(srcA) < $signed(srcB);
end
'b 1011: begin // greater of equal
result <= srcA >= srcB;
end
'b 0111: begin // <<
result[31:0] <= (srcA[31:0] << srcB[4:0]);
end
'b 1110: begin // >>
result[31:0] <= (srcA[31:0] >> srcB[4:0]);
end
'b 0011: begin // >>>
result[31:0] <= ((srcA >>> srcB) | ('h FFFFFFFF << (32 - srcB[4:0])));
// result <= srcA >>> srcB;
end
'b 1111: begin // ignore src a
result <= srcB;
end
default: begin
result <= 0;
end
endcase
assign zeroFlag = result == 0;
endmodule
module immDecode( input [31:7] in, input [2:0] imm_control, output reg [31:0] out );
// control
// lw & addi & jalr -> 000
// sw -> 001
// beq -> 010
// jal -> 011
// lui -> 100
always @(*) begin
if (imm_control[2:0] == 'b 000) begin
out[31:12] <= {21{in[31]}};
out[11:0] <= in[31:20];
end else if (imm_control[2:0] == 'b 001) begin
out[31:12] <= {21{in[31]}};
out[11:5] <= in[31:25];
out[4:0] <= in[11:7];
end else if (imm_control[2:0] == 'b 010) begin
out[31:13] <= {19{in[31]}};
out[12] <= in[31];
out[11] <= in[7];
out[10:5] <= in[30:25];
out[4:1] <= in[11:8];
out[0] <= 0;
end else if (imm_control[2:0] == 'b 011) begin
out[31:21] <= {11{in[31]}};
out[20] <= in[31];
out[19:12] <= in[19:12];
out[11] <= in[20];
out[10:1] <= in[30:21];
out[0] <= 0;
end else if (imm_control[2:0] == 'b 100) begin
out[31:12] <= in[31:12];
out[11:0] <= 0;
end
end
endmodule
module register( input [31:0] in, input clk, reset, output reg [31:0] out );
initial begin
out[31:0] = 0;
end
always @(posedge clk) begin
if (reset)
out[31:0] = 0;
else
out = in;
end
endmodule
module mux2_1(input [31:0]d0, d1, input select, output [31:0]y );
assign y = select ? d1 : d0;
endmodule
module mux4_1(input [31:0]d0, d1, d2, d3, input [1:0]select, output [31:0]y );
assign y = select[0] ? (select[1] ? d3 : d1) : (select[1] ? d2 : d0);
endmodule
module register_unit_32x32(input clk, write_enabled, input [31:0] datain, input [4:0] address1, address2, address3, output [31:0] dataout1, dataout2 );
reg [31:0] registers[31:0];
always @(posedge clk) begin
if (write_enabled && address3 != 0)
registers[address3] <= datain;
end
integer dump_counter;
initial begin
dump_counter = 0;
registers[0] = 32'b0;
registers[1] = 32'b0;
registers[2] = 32'b0;
registers[3] = 32'b0;
registers[4] = 32'b0;
registers[5] = 32'b0;
registers[6] = 32'b0;
registers[7] = 32'b0;
registers[8] = 32'b0;
registers[9] = 32'b0;
registers[10] = 32'b0;
registers[11] = 32'b0;
registers[12] = 32'b0;
registers[13] = 32'b0;
registers[14] = 32'b0;
registers[15] = 32'b0;
registers[16] = 32'b0;
registers[17] = 32'b0;
registers[18] = 32'b0;
registers[19] = 32'b0;
registers[20] = 32'b0;
registers[21] = 32'b0;
registers[22] = 32'b0;
registers[23] = 32'b0;
registers[24] = 32'b0;
registers[25] = 32'b0;
registers[26] = 32'b0;
registers[27] = 32'b0;
registers[28] = 32'b0;
registers[29] = 32'b0;
registers[30] = 32'b0;
registers[31] = 32'b0;
end
// always #2 begin
// $writememh($sformatf("./regdump/reg_%0d.hex", dump_counter), registers, 0, 31);
// dump_counter = dump_counter + 1;
// end
assign dataout1 = registers[address1];
assign dataout2 = registers[address2];
endmodule
module program_counter(input clk, output reg [31:0] address );
initial begin
address[31:0] = 32'b0;
end
always @(posedge clk) begin
address[31:0] <= address[31:0] + 1;
end
endmodule
module control_unit_module( input [31:0] instruction,
output reg
branch_beq,
branch_jal,
branch_jalr,
reg_write,
mem_to_reg,
mem_write,
alu_src_select,
auipc,
output reg [2:0] imm_control,
output reg [3:0] alu_control
);
wire [6:0] optcode;
assign optcode[6:0] = instruction[6:0];
wire [2:0]funct3 = instruction[14:12];
wire [6:0]funct7 = instruction[31:25];
always @(*) begin
// lw
if (optcode == 'b0000011 && funct3 == 'b010) begin
alu_src_select <= 1;
alu_control <= 'b 0100;
mem_write <= 0;
mem_to_reg <= 1;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// sw
else if (optcode == 'b0100011 && funct3 == 'b010) begin
alu_src_select <= 1;
alu_control <= 'b 0100;
mem_write <= 1;
mem_to_reg <= 0;
reg_write <= 0;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 001;
end
// add
else if (optcode == 'b0110011 && funct3 == 'b000 && funct7 == 'b0000000) begin
alu_src_select <= 0;
alu_control <= 'b 0100;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// addi
else if (optcode == 'b0010011 && funct3 == 'b000) begin
alu_src_select <= 1;
alu_control <= 'b 0100;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// sub
else if (optcode == 'b0110011 && funct3 == 'b000 && funct7 == 'b0100000) begin
alu_src_select <= 0;
alu_control <= 'b 1100;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// slt
else if (optcode == 'b0110011 && funct3 == 'b010 && funct7 == 'b0000000) begin
alu_src_select <= 0;
alu_control <= 'b 1010;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// or
else if (optcode == 'b0110011 && funct3 == 'b110 && funct7 == 'b0000000) begin
alu_src_select <= 0;
alu_control <= 'b 0110;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// and
else if (optcode == 'b0110011 && funct3 == 'b111 && funct7 == 'b0000000) begin
alu_src_select <= 0;
alu_control <= 'b 0010;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// beq
else if (optcode == 'b1100011 && funct3 == 'b000) begin
alu_src_select <= 0;
alu_control <= 'b 1100;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 0;
branch_beq <= 1;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 010;
end
// jal
else if (optcode == 'b1101111) begin
alu_src_select <= 0;
alu_control <= 'b 0000;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 1;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 011;
end
// jalr
else if (optcode == 'b1100111 && funct3 == 'b000) begin
alu_src_select <= 1;
alu_control <= 'b 0100;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 0;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 1;
auipc <= 0;
imm_control <= 'b 000;
end
// div
else if (optcode == 'b0110011 && funct3 == 'b100 && funct7 == 'b0000001) begin
alu_src_select <= 0;
alu_control <= 'b 0001;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// rem
else if (optcode == 'b0110011 && funct3 == 'b110 && funct7 == 'b0000001) begin
alu_src_select <= 0;
alu_control <= 'b 1001;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// blt
else if (optcode == 'b1100011 && funct3 == 'b100) begin
alu_src_select <= 0;
alu_control <= 'b 1011;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 0;
branch_beq <= 1;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 010;
end
// lui
else if (optcode == 'b0110111) begin
alu_src_select <= 1;
alu_control <= 'b 1111;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 100;
end
// auipc
else if (optcode == 'b0010111) begin
alu_src_select <= 1;
alu_control <= 'b 0100;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 1;
imm_control <= 'b 100;
end
// sll
else if (optcode == 'b0110011 && funct3 == 'b001 && funct7 == 'b0000000) begin
alu_src_select <= 0;
alu_control <= 'b 0111;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// srl
else if (optcode == 'b0110011 && funct3 == 'b101 && funct7 == 'b0000000) begin
alu_src_select <= 0;
alu_control <= 'b 1110;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
// sra
else if (optcode == 'b0110011 && funct3 == 'b101 && funct7 == 'b0100000) begin
alu_src_select <= 0;
alu_control <= 'b 0011;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 1;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end else begin
alu_src_select <= 0;
alu_control <= 'b 0000;
mem_write <= 0;
mem_to_reg <= 0;
reg_write <= 0;
branch_beq <= 0;
branch_jal <= 0;
branch_jalr <= 0;
auipc <= 0;
imm_control <= 'b 000;
end
end
endmodule
module pc_adder_module(input [31:0]prev_address, output [31:0]next_address);
assign next_address = prev_address + 4;
endmodule
module adder_module32(input [31:0]in1, input [31:0]in2, output [31:0]out);
assign out[31:0] = in1[31:0] + in2[31:0];
endmodule
`default_nettype wire
//#############################################################
// TEST MODULES
module data_mem (input clk, we,
input [31:0] address, wd,
output [31:0] rd);
reg [31:0] RAM[63:0];
integer dump_counter;
initial begin
dump_counter = 0;
$readmemh ("memfile_data.hex",RAM,0,63);
end
// always #1 begin
// $writememh($sformatf("./memdump/mem_%0d.hex", dump_counter), RAM, 0, 63);
// dump_counter = dump_counter + 1;
// end
assign rd=RAM[address[31:2]]; // word aligned
always @ (posedge clk)
if (we)
RAM[address[31:2]]<=wd;
endmodule
//-------------------------------------------------------------------
module inst_mem (input [5:0] address,
output [31:0] rd);
reg [31:0] RAM[63:0];
initial begin
$readmemh ("Hladuvka_Ondrej_prog1.hex",RAM,0,63);
end
assign rd=RAM[address]; // word aligned
endmodule
module top ( input clk, reset,
output [31:0] data_to_mem, address_to_mem,
output write_enable);
wire [31:0] pc, instruction, data_from_mem;
inst_mem imem(pc[7:2], instruction);
data_mem dmem(clk, write_enable, address_to_mem, data_to_mem, data_from_mem);
processor CPU(clk, reset, pc, instruction, write_enable, address_to_mem, data_to_mem, data_from_mem);
endmodule
module testbench();
reg clk;
reg reset;
wire [31:0] data_to_mem, address_to_mem;
wire write_enable;
top simulated_system (clk, reset, data_to_mem, address_to_mem, write_enable);
initial begin
$dumpfile("test");
$dumpvars;
reset<=1; # 2; reset<=0;
#1000;
$writememh ("memfile_data_after_simulation.hex",simulated_system.dmem.RAM,0,63);
$finish;
end
// generate clock
always begin
clk<=1; # 1; clk<=0; # 1;
end
endmodule
//#############################################################

62
memfile_data.hex Normal file
View File

@ -0,0 +1,62 @@
00000008
00000008
00000013
00000025
0000002b
00000059
00000016
00000023
0000004d
00000063
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

54
prog.asm Normal file
View File

@ -0,0 +1,54 @@
beq x0, x0 main
test:
addi t0, x0, 4
blt a0, t0, is_prime
addi t0, x0, 2
rem t1, a0, t0
beq t1, x0, is_not_prime
addi t1, x0, 3
div t2, a0, t0
addi t2, t2, 1
#addi t2, x0, 32 #todo: t2 = min((t2)/2, 32)
prime_loop:
rem t0, a0, t1
beq t0, x0, is_not_prime
addi t1, t1, 2
blt t1, t2, prime_loop
is_prime:
addi a0, x0, 1
jalr ra
is_not_prime:
addi a0, x0, 0
jalr ra
main:
add t3, x0, ra
lw t5, 0(x0) #size
lw t6, 4(x0) #pointer
#lw t5, size
#la t6, array
addi t4, x0, 2
sll t5, t5, t4
add t5, t6, t5
main_loop:
beq t5, t6, end
lw a0, 0(t6)
jal ra, test
sw a0, 0(t6)
addi t6, t6, 4
beq, x0, x0, main_loop
end:
add ra, x0, t3
beq x0, x0, end

24
prog.hex Normal file
View File

@ -0,0 +1,24 @@
00802503
00402583
00000293
00052603
018000ef
00c52023
00128293
00450513
02b28e63
fe9ff06f
00200393
02764063
02760263
00200313
00660e63
02666e33
000e0663
00130313
ff1ff06f
00000613
00008067
00100613
00008067
00008067

41955
test.vcd Normal file

File diff suppressed because it is too large Load Diff