Added rtl and macros configuration
diff --git a/verilog/rtl/elpis/IO_arbiter.v b/verilog/rtl/elpis/IO_arbiter.v
new file mode 100644
index 0000000..c6a176f
--- /dev/null
+++ b/verilog/rtl/elpis/IO_arbiter.v
@@ -0,0 +1,136 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module io_output_arbiter(
+ input clk,
+ input reset,
+ input req_core0,
+ input[31:0] data_core0,
+ output reg print_hex_enable,
+ output reg[31:0] print_output,
+ output reg is_ready_core0
+);
+
+ reg[1:0] arb_state, next_arb_state;
+
+ always@(posedge clk) begin
+ if (reset) begin
+ arb_state <= `ARB_IO_IDLE_STATE;
+ end
+ else arb_state <= next_arb_state;
+ end
+
+ always@(req_core0 or arb_state) begin
+ case(arb_state)
+ `ARB_IO_IDLE_STATE: begin
+ if (req_core0) next_arb_state <= `ARB_IO_CORE1_USE;
+ else next_arb_state <= `ARB_IO_IDLE_STATE;
+ end
+ `ARB_IO_CORE1_USE: begin
+ next_arb_state <= `ARB_IO_IDLE_STATE;
+ end
+ default: next_arb_state <= `ARB_IO_IDLE_STATE;
+ endcase
+ end
+
+ always@(arb_state) begin
+ case(arb_state)
+ `ARB_IO_IDLE_STATE: begin
+ print_hex_enable <= 1'b0;
+ print_output <= 24'b0;
+ if (reset) begin
+ is_ready_core0 <= 1'b1;
+ end else begin
+ is_ready_core0 <= !req_core0;
+ end
+ end
+ `ARB_IO_CORE1_USE: begin
+ print_hex_enable <= 1'b1;
+ print_output <= data_core0;
+ is_ready_core0 <= 1'b1;
+ end
+ default: begin
+ print_hex_enable <= 1'b0;
+ print_output <= 24'b0;
+ is_ready_core0 <= 1'b1;
+ end
+ endcase
+ end
+
+endmodule
+
+
+module io_input_arbiter(
+ input clk,
+ input reset,
+ input req_core0,
+ input[31:0] read_value,
+ input read_enable,
+ output reg is_ready_core0,
+ output reg[31:0] data_out
+);
+
+ reg[1:0] arb_state, next_arb_state;
+
+ always@(posedge clk) begin
+ if (reset) begin
+ arb_state <= `ARB_IO_IDLE_STATE;
+ end
+ else arb_state <= next_arb_state;
+ end
+
+ always@(req_core0 or arb_state or read_enable) begin
+ case(arb_state)
+ `ARB_IO_IDLE_STATE: begin
+ if (req_core0) next_arb_state <= `ARB_IO_CORE1_USE;
+ else next_arb_state <= `ARB_IO_IDLE_STATE;
+ end
+ `ARB_IO_CORE1_USE: begin
+ if (read_enable) next_arb_state <= `ARB_IO_IDLE_STATE;
+ else next_arb_state <= `ARB_IO_CORE1_USE;
+ end
+ default: next_arb_state <= `ARB_IO_IDLE_STATE;
+ endcase
+ end
+
+ always@(arb_state or read_enable) begin
+ case(arb_state)
+ `ARB_IO_IDLE_STATE: begin
+ is_ready_core0 <= 1'b0;
+ data_out <= 10'b0;
+ end
+ `ARB_IO_CORE1_USE: begin
+ if (read_enable) begin
+ is_ready_core0 <= 1'b1;
+ data_out <= read_value;
+ end else begin
+ is_ready_core0 <= 1'b0;
+ data_out <= 10'b0;
+ end
+ end
+ default: begin
+ is_ready_core0 <= 1'b0;
+ data_out <= 10'b0;
+ end
+ endcase
+ end
+
+endmodule
+
+
diff --git a/verilog/rtl/elpis/alu.v b/verilog/rtl/elpis/alu.v
new file mode 100644
index 0000000..5c9b025
--- /dev/null
+++ b/verilog/rtl/elpis/alu.v
@@ -0,0 +1,142 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module alu(
+ input[31:0] x,
+ input[31:0] y,
+ input[3:0] op,
+ output reg[31:0] w,
+ output z,
+ output reg[31:0] exception_code
+);
+
+ wire[32:0] w_add = x + y;
+ wire[32:0] w_sub = x - y;
+ wire[31:0] w_and = x & y;
+ wire[31:0] w_or = x | y;
+ wire[31:0] w_xor = x ^ y;
+ wire[31:0] w_sll = x << y;
+ wire[31:0] w_srl = x >> y;
+ //wire[31:0] w_sra = $signed(x) >>> y;
+ wire[31:0] w_sra = 32'b0;
+
+ //wire[31:0] excp = (op == `ALU_OP_ADD) ? ((w_add[32] && (x[31] == y[31])) ? `EXC_OVERFLOW : 0) : ( (op == `ALU_OP_SUB) ? ( (w_sub[32]) ? `EXC_UNDERFLOW : 0) : 32'b0);
+
+ assign z = (x==y) ? 1'b1 : 1'b0;
+ wire is_add = op == `ALU_OP_ADD;
+ wire is_sub = op == `ALU_OP_SUB;
+ wire is_and = op == `ALU_OP_AND;
+ wire is_or = op == `ALU_OP_OR;
+ wire is_xor = op == `ALU_OP_XOR;
+ wire is_branch = op == `ALU_OP_BRANCH;
+ wire is_sll = op == `ALU_OP_SLL;
+ wire is_slr = op == `ALU_OP_SRL;
+ wire is_sra = op == `ALU_OP_SRA;
+ (* parallel_case, full_case *)
+ always@(*) begin
+ case(1'b1)
+ is_add: begin
+ w = w_add[31:0];
+ end
+ is_sub: begin
+ w = w_sub[31:0];
+ end
+ is_and: begin
+ w = w_and;
+ end
+ is_or: begin
+ w = w_or;
+ end
+ is_xor: begin
+ w = w_xor;
+ end
+ is_branch: begin
+ w = w_add[31:0];
+ end
+ is_sll: begin
+ w = w_sll;
+ end
+ is_slr: begin
+ w = w_srl;
+ end
+ is_sra: begin
+ w = w_sra;
+ end
+ default: begin
+ w = 32'b0;
+ end
+ endcase
+ end
+ // always@(*) begin
+ // case(op)
+ // `ALU_OP_ADD: begin
+ // {carry, w} = x + y;
+ // exception_code = (carry && (x[31] == y[31])) ? `EXC_OVERFLOW : 0;
+ // end
+ // `ALU_OP_SUB: begin
+ // {carry, w} = x - y;
+ // exception_code = (carry) ? `EXC_UNDERFLOW : 0;
+ // end
+ // `ALU_OP_AND: begin
+ // w = x & y;
+ // exception_code = 32'b0;
+ // carry = 0;
+ // end
+ // `ALU_OP_OR: begin
+ // w = x | y;
+ // exception_code = 32'b0;
+ // carry = 0;
+ // end
+ // `ALU_OP_XOR: begin
+ // w = x ^ y;
+ // exception_code = 32'b0;
+ // carry = 0;
+ // end
+ // `ALU_OP_BRANCH: begin
+ // w = x + y;
+ // exception_code = 32'b0;
+ // carry = 0;
+ // end
+ // `ALU_OP_SLL: begin
+ // w = x << y;
+ // exception_code = 32'b0;
+ // carry = 0;
+ // end
+ // `ALU_OP_SRL: begin
+ // w = x >> y;
+ // exception_code = 32'b0;
+ // carry = 0;
+ // end
+ // `ALU_OP_SRA: begin
+ // w = $signed(x) >>> y;
+ // exception_code = 32'b0;
+ // carry = 0;
+ // end
+ // default: begin
+ // w = 32'b0;
+ // exception_code = 32'b0;
+ // carry = 0;
+ // end
+ // endcase
+
+ // z = (x==y) ? 1'b1 : 1'b0;
+
+ // end
+
+endmodule
diff --git a/verilog/rtl/elpis/arbiter.v b/verilog/rtl/elpis/arbiter.v
new file mode 100644
index 0000000..e2cb850
--- /dev/null
+++ b/verilog/rtl/elpis/arbiter.v
@@ -0,0 +1,151 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module arbiter(
+ input clk,
+ input reset,
+ output reg[19:0] mem_addr,
+ input[127:0] dcache_to_mem_data_in, // Input data from dCache
+ output reg[127:0] dcache_to_mem_data_out, // Output data to memory
+ output [127:0] mem_to_icache_data, // Output data to iCache
+ output [127:0] mem_to_dcache_data, // Output data to dCache
+ input[127:0] data_from_mem, // Input data from memory
+ input dcache_we,
+ output reg mem_we,
+ input icache_request,
+ input dcache_request,
+ input mem_ready,
+ output reg is_icache_ready,
+ output reg is_dcache_ready,
+ input reset_mem_req,
+ input hit_itlb_in,
+ input hit_dtlb_in,
+ input[19:0] itlb_physical_addr_in,
+ input[19:0] dtlb_physical_addr_in,
+ input dcache_re,
+ output reg is_mem_req
+);
+
+ reg[2:0] arb_state, next_arb_state;
+
+ assign mem_to_icache_data = data_from_mem;
+ assign mem_to_dcache_data = data_from_mem;
+
+ always@(posedge clk) begin
+ if (reset || reset_mem_req) begin
+ arb_state <= `ARB_IDLE_STATE;
+ end
+ else arb_state <= next_arb_state;
+ end
+
+ always@(dcache_request or icache_request or hit_dtlb_in or hit_itlb_in or mem_ready or arb_state) begin
+ case(arb_state)
+ `ARB_IDLE_STATE: begin
+ if (dcache_request && hit_dtlb_in) next_arb_state <= `ARB_DCACHE_REQUEST;
+ else if (icache_request && hit_itlb_in) next_arb_state <= `ARB_ICACHE_REQUEST;
+ else next_arb_state <= `ARB_IDLE_STATE;
+ end
+ `ARB_DCACHE_REQUEST: begin
+ next_arb_state <= `ARB_DCACHE_WAIT;
+ end
+ `ARB_ICACHE_REQUEST: begin
+ next_arb_state <= `ARB_ICACHE_WAIT;
+ end
+ `ARB_DCACHE_WAIT: begin
+ if(mem_ready)begin
+ next_arb_state <= `ARB_IDLE_STATE;
+ end else begin
+ next_arb_state <= `ARB_DCACHE_WAIT;
+ end
+ end
+ `ARB_ICACHE_WAIT: begin
+ if(mem_ready) begin
+ next_arb_state <= `ARB_IDLE_STATE;
+ end else begin
+ next_arb_state <= `ARB_ICACHE_WAIT;
+ end
+ end
+ default: next_arb_state <= `ARB_IDLE_STATE;
+ endcase
+ end
+
+ always@(arb_state or mem_ready) begin
+ case(arb_state)
+ `ARB_IDLE_STATE: begin
+ is_dcache_ready <= 0;
+ is_icache_ready <= 0;
+ mem_we <= 0;
+ dcache_to_mem_data_out <= 0;
+ mem_addr <= 0;
+ is_mem_req <= 1'b0;
+ end
+ `ARB_DCACHE_REQUEST: begin
+ is_dcache_ready <= 0;
+ is_icache_ready <= 0;
+ mem_we <= dcache_we;
+ mem_addr <= dtlb_physical_addr_in;
+ dcache_to_mem_data_out <= dcache_to_mem_data_in;
+ is_mem_req <= 1'b1;
+ end
+ `ARB_ICACHE_REQUEST: begin
+ is_dcache_ready <= 0;
+ is_icache_ready <= 0;
+ mem_we <= 0;
+ mem_addr <= itlb_physical_addr_in;
+ dcache_to_mem_data_out <= 0;
+ is_mem_req <= 1'b1;
+ end
+ `ARB_DCACHE_WAIT: begin
+ if (mem_ready) begin
+ is_dcache_ready <= mem_ready;
+ is_mem_req <= 1'b0;
+ end else begin
+ is_dcache_ready <= 0;
+ is_mem_req <= 1'b1;
+ end
+ is_icache_ready <= 0;
+ mem_we <= dcache_we;
+ dcache_to_mem_data_out <= dcache_to_mem_data_in;
+ mem_addr <= dtlb_physical_addr_in;
+ end
+ `ARB_ICACHE_WAIT: begin
+ if (mem_ready) begin
+ is_icache_ready <= mem_ready;
+ is_mem_req <= 1'b0;
+ end else begin
+ is_icache_ready <= 0;
+ is_mem_req <= 1'b1;
+ end
+ is_dcache_ready <= 0;
+ mem_we <= 0;
+ dcache_to_mem_data_out <= 0;
+ mem_addr <= itlb_physical_addr_in;
+ end
+ default: begin
+ is_dcache_ready <= 0;
+ is_icache_ready <= 0;
+ mem_we <= 0;
+ dcache_to_mem_data_out <= 0;
+ mem_addr <= 0;
+ is_mem_req <= 1'b0;
+ end
+ endcase
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/betweenStages.v b/verilog/rtl/elpis/betweenStages.v
new file mode 100644
index 0000000..59077d9
--- /dev/null
+++ b/verilog/rtl/elpis/betweenStages.v
@@ -0,0 +1,595 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module IF_ID(input clk, input stall_icache, input stall, input flush, input[31:0] pc_in, input[31:0] inst_in, input is_hit_itlb_in, input[31:0] exc_code_in,
+ input psw_in, input is_flush_in,
+ output reg[31:0] pc_out, output reg[31:0] inst_out, output reg is_hit_itlb_out, output reg[31:0] rm2_out, output reg psw_out, output reg[31:0] rm1_out,
+ output reg[31:0] rm0_out, output reg is_flush_out);
+
+ always@(posedge clk) begin
+ if (flush) begin
+ inst_out <= `NOP;
+ pc_out <= `PC_INITIAL;
+ is_hit_itlb_out <= 0;
+ rm2_out <= 0;
+ psw_out <= 0;
+ rm1_out <= 0;
+ rm0_out <= 0;
+ is_flush_out <= 1;
+ end else if (exc_code_in) begin
+ inst_out <= `NOP;
+ pc_out <= `PC_INITIAL;
+ is_hit_itlb_out <= 0;
+ rm2_out <= exc_code_in;
+ psw_out <= psw_in;
+ rm1_out <= pc_in;
+ rm0_out <= pc_in;
+ is_flush_out <= 0;
+ end else if (stall) begin
+ inst_out <= inst_out;
+ pc_out <= pc_out;
+ is_hit_itlb_out <= is_hit_itlb_out;
+ rm2_out <= rm2_out;
+ psw_out <= psw_out;
+ rm1_out <= rm1_out;
+ rm0_out <= rm0_out;
+ is_flush_out <= is_flush_out;
+ end else if (stall_icache) begin
+ inst_out <= `NOP;
+ pc_out <= pc_out;
+ is_hit_itlb_out <= is_hit_itlb_out;
+ rm2_out <= rm2_out;
+ psw_out <= psw_out;
+ rm1_out <= rm1_out;
+ rm0_out <= rm0_out;
+ is_flush_out <= is_flush_out;
+ end else begin
+ inst_out <= inst_in;
+ pc_out <= pc_in;
+ is_hit_itlb_out <= is_hit_itlb_in;
+ rm2_out <= exc_code_in;
+ psw_out <= psw_in;
+ rm1_out <= 0;
+ rm0_out <= 0;
+ is_flush_out <= is_flush_in;
+ end
+ end
+
+endmodule
+
+
+module ID_EX(input clk, input flush, input haz, input stall, input[31:0] reg_a_in, input[31:0] reg_b_in, input[3:0] alu_op_in, input[4:0] reg_addr_dest_in,
+ input reg_write_enable_in, input is_flush_in, input is_ecall_in, input[6:0] io_code_in,
+ input rb_imm_in, input[31:0] immed_in, input mem_to_reg_in, input mem_we_in, input[31:0] pc_in, input[2:0] branch_code_in,input is_a_jump_in, input[4:0] reg_a_addr_in,
+ input[4:0] reg_b_addr_in, input is_byte_in, input[1:0] is_mov_in, input[31:0] reg_rm_in, input psw_in, input[31:0] exc_code_in, input[31:0] fw_reg_a_in, input[31:0] fw_reg_b_in,
+ input is_tlbwrite_in, input is_iret_in, input is_hit_itlb_in, input[31:0] rm2_in, input[31:0] rm1_in, input[31:0] rm0_in, input[31:0] stored_rm1_in, input[31:0] stored_rm2_in, input[31:0] stored_rm4_in,
+ output reg[31:0] reg_a_out, output reg[31:0] reg_b_out, output reg[3:0] alu_op_out, output reg[4:0] reg_addr_dest_out, output reg reg_write_enable_out, output reg[6:0] io_code_out,
+ output reg rb_imm_out, output reg[31:0] immed_out, output reg mem_to_reg_out, output reg mem_we_out, output reg[31:0] pc_out, output reg[2:0] branch_code_out,
+ output reg is_a_jump_out, output reg[4:0] reg_a_addr_out, output reg[4:0] reg_b_addr_out, output reg is_byte_out, output reg[31:0] stored_rm1_out, output reg[31:0] stored_rm2_out, output reg[31:0] stored_rm4_out,
+ output reg[1:0] is_mov_out, output reg[31:0] reg_rm_out, output reg psw_out, output reg pending_haz, output reg is_ecall_out,
+ output reg is_tlbwrite_out, output reg is_iret_out, output reg is_hit_itlb_out, output reg[31:0] rm2_out, output reg[31:0] rm1_out, output reg[31:0] rm0_out, output reg is_flush_out);
+
+ always@(posedge clk) begin
+ if (flush) begin
+ reg_a_out <= 0;
+ reg_b_out <= 0;
+ alu_op_out <= `ALU_OP_ADD;
+ reg_addr_dest_out <= 0;
+ reg_write_enable_out <= 0;
+ rb_imm_out <= 0;
+ immed_out <= 0;
+ mem_to_reg_out <= 0;
+ mem_we_out <= 0;
+ pc_out <= `PC_INITIAL;
+ branch_code_out <= `FUNCT3_BRANCH_NO;
+ is_a_jump_out <= 0;
+ reg_a_addr_out <= 0;
+ reg_b_addr_out <= 0;
+ is_byte_out <= 0;
+ is_mov_out <= 0;
+ is_ecall_out <= 0;
+ reg_rm_out <= 0;
+ psw_out <= 0;
+ is_tlbwrite_out <= 0;
+ is_iret_out <= 0;
+ is_hit_itlb_out <= 0;
+ io_code_out <= 0;
+ rm2_out <= 0;
+ rm1_out <= 0;
+ rm0_out <= 0;
+ stored_rm2_out <= 0;
+ stored_rm1_out <= 0;
+ stored_rm4_out <= 0;
+ pending_haz <= 0;
+ is_flush_out <= 1;
+ end else if (exc_code_in) begin
+ reg_a_out <= 0;
+ reg_b_out <= 0;
+ alu_op_out <= `ALU_OP_ADD;
+ reg_addr_dest_out <= 0;
+ reg_write_enable_out <= 0;
+ rb_imm_out <= 0;
+ immed_out <= 0;
+ mem_to_reg_out <= 0;
+ mem_we_out <= 0;
+ pc_out <= `PC_INITIAL;
+ branch_code_out <= `FUNCT3_BRANCH_NO;
+ is_a_jump_out <= 0;
+ reg_a_addr_out <= 0;
+ reg_b_addr_out <= 0;
+ is_byte_out <= 0;
+ is_mov_out <= 0;
+ is_ecall_out <= 0;
+ reg_rm_out <= 0;
+ psw_out <= 0;
+ io_code_out <= 0;
+ is_tlbwrite_out <= 0;
+ is_iret_out <= 0;
+ is_hit_itlb_out <= 0;
+ stored_rm2_out <= 0;
+ stored_rm1_out <= 0;
+ stored_rm4_out <= 0;
+ pending_haz <= 0;
+ is_flush_out <= 0;
+ if (rm2_in) begin
+ rm2_out <= rm2_in;
+ rm1_out <= rm1_in;
+ rm0_out <= rm0_in;
+ end else begin
+ rm2_out <= exc_code_in;
+ rm1_out <= 0;
+ rm0_out <= rm0_in;
+ end
+ end else if (stall) begin
+ reg_a_out <= fw_reg_a_in;
+ reg_b_out <= fw_reg_b_in;
+ alu_op_out <= alu_op_out;
+ reg_addr_dest_out <= reg_addr_dest_out;
+ reg_write_enable_out <= reg_write_enable_out;
+ rb_imm_out <= rb_imm_out;
+ immed_out <= immed_out;
+ mem_to_reg_out <= mem_to_reg_out;
+ mem_we_out <= mem_we_out;
+ branch_code_out <= branch_code_out;
+ is_a_jump_out <= is_a_jump_out;
+ reg_a_addr_out <= reg_a_addr_out;
+ reg_b_addr_out <= reg_b_addr_out;
+ pc_out <= pc_out;
+ is_byte_out <= is_byte_out;
+ is_mov_out <= is_mov_out;
+ is_ecall_out <= is_ecall_out;
+ reg_rm_out <= reg_rm_out;
+ psw_out <= psw_out;
+ is_tlbwrite_out <= is_tlbwrite_out;
+ is_iret_out <= is_iret_out;
+ io_code_out <= io_code_out;
+ is_hit_itlb_out <= is_hit_itlb_out;
+ rm2_out <= rm2_out;
+ rm1_out <= rm1_out;
+ rm0_out <= rm0_out;
+ stored_rm2_out <= stored_rm2_out;
+ stored_rm1_out <= stored_rm1_out;
+ stored_rm4_out <= stored_rm4_out;
+ is_flush_out <= is_flush_out;
+ pending_haz <= haz;
+ end else if (haz) begin
+ reg_a_out <= reg_a_out;
+ reg_b_out <= reg_b_out;
+ alu_op_out <= 0;
+ reg_addr_dest_out <= 0;
+ reg_write_enable_out <= 0;
+ rb_imm_out <= rb_imm_out;
+ immed_out <= immed_out;
+ mem_to_reg_out <= 0;
+ mem_we_out <= 0;
+ branch_code_out <= `FUNCT3_BRANCH_NO;
+ is_a_jump_out <= 0;
+ reg_a_addr_out <= reg_a_addr_out;
+ reg_b_addr_out <= reg_b_addr_out;
+ pc_out <= pc_out;
+ is_byte_out <= 0;
+ is_mov_out <= is_mov_out;
+ io_code_out <= io_code_out;
+ is_ecall_out <= is_ecall_out;
+ reg_rm_out <= reg_rm_out;
+ psw_out <= psw_out;
+ is_tlbwrite_out <= is_tlbwrite_out;
+ is_iret_out <= is_iret_out;
+ is_hit_itlb_out <= is_hit_itlb_out;
+ rm2_out <= rm2_in;
+ rm1_out <= rm1_in;
+ rm0_out <= rm0_in;
+ stored_rm2_out <= stored_rm2_out;
+ stored_rm1_out <= stored_rm1_out;
+ stored_rm4_out <= stored_rm4_out;
+ pending_haz <= 0;
+ is_flush_out <= is_flush_out;
+ end else begin
+ reg_a_out <= reg_a_in;
+ reg_b_out <= reg_b_in;
+ alu_op_out <= alu_op_in;
+ reg_addr_dest_out <= reg_addr_dest_in;
+ reg_write_enable_out <= reg_write_enable_in;
+ rb_imm_out <= rb_imm_in;
+ immed_out <= immed_in;
+ mem_to_reg_out <= mem_to_reg_in;
+ mem_we_out <= mem_we_in;
+ pc_out <= pc_in;
+ branch_code_out <= branch_code_in;
+ is_a_jump_out <= is_a_jump_in;
+ reg_a_addr_out <= reg_a_addr_in;
+ reg_b_addr_out <= reg_b_addr_in;
+ is_byte_out <= is_byte_in;
+ is_mov_out <= is_mov_in;
+ io_code_out <= io_code_in;
+ is_ecall_out <= is_ecall_in;
+ reg_rm_out <= reg_rm_in;
+ psw_out <= psw_in;
+ is_tlbwrite_out <= is_tlbwrite_in;
+ is_iret_out <= is_iret_in;
+ is_hit_itlb_out <= is_hit_itlb_in;
+ rm2_out <= rm2_in;
+ rm1_out <= rm1_in;
+ rm0_out <= rm0_in;
+ stored_rm2_out <= stored_rm2_in;
+ stored_rm1_out <= stored_rm1_in;
+ stored_rm4_out <= stored_rm4_in;
+ pending_haz <= 0;
+ is_flush_out <= is_flush_in;
+ end
+ end
+
+endmodule
+
+
+module EX_MEM(input clk, input flush, input stall, input reg_write_enable_in, input[4:0] reg_dest_in, input [31:0] reg_data_in, input mem_to_reg_in, input[31:0] pc_in,
+ input mem_we_in, input[31:0] reg_b_in, input[31:0] pc_candidate_address_in, input z_in, input is_branch_taken_in, input is_a_jump_in, input is_flush_in, input[6:0] io_code_in,
+ input[31:0] exc_code_in, input[31:0] rm0_in, input[31:0] rm1_in, input[31:0] rm2_in, input psw_in, input is_byte_in, input sb_hit_in, input is_ecall_in, input[1:0] is_mov_in,
+ input[4:0] reg_b_addr_in, input[31:0] sb_addr_out_in, input[31:0] sb_data_out_in, input sb_data_to_cache_in, input was_stall_dcache_in, input sb_is_byte_in,
+ input is_tlbwrite_in, input is_iret_in, input is_hit_itlb_in, input[31:0] stored_rm4_in, input[31:0] stored_rm2_in, input[31:0] stored_rm1_in, input[31:0] physical_tlb_addr_in,
+ output reg reg_write_enable_out, output reg[4:0] reg_dest_out, output reg [31:0] reg_data_out, output reg[31:0] stored_rm1_out, output reg[31:0] stored_rm2_out, output reg[31:0] stored_rm4_out,
+ output reg mem_to_reg_out, output reg mem_we_out, output reg[31:0] reg_b_out,output reg[31:0] pc_candidate_address_out, output reg [31:0] physical_tlb_addr_out,
+ output reg z_out, output reg is_branch_taken_out, output reg is_a_jump_out,
+ output reg[31:0] rm0_out, output reg[31:0] rm1_out, output reg[31:0] rm2_out, output reg psw_out, output reg is_flush_out, output reg[6:0] io_code_out,
+ output reg is_byte_out, output reg sb_is_byte_out, output reg[4:0] reg_b_addr_out, output reg[31:0] sb_addr_out_out, output reg[31:0] sb_data_out_out, output reg[1:0] is_mov_out,
+ output reg sb_hit_out, output reg sb_data_to_cache_out, output reg was_stall_dcache_out, output reg is_tlbwrite_out, output reg is_iret_out, output reg is_ecall_out,
+ output reg is_hit_itlb_out, output reg[31:0] pc_out);
+
+ always@(posedge clk) begin
+ if (flush) begin
+ reg_write_enable_out <= 0;
+ reg_dest_out <= 0;
+ reg_data_out <= 0;
+ mem_to_reg_out <= 0;
+ mem_we_out <= 0;
+ reg_b_out <= 0;
+ pc_candidate_address_out <= `PC_INITIAL;
+ z_out <= 0;
+ is_branch_taken_out <= 0;
+ is_a_jump_out <= 0;
+ is_ecall_out <= 0;
+ io_code_out <= 0;
+ rm0_out <= 0;
+ rm1_out <= 0;
+ rm2_out <= 0;
+ psw_out <= 0;
+ is_byte_out <= 0;
+ reg_b_addr_out <= 0;
+ sb_addr_out_out <= 0;
+ sb_is_byte_out <= 0;
+ sb_data_out_out <= 0;
+ was_stall_dcache_out <= 0;
+ sb_data_to_cache_out <= 0;
+ sb_hit_out <= 0;
+ is_tlbwrite_out <= 0;
+ is_iret_out <= 0;
+ is_hit_itlb_out <= 0;
+ stored_rm2_out <= 0;
+ stored_rm1_out <= 0;
+ stored_rm4_out <= 0;
+ physical_tlb_addr_out <= 0;
+ is_mov_out <= 0;
+ pc_out <= `PC_INITIAL;
+ is_flush_out <= 1;
+ end else if (exc_code_in) begin
+ reg_write_enable_out <= 0;
+ reg_dest_out <= 0;
+ reg_data_out <= 0;
+ mem_to_reg_out <= 0;
+ mem_we_out <= 0;
+ reg_b_out <= 0;
+ pc_candidate_address_out <= `PC_INITIAL;
+ z_out <= 0;
+ io_code_out <= 0;
+ is_ecall_out <= 0;
+ is_branch_taken_out <= 0;
+ is_a_jump_out <= 0;
+ is_byte_out <= 0;
+ reg_b_addr_out <= 0;
+ sb_addr_out_out <= 0;
+ sb_is_byte_out <= 0;
+ sb_data_out_out <= 0;
+ is_mov_out <= 0;
+ // if (rm2_in) begin
+ // rm2_out <= rm2_in;
+ // rm0_out <= rm0_in;
+ // rm1_out <= rm1_in;
+ // end else begin
+ // rm2_out <= exc_code_in;
+ // rm0_out <= rm0_in;
+ // rm1_out <= 0;
+ // end
+ rm2_out <= (rm2_in) ? rm2_in : exc_code_in;
+ rm0_out <= (rm2_in) ? rm0_in : rm0_in;
+ rm1_out <= (rm2_in) ? rm1_in : 0;
+ psw_out <= psw_in;
+ was_stall_dcache_out <= 0;
+ sb_data_to_cache_out <= 0;
+ sb_hit_out <= 0;
+ is_tlbwrite_out <= 0;
+ is_iret_out <= 0;
+ is_hit_itlb_out <= 0;
+ stored_rm2_out <= 0;
+ stored_rm1_out <= 0;
+ stored_rm4_out <= 0;
+ physical_tlb_addr_out <= 0;
+ pc_out <= `PC_INITIAL;
+ is_flush_out <= 0;
+ end else if (!stall) begin
+ reg_write_enable_out <= reg_write_enable_in;
+ reg_dest_out <= reg_dest_in;
+ reg_data_out <= reg_data_in;
+ mem_to_reg_out <= mem_to_reg_in;
+ mem_we_out <= mem_we_in;
+ reg_b_out <= reg_b_in;
+ pc_candidate_address_out <= pc_candidate_address_in;
+ z_out <= z_in;
+ io_code_out <= io_code_in;
+ is_branch_taken_out <= is_branch_taken_in;
+ is_a_jump_out <= is_a_jump_in;
+ is_byte_out <= is_byte_in;
+ reg_b_addr_out <= reg_b_addr_in;
+ rm0_out <= rm0_in;
+ rm1_out <= rm1_in;
+ rm2_out <= rm2_in;
+ psw_out <= psw_in;
+ is_ecall_out <= is_ecall_in;
+ sb_addr_out_out <= sb_addr_out_in;
+ sb_data_out_out <= sb_data_out_in;
+ sb_is_byte_out <= sb_is_byte_in;
+ was_stall_dcache_out <= 0;
+ sb_data_to_cache_out <= 0;
+ sb_hit_out <= 0;
+ is_tlbwrite_out <= is_tlbwrite_in;
+ is_iret_out <= is_iret_in;
+ is_hit_itlb_out <= is_hit_itlb_in;
+ stored_rm2_out <= stored_rm2_in;
+ stored_rm1_out <= stored_rm1_in;
+ stored_rm4_out <= stored_rm4_in;
+ physical_tlb_addr_out <= physical_tlb_addr_in;
+ pc_out <= pc_in;
+ is_flush_out <= is_flush_in;
+ is_mov_out <= is_mov_in;
+ end else if (was_stall_dcache_out) begin
+ was_stall_dcache_out <= was_stall_dcache_out;
+ sb_addr_out_out <= sb_addr_out_out;
+ sb_data_out_out <= sb_data_out_out;
+ sb_is_byte_out <= sb_is_byte_out;
+ sb_data_to_cache_out <= sb_data_to_cache_out;
+ sb_hit_out <= sb_hit_out;
+ is_iret_out <= is_iret_out;
+ io_code_out <= io_code_out;
+ is_mov_out <= is_mov_out;
+ is_ecall_out <= is_ecall_out;
+ is_branch_taken_out <= is_branch_taken_out;
+ reg_data_out <= reg_data_out;
+ pc_candidate_address_out <= pc_candidate_address_out;
+ rm0_out <= rm0_out;
+ rm1_out <= rm1_out;
+ rm2_out <= rm2_out;
+ psw_out <= psw_out;
+ is_flush_out <= is_flush_out;
+ is_hit_itlb_out <= is_hit_itlb_out;
+ stored_rm2_out <= stored_rm2_out;
+ stored_rm1_out <= stored_rm1_out;
+ stored_rm4_out <= stored_rm4_out;
+ physical_tlb_addr_out <= physical_tlb_addr_out;
+ pc_out <= pc_out;
+ is_tlbwrite_out <= is_tlbwrite_out;
+ is_a_jump_out <= is_a_jump_out;
+ is_byte_out <= is_byte_out;
+ reg_b_addr_out <= reg_b_addr_out;
+ z_out <= z_out;
+ mem_to_reg_out <= mem_to_reg_out;
+ mem_we_out <= mem_we_out;
+ reg_b_out <= reg_b_out;
+ reg_write_enable_out <= reg_write_enable_out;
+ reg_dest_out <= reg_dest_out;
+ end else if (was_stall_dcache_in) begin
+ was_stall_dcache_out <= was_stall_dcache_in;
+ sb_addr_out_out <= sb_addr_out_in;
+ sb_data_out_out <= sb_data_out_in;
+ sb_data_to_cache_out <= sb_data_to_cache_in;
+ sb_is_byte_out <= sb_is_byte_in;
+ sb_hit_out <= sb_hit_in;
+ is_iret_out <= is_iret_in;
+ io_code_out <= io_code_in;
+ is_mov_out <= is_mov_in;
+ is_ecall_out <= is_ecall_in;
+ is_branch_taken_out <= is_branch_taken_in;
+ pc_candidate_address_out <= pc_candidate_address_in;
+ rm0_out <= rm0_out;
+ rm1_out <= rm1_out;
+ rm2_out <= rm2_out;
+ psw_out <= psw_out;
+ is_flush_out <= is_flush_out;
+ is_hit_itlb_out <= is_hit_itlb_out;
+ stored_rm2_out <= stored_rm2_out;
+ stored_rm1_out <= stored_rm1_out;
+ stored_rm4_out <= stored_rm4_out;
+ physical_tlb_addr_out <= physical_tlb_addr_out;
+ pc_out <= pc_out;
+ is_tlbwrite_out <= is_tlbwrite_out;
+ is_a_jump_out <= is_a_jump_out;
+ is_byte_out <= is_byte_out;
+ reg_b_addr_out <= reg_b_addr_out;
+ z_out <= z_out;
+ mem_to_reg_out <= mem_to_reg_out;
+ mem_we_out <= mem_we_out;
+ reg_b_out <= reg_b_out;
+ reg_write_enable_out <= reg_write_enable_out;
+ reg_dest_out <= reg_dest_out;
+ end else begin
+ was_stall_dcache_out <= was_stall_dcache_out;
+ sb_addr_out_out <= sb_addr_out_out;
+ sb_data_out_out <= sb_data_out_out;
+ sb_is_byte_out <= sb_is_byte_out;
+ sb_data_to_cache_out <= sb_data_to_cache_out;
+ sb_hit_out <= sb_hit_out;
+ is_iret_out <= is_iret_out;
+ io_code_out <= io_code_out;
+ is_mov_out <= is_mov_out;
+ is_ecall_out <= is_ecall_out;
+ is_branch_taken_out <= is_branch_taken_out;
+ reg_data_out <= reg_data_out;
+ pc_candidate_address_out <= pc_candidate_address_out;
+ rm0_out <= rm0_out;
+ rm1_out <= rm1_out;
+ rm2_out <= rm2_out;
+ psw_out <= psw_out;
+ is_flush_out <= is_flush_out;
+ is_hit_itlb_out <= is_hit_itlb_out;
+ stored_rm2_out <= stored_rm2_out;
+ stored_rm1_out <= stored_rm1_out;
+ stored_rm4_out <= stored_rm4_out;
+ physical_tlb_addr_out <= physical_tlb_addr_out;
+ pc_out <= pc_out;
+ is_tlbwrite_out <= is_tlbwrite_out;
+ is_a_jump_out <= is_a_jump_out;
+ is_byte_out <= is_byte_out;
+ reg_b_addr_out <= reg_b_addr_out;
+ z_out <= z_out;
+ mem_to_reg_out <= mem_to_reg_out;
+ mem_we_out <= mem_we_out;
+ reg_b_out <= reg_b_out;
+ reg_write_enable_out <= reg_write_enable_out;
+ reg_dest_out <= reg_dest_out;
+ end
+ end
+
+endmodule
+
+
+module MEM_WB(input clk, input flush, input stall, input[4:0] reg_dest_in, input[31:0] reg_data_alu_in, input reg_write_enable_in, input[31:0] mem_data_in, input mem_to_reg_in,
+ input[31:0] rm0_in, input[31:0] rm1_in, input[31:0] rm2_in, input psw_in, input is_iret_in, input is_hit_dtlb_in, input is_hit_itlb_in, input[31:0] exc_code_in, input[31:0] stored_rm4_in,
+ input[31:0] mem_addr_in, input[31:0] pc_in, input is_flush_in, input is_ecall_in, input[1:0] is_mov_in, input[6:0] io_code_in, input[31:0] read_interactive_value_in, input is_read_interactive_enabled_in,
+ output reg[4:0] reg_dest_out, output reg[31:0] reg_data_alu_out, output reg reg_write_enable_out, output reg[31:0] mem_data_out, output reg mem_to_reg_out, output reg[1:0] is_mov_out,
+ output reg[31:0] rm0_out, output reg[31:0] rm1_out, output reg[31:0] rm2_out, output reg is_iret_out, output reg is_hit_dtlb_out, output reg[31:0] pc_out, output reg[31:0] stored_rm4_out,
+ output reg is_hit_itlb_out, output reg is_flush_out, output reg[6:0] io_code_out, output reg[31:0] read_interactive_value_out, output reg is_read_interactive_enabled_out);
+
+ always@(posedge clk) begin
+ if (flush) begin
+ reg_dest_out <= 0;
+ reg_data_alu_out <= 0;
+ reg_write_enable_out <= 1'b0;
+ mem_data_out <= 1'b0;
+ mem_to_reg_out <= 1'b0;
+ rm0_out <= 0;
+ rm1_out <= 0;
+ rm2_out <= 0;
+ stored_rm4_out <= 0;
+ is_iret_out <= 0;
+ is_hit_dtlb_out <= 0;
+ is_hit_itlb_out <= 0;
+ is_mov_out <= 0;
+ io_code_out <= 0;
+ is_read_interactive_enabled_out <= 0;
+ read_interactive_value_out <= 0;
+ pc_out <= `PC_INITIAL;
+ is_flush_out <= 1;
+ end
+ else if (exc_code_in) begin
+ reg_dest_out <= 0;
+ reg_data_alu_out <= 0;
+ reg_write_enable_out <= 1'b0;
+ mem_data_out <= 1'b0;
+ mem_to_reg_out <= 1'b0;
+ rm0_out <= 0;
+ rm1_out <= 0;
+ rm2_out <= 0;
+ stored_rm4_out <= 0;
+ io_code_out <= 0;
+ is_iret_out <= 0;
+ is_mov_out <= 0;
+ is_hit_dtlb_out <= 0;
+ is_hit_itlb_out <= 0;
+ is_read_interactive_enabled_out <= 0;
+ read_interactive_value_out <= 0;
+ if (rm2_in) begin
+ if (rm2_in == `EXC_ITLB_MISS) begin
+ rm2_out <= rm2_in;
+ rm1_out <= rm1_in;
+ rm0_out <= rm0_in;
+ end else begin
+ rm2_out <= 0;
+ rm1_out <= 0;
+ rm0_out <= 0;
+ end
+ end else begin
+ if ( (exc_code_in == `EXC_ITLB_MISS) || (exc_code_in == `EXC_DTLB_MISS ) ) begin
+ rm2_out <= exc_code_in;
+ rm1_out <= mem_addr_in;
+ rm0_out <= pc_in;
+ end else begin
+ rm2_out <= 0;
+ rm1_out <= 0;
+ rm0_out <= 0;
+ end
+ end
+ pc_out <= `PC_INITIAL;
+ is_flush_out <= 0;
+ end else if (!stall) begin
+ reg_dest_out <= reg_dest_in;
+ reg_data_alu_out <= reg_data_alu_in;
+ reg_write_enable_out <= reg_write_enable_in;
+ mem_data_out <= mem_data_in;
+ mem_to_reg_out <= mem_to_reg_in;
+ if(is_ecall_in) begin
+ rm0_out <= pc_in + 4; // PC jumps to the following instruction of the ecall
+ rm1_out <= rm1_in;
+ rm2_out <= reg_data_alu_in;
+ end else begin
+ rm0_out <= rm0_in;
+ rm1_out <= rm1_in;
+ rm2_out <= rm2_in;
+ end
+ stored_rm4_out <= stored_rm4_in;
+ is_mov_out <= is_mov_in;
+ io_code_out <= io_code_in;
+ is_iret_out <= is_iret_in;
+ is_hit_dtlb_out <= is_hit_dtlb_in;
+ is_hit_itlb_out <= is_hit_itlb_in;
+ pc_out <= pc_in;
+ is_flush_out <= is_flush_in;
+ is_read_interactive_enabled_out <= is_read_interactive_enabled_in;
+ read_interactive_value_out <= read_interactive_value_in;
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/elpis/branchComparer.v b/verilog/rtl/elpis/branchComparer.v
new file mode 100644
index 0000000..6ac11ab
--- /dev/null
+++ b/verilog/rtl/elpis/branchComparer.v
@@ -0,0 +1,32 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module branchComparer(input[2:0] branch_code_in, input[31:0] reg_a_content_in, input[31:0] reg_b_content_in, output reg is_branch_taken_out);
+
+ always@(*)begin
+ case(branch_code_in)
+ `FUNCT3_BRANCH_BEQ : is_branch_taken_out = (reg_a_content_in == reg_b_content_in);
+ `FUNCT3_BRANCH_BNE : is_branch_taken_out = (reg_a_content_in != reg_b_content_in);
+ `FUNCT3_BRANCH_BLT : is_branch_taken_out = (reg_a_content_in < reg_b_content_in);
+ `FUNCT3_BRANCH_BGE : is_branch_taken_out = (reg_a_content_in >= reg_b_content_in);
+ default : is_branch_taken_out = 0;
+ endcase
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/cache.v b/verilog/rtl/elpis/cache.v
new file mode 100644
index 0000000..3843301
--- /dev/null
+++ b/verilog/rtl/elpis/cache.v
@@ -0,0 +1,271 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module cache #(parameter CORE_ID = 0, parameter CACHE_TYPE = `CACHE_TYPE_ICACHE)(input clk, input reset, input[31:0] address_in, input[31:0] data_in, input write_enable_in,
+ input read_enable_in, input mem_ready_in, input[127:0] mem_data_in, input is_byte, input reset_mem_req, input privilege_mode, input tlb_we, input tlb_re,
+ input[19:0] physical_addr_in, input[31:0] virtual_addr_write_tlb_in, input[19:0] physical_addr_write_tlb_in,
+ output reg[31:0] read_data_out, output reg hit_out, output reg[19:0] mem_addr_out, output reg[127:0] mem_data_out, output reg req_mem, output reg mem_we_out,
+ output reg hit_tlb, output reg exc_protected_page_tlb);
+
+ wire is_hit_tlb, is_privilege_mode, is_tlb_we, is_tlb_re, is_exc_protected_page_tlb;
+ wire[19:0] phys_addr_out;
+
+ always@(*) begin
+ hit_tlb <= is_hit_tlb;
+ exc_protected_page_tlb <= is_exc_protected_page_tlb;
+ end
+
+ assign is_privilege_mode = privilege_mode;
+ assign is_tlb_we = tlb_we;
+ assign is_tlb_re = tlb_re;
+
+ tlb #(.CORE_ID(CORE_ID), .CACHE_TYPE(CACHE_TYPE)) tlb(
+ .clk(clk),
+ .reset(reset),
+ .virtual_addr(address_in),
+ .virtual_addr_write_in(virtual_addr_write_tlb_in),
+ .privilege_mode(is_privilege_mode),
+ .tlb_we(is_tlb_we),
+ .tlb_re(is_tlb_re),
+ .physical_addr_in(physical_addr_in),
+ .physical_addr_write_in(physical_addr_write_tlb_in),
+ .physical_addr_out(phys_addr_out),
+ .hit_tlb(is_hit_tlb),
+ .exc_protected_page(is_exc_protected_page_tlb)
+ );
+
+ reg[0:0] cacheValidBits[0:`NUM_CACHE_LINES-1];
+ reg[0:0] cacheDirtyBits[0:`NUM_CACHE_LINES-1];
+ reg[`CACHE_TAG_SIZE-1:0] cacheTag[0:`NUM_CACHE_LINES-1];
+ reg[`CACHE_LINE_SIZE-1:0] cacheData[0:`NUM_CACHE_LINES-1];
+
+ // SRAM cache data and tag ports
+ reg[`CACHE_TAG_SIZE-1:0] sram_addr_in_port;
+ wire[`CACHE_TAG_SIZE-1:0] sram_addr_out_port;
+ reg[`CACHE_LINE_SIZE-1:0] sram_data_in_port;
+ wire[`CACHE_LINE_SIZE-1:0] sram_data_out_port;
+ wire sram_we_port, sram_we_valid, sram_we_dirty, sram_value_valid, sram_value_dirty;
+
+ wire[`CACHE_TAG_SIZE-1:0] tag;
+ wire[1:0] index;
+ wire[3:0] offset;
+
+ assign tag = phys_addr_out[19:6];
+ assign index = address_in[5:4];
+ assign offset = address_in[3:0];
+
+ reg[2:0] cache_state, next_cache_state;
+
+ integer i;
+
+ always@(posedge clk)
+ begin
+ if (reset) begin
+ cache_state <= `IDLE_STATE;
+ end
+ else cache_state <= next_cache_state;
+ end
+
+ wire[31:0] auxAL = phys_addr_out>>2;
+ wire[31:0] auxWB = {sram_addr_out_port, index, 2'b0};
+
+ wire no_need_write_back = (!hit_out & !cacheDirtyBits[index]);
+ wire need_write_back = (!hit_out & cacheDirtyBits[index]);
+
+ always@(cache_state or read_enable_in or write_enable_in or reset_mem_req or no_need_write_back or need_write_back or mem_ready_in or is_hit_tlb or hit_out) begin
+ case(cache_state)
+ `IDLE_STATE:begin
+ if ((read_enable_in | write_enable_in) && is_hit_tlb) begin
+ if (hit_out) begin
+ next_cache_state <= `IDLE_STATE;
+ end
+ else if (reset_mem_req) begin
+ next_cache_state <= `IDLE_STATE;
+ end
+ else if (no_need_write_back) begin
+ next_cache_state <= `ALLOCATE_STATE;
+ end
+ else if (need_write_back) begin
+ next_cache_state <= `WRITE_BACK_STATE;
+ end else begin
+ next_cache_state <= `IDLE_STATE;
+ end
+ end
+ else begin
+ next_cache_state <= `IDLE_STATE;
+ end
+ end
+ `ALLOCATE_STATE: begin
+ if (reset_mem_req) next_cache_state <= `IDLE_STATE;
+ else if (!mem_ready_in) next_cache_state <= `ALLOCATE_STATE;
+ else next_cache_state <= `IDLE_STATE;
+ end
+ `WRITE_BACK_STATE: begin
+ if (reset_mem_req) next_cache_state <= `IDLE_STATE;
+ else if (!mem_ready_in) next_cache_state <= `WRITE_BACK_STATE;
+ // else if (mem_ready_in) next_cache_state <= `IDLE_STATE;
+ else next_cache_state <= `ALLOCATE_STATE;
+ end
+ default: next_cache_state <= `IDLE_STATE;
+ endcase
+ end
+
+ always@(posedge clk) begin
+ if (reset) begin
+ for(i = 0; i < `NUM_CACHE_LINES; i=i+1) begin
+ cacheValidBits[i] <= 1'b0;
+ cacheDirtyBits[i] <= 1'b0;
+ end
+ end else begin
+ if (sram_we_port || (cache_state == `ALLOCATE_STATE && mem_ready_in) ) begin
+ cacheTag[index] <= (cache_state == `ALLOCATE_STATE) ? tag : sram_addr_in_port;
+ cacheData[index] <= (cache_state == `ALLOCATE_STATE) ? mem_data_in : sram_data_in_port;
+ end
+ if (sram_we_valid || (cache_state == `ALLOCATE_STATE && mem_ready_in) ) begin
+ cacheValidBits[index] <= (cache_state == `ALLOCATE_STATE) ? 1'b1 : sram_value_valid;
+ end
+ if (sram_we_dirty || (cache_state == `ALLOCATE_STATE && mem_ready_in)) begin
+ cacheDirtyBits[index] <= (cache_state == `ALLOCATE_STATE) ? 1'b0 : sram_value_dirty;
+ end
+
+ end
+ end
+
+ assign sram_addr_out_port = (cache_state == `ALLOCATE_STATE && mem_ready_in) ? tag : cacheTag[index];
+ assign sram_data_out_port = (cache_state == `ALLOCATE_STATE && mem_ready_in) ? mem_data_in : cacheData[index];
+
+ assign sram_we_port = ((hit_out && write_enable_in) || (cache_state == `ALLOCATE_STATE && mem_ready_in)) ? 1'b1 : 1'b0;
+ assign sram_we_dirty = ((hit_out && write_enable_in) || (cache_state == `ALLOCATE_STATE && mem_ready_in)) ? 1'b1 : 1'b0;
+ assign sram_we_valid = ((hit_out && write_enable_in) || (cache_state == `ALLOCATE_STATE && mem_ready_in)) ? 1'b1 : 1'b0;
+ assign sram_value_valid = 1'b1;
+ assign sram_value_dirty = (cacheDirtyBits[index] | write_enable_in);
+
+ always@(*) begin
+ if (reset) begin
+ mem_data_out <= 128'b0;
+ req_mem <= 0;
+ mem_we_out <= 0;
+ mem_addr_out <= 20'b0;
+ sram_data_in_port <= 128'b0;
+ sram_addr_in_port <= 'b0;
+ end else begin
+ case(cache_state)
+ `IDLE_STATE: begin
+ mem_data_out <= 128'b0;
+ mem_addr_out <= 20'b0;
+ req_mem <= 0;
+ mem_we_out <= 0;
+ if (write_enable_in) begin
+ sram_addr_in_port <= tag;
+ if (is_byte) begin
+ case(offset)
+ 4'b0000:sram_data_in_port <= {sram_data_out_port[127:8], data_in[7:0]};
+ 4'b0001:sram_data_in_port <= {sram_data_out_port[127:16], data_in[7:0], sram_data_out_port[7:0]};
+ 4'b0010:sram_data_in_port <= {sram_data_out_port[127:24], data_in[7:0], sram_data_out_port[15:0]};
+ 4'b0011:sram_data_in_port <= {sram_data_out_port[127:32], data_in[7:0], sram_data_out_port[23:0]};
+ 4'b0100:sram_data_in_port <= {sram_data_out_port[127:40], data_in[7:0], sram_data_out_port[31:0]};
+ 4'b0101:sram_data_in_port <= {sram_data_out_port[127:48], data_in[7:0], sram_data_out_port[39:0]};
+ 4'b0110:sram_data_in_port <= {sram_data_out_port[127:56], data_in[7:0], sram_data_out_port[47:0]};
+ 4'b0111:sram_data_in_port <= {sram_data_out_port[127:64], data_in[7:0], sram_data_out_port[55:0]};
+ 4'b1000:sram_data_in_port <= {sram_data_out_port[127:72], data_in[7:0], sram_data_out_port[63:0]};
+ 4'b1001:sram_data_in_port <= {sram_data_out_port[127:80], data_in[7:0], sram_data_out_port[71:0]};
+ 4'b1010:sram_data_in_port <= {sram_data_out_port[127:88], data_in[7:0], sram_data_out_port[79:0]};
+ 4'b1011:sram_data_in_port <= {sram_data_out_port[127:96], data_in[7:0], sram_data_out_port[87:0]};
+ 4'b1100:sram_data_in_port <= {sram_data_out_port[127:104], data_in[7:0], sram_data_out_port[95:0]};
+ 4'b1101:sram_data_in_port <= {sram_data_out_port[127:112], data_in[7:0], sram_data_out_port[103:0]};
+ 4'b1110:sram_data_in_port <= {sram_data_out_port[127:120], data_in[7:0], sram_data_out_port[111:0]};
+ 4'b1111:sram_data_in_port <= {data_in[7:0], sram_data_out_port[119:0]};
+ default: sram_data_in_port <= 128'b0;
+ endcase
+ end else begin
+ case(offset)
+ 4'b0000:sram_data_in_port <= {sram_data_out_port[127:32], data_in};
+ 4'b0100:sram_data_in_port <= {sram_data_out_port[127:64], data_in, sram_data_out_port[31:0]};
+ 4'b1000:sram_data_in_port <= {sram_data_out_port[127:96], data_in, sram_data_out_port[63:0]};
+ 4'b1100:sram_data_in_port <= {data_in, sram_data_out_port[95:0]};
+ default: sram_data_in_port <= 128'b0;
+ endcase
+ end
+ end else begin
+ sram_addr_in_port <= 'b0;
+ sram_data_in_port <= 128'b0;
+ end
+ end
+ `ALLOCATE_STATE: begin
+ mem_data_out <= 128'b0;
+ mem_addr_out <= {auxAL[17:2],2'b00};
+ mem_we_out <= 1'b0;
+ if (mem_ready_in) begin
+ req_mem <= 1'b0;
+ sram_data_in_port <= mem_data_in;
+ sram_addr_in_port <= tag;
+ end else begin
+ req_mem <= 1'b1;
+ sram_data_in_port <= 128'b0;
+ sram_addr_in_port <= 'b0;
+ end
+ end
+ `WRITE_BACK_STATE: begin
+ req_mem <= 1'b1;
+ mem_we_out <= 1'b1;
+ mem_addr_out <= auxWB[19:0];
+ mem_data_out <= sram_data_out_port;
+ sram_data_in_port <= 128'b0;
+ sram_addr_in_port <= 'b0;
+ end
+ default: begin
+ sram_addr_in_port <= 'b0;
+ sram_data_in_port <= 128'b0;
+ mem_data_out <= 128'b0;
+ mem_addr_out <= 20'b0;
+ end
+ endcase
+ end
+ end
+
+ //BIT SELECTOR
+ always@(*) begin
+ if (read_enable_in) begin
+ if (is_byte) begin
+ read_data_out <= {24'b0, sram_data_out_port[offset*8+:8]};
+ end else begin
+ read_data_out <= sram_data_out_port[offset*8+:32];
+ end
+ end else begin
+ read_data_out <= 0;
+ end
+ end
+
+ always@(*) begin : hit_cache_logic
+ if (read_enable_in | write_enable_in) begin
+ if (cache_state != `IDLE_STATE) begin
+ hit_out <= 1'b0;
+ end else begin
+ if(write_enable_in) begin
+ hit_out <= (sram_addr_out_port == tag) && cacheValidBits[index] && is_hit_tlb;
+ end else begin
+ hit_out <= (sram_addr_out_port == tag) && cacheValidBits[index] && is_hit_tlb;
+ end
+
+ end
+ end
+ else hit_out <= 1;
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/controlunit.v b/verilog/rtl/elpis/controlunit.v
new file mode 100644
index 0000000..1b4bad5
--- /dev/null
+++ b/verilog/rtl/elpis/controlunit.v
@@ -0,0 +1,96 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module controlunit(
+ input rst,
+ input[31:0] ir,
+ output reg[3:0] op_alu,
+ output reg wrd_reg,
+ output reg[4:0] addr_d,
+ output reg rb_immed,
+ output reg[31:0] imm,
+ output reg mem_to_reg,
+ output reg wrd_mem,
+ output reg[2:0] branch_code,
+ output reg is_a_jump,
+ output reg is_byte,
+ output reg[1:0] is_mov,
+ output reg[31:0] is_illegal,
+ output reg is_tlbwrite,
+ output reg is_iret,
+ output reg is_ecall,
+ output reg[6:0] io_code
+);
+
+ wire[3:0] alu_op;
+ wire reg_we;
+ wire[6:0] io_code_wire;
+ wire[4:0] dest;
+ wire rb_imm;
+ wire[31:0] immed;
+ wire MemToReg;
+ wire mem_we;
+ wire[2:0] branch_code_wire;
+ wire is_a_jump_wire;
+ wire is_a_byte;
+ wire[1:0] is_a_mov;
+ wire is_instr_illegal;
+ wire is_a_tlbwrite, is_an_iret, is_a_mul, is_a_ecall;
+
+ decoder decoder(
+ .rst(rst),
+ .instr(ir),
+ .op_alu(alu_op),
+ .wrd_reg(reg_we),
+ .addr_d(dest),
+ .rb_immed(rb_imm),
+ .imm(immed),
+ .mem_to_reg(MemToReg),
+ .wrd_mem(mem_we),
+ .branch_code(branch_code_wire),
+ .is_a_jump(is_a_jump_wire),
+ .is_byte(is_a_byte),
+ .is_mov(is_a_mov),
+ .is_illegal(is_instr_illegal),
+ .is_tlbwrite(is_a_tlbwrite),
+ .is_iret(is_an_iret),
+ .is_ecall(is_a_ecall),
+ .io_code(io_code_wire)
+ );
+
+ always@(*) begin
+ op_alu = alu_op;
+ wrd_reg = reg_we;
+ addr_d = dest;
+ rb_immed = rb_imm;
+ imm = immed;
+ mem_to_reg = MemToReg;
+ wrd_mem = mem_we;
+ branch_code = branch_code_wire;
+ is_a_jump = is_a_jump_wire;
+ is_byte = is_a_byte;
+ is_mov = is_a_mov;
+ is_illegal = (is_instr_illegal) ? `EXC_ILLEGAL_INST : 'b0;
+ is_tlbwrite = is_a_tlbwrite;
+ is_iret = is_an_iret;
+ is_ecall = is_a_ecall;
+ io_code = io_code_wire;
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/core.v b/verilog/rtl/elpis/core.v
new file mode 100644
index 0000000..c3b9cee
--- /dev/null
+++ b/verilog/rtl/elpis/core.v
@@ -0,0 +1,181 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module core
+#(parameter CORE_ID = 0)
+(
+ input clk,
+ input rst,
+ input[31:0] read_interactive_value,
+ input read_interactive_ready,
+ output[31:0] hex_out,
+ output read_interactive_req,
+ output hex_req,
+ input is_print_done,
+ // LLC ports
+ output is_memory_we,
+ output[19:0] mem_addr_out,
+ output[127:0] mem_data_out,
+ output is_mem_req_reset,
+ input[127:0] data_from_mem,
+ input is_mem_ready,
+ output is_mem_req
+);
+
+ wire[31:0] search_addr_if, search_addr_mem;
+ wire[127:0] read_data_mem, dcache_mem_data_in;
+ wire[31:0] write_data;
+
+ wire wrd_mem, is_hit_icache, is_hit_dcache;
+ wire[19:0] icache_mem_addr, dcache_mem_addr;
+ wire[127:0] icache_mem_data, dcache_mem_data, read_data_if;
+ wire[31:0] dcache_read_data, read_instr;
+ wire re_dcache, is_byte_acc, mem_we_dcache, mem_we_icache;
+ wire icache_req_mem, dcache_req_mem, is_icache_ready, is_dcache_ready;
+ wire need_reset_mem_req;
+ wire privilege_mode, is_tlbwrite;
+ wire[31:0] type_exception;
+ wire[31:0] current_address_rm2_wire;
+ wire[19:0] physical_addr_write;
+
+ wire is_itlb_we = (is_tlbwrite && (type_exception == `EXC_ITLB_MISS)) ? 1'b1: 1'b0;
+ wire is_itlb_re = (!is_itlb_we);
+ wire is_dtlb_we = (is_tlbwrite && (type_exception == `EXC_DTLB_MISS)) ? 1'b1: 1'b0;
+ wire is_dtlb_re = (!is_dtlb_we && (re_dcache || wrd_mem));
+ wire hit_itlb, exc_protected_page_itlb, hit_dtlb, exc_protected_page_dtlb;
+
+ // arbiter
+ arbiter arbiter(
+ .clk(clk),
+ .reset(rst),
+ .mem_addr(mem_addr_out),
+ .dcache_to_mem_data_in(dcache_mem_data_in),
+ .dcache_to_mem_data_out(mem_data_out),
+ .mem_to_icache_data(read_data_if),
+ .mem_to_dcache_data(read_data_mem),
+ .data_from_mem(data_from_mem),
+ .dcache_we(mem_we_dcache),
+ .mem_we(is_memory_we),
+ .icache_request(icache_req_mem),
+ .dcache_request(dcache_req_mem),
+ .mem_ready(is_mem_ready),
+ .is_icache_ready(is_icache_ready),
+ .is_dcache_ready(is_dcache_ready),
+ .reset_mem_req(need_reset_mem_req),
+ .hit_itlb_in(hit_itlb),
+ .hit_dtlb_in(hit_dtlb),
+ .itlb_physical_addr_in(icache_mem_addr),
+ .dtlb_physical_addr_in(dcache_mem_addr),
+ .dcache_re(re_dcache),
+ .is_mem_req(is_mem_req)
+ );
+
+ assign is_mem_req_reset = need_reset_mem_req;
+
+ // instruction cache
+ cache #(.CORE_ID(CORE_ID), .CACHE_TYPE(`CACHE_TYPE_ICACHE)) icache(
+ .clk(clk),
+ .reset(rst),
+ .address_in(search_addr_if),
+ .data_in('b0),
+ .write_enable_in(1'b0),
+ .read_enable_in(1'b1),
+ .reset_mem_req(need_reset_mem_req),
+ .mem_ready_in(is_icache_ready),
+ .mem_data_in(read_data_if),
+ .is_byte(1'b0),
+ .privilege_mode(privilege_mode),
+ .tlb_we(is_itlb_we),
+ .tlb_re(is_itlb_re),
+ .physical_addr_in(write_data[19:0]),
+ .read_data_out(read_instr),
+ .hit_out(is_hit_icache),
+ .mem_addr_out(icache_mem_addr),
+ .mem_data_out(icache_mem_data),
+ .req_mem(icache_req_mem),
+ .hit_tlb(hit_itlb),
+ .exc_protected_page_tlb(exc_protected_page_itlb),
+ .virtual_addr_write_tlb_in(current_address_rm2_wire),
+ .physical_addr_write_tlb_in(physical_addr_write),
+ .mem_we_out(mem_we_icache)
+ );
+
+ // data cache
+ cache #(.CORE_ID(CORE_ID), .CACHE_TYPE(`CACHE_TYPE_DCACHE)) dcache(
+ .clk(clk),
+ .reset(rst),
+ .address_in(search_addr_mem),
+ .data_in(write_data),
+ .write_enable_in(wrd_mem),
+ .read_enable_in(re_dcache),
+ .reset_mem_req(need_reset_mem_req),
+ .mem_ready_in(is_dcache_ready),
+ .mem_data_in(read_data_mem),
+ .is_byte(is_byte_acc),
+ .privilege_mode(privilege_mode),
+ .tlb_we(is_dtlb_we),
+ .tlb_re(is_dtlb_re),
+ .physical_addr_in(write_data[19:0]),
+ .read_data_out(dcache_read_data),
+ .hit_out(is_hit_dcache),
+ .mem_addr_out(dcache_mem_addr),
+ .mem_data_out(dcache_mem_data_in),
+ .req_mem(dcache_req_mem),
+ .hit_tlb(hit_dtlb),
+ .exc_protected_page_tlb(exc_protected_page_dtlb),
+ .virtual_addr_write_tlb_in(current_address_rm2_wire),
+ .physical_addr_write_tlb_in(physical_addr_write),
+ .mem_we_out(mem_we_dcache)
+ );
+
+ // datapath module
+ datapath #(.CORE_ID(CORE_ID)) datapath(
+ .clk(clk),
+ .reset(rst),
+ .mem_data_rd_f(read_instr),
+ .mem_data_rd_m(dcache_read_data),
+ .mem_addr_f(search_addr_if),
+ .mem_addr_m(search_addr_mem),
+ .mem_data_wr(write_data),
+ .mem_wrd(wrd_mem),
+ .hit_icache(is_hit_icache),
+ .hit_dcache(is_hit_dcache),
+ .hit_itlb(hit_itlb),
+ .hit_dtlb(hit_dtlb),
+ .read_interactive_value(read_interactive_value),
+ .is_read_interactive_enabled(read_interactive_ready),
+ .dcache_re(re_dcache),
+ .mem_isbyte(is_byte_acc),
+ .reset_mem_req(need_reset_mem_req),
+ .privilege_mode(privilege_mode),
+ .is_tlbwrite(is_tlbwrite),
+ .exception_type(type_exception),
+ .current_address_rm2(current_address_rm2_wire),
+ .mem_physical_tlb_addr_out(physical_addr_write),
+ .print_output(hex_out),
+ .print_hex_enable(hex_req),
+ .read_interactive_req(read_interactive_req),
+ .is_print_done(is_print_done)
+ );
+
+ initial begin
+ $display("Hello from Elpis!");
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/datapath.v b/verilog/rtl/elpis/datapath.v
new file mode 100644
index 0000000..d63e7fd
--- /dev/null
+++ b/verilog/rtl/elpis/datapath.v
@@ -0,0 +1,475 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module datapath #(parameter CORE_ID=0) (
+ input clk,
+ input reset,
+ input[31:0] mem_data_rd_f,
+ input[31:0] mem_data_rd_m,
+ input hit_icache,
+ input hit_dcache,
+ input hit_itlb,
+ input hit_dtlb,
+ input[31:0] read_interactive_value,
+ input is_read_interactive_enabled,
+ output[31:0] mem_addr_f,
+ output[31:0] mem_addr_m,
+ output[31:0] mem_data_wr,
+ output mem_wrd,
+ output dcache_re,
+ output mem_isbyte,
+ output reset_mem_req,
+ output privilege_mode, // PSW/rm3
+ output is_tlbwrite,
+ output[31:0] current_address_rm2,
+ output[19:0] mem_physical_tlb_addr_out,
+ output[31:0] exception_type,
+ output[31:0] print_output,
+ output print_hex_enable,
+ output read_interactive_req,
+ input is_print_done
+);
+ wire stall_icache, stall_dcache;
+ wire[31:0] global_rm0; // PC of current exception (if exists)
+
+ wire[31:0] branch_or_jump_address_wire;
+ wire is_branch_or_jump_taken_wire, is_iret_wire;
+ reg is_iret_ff;
+
+ reg flush;
+ reg boot;
+
+ wire[3:0] id_alu_op;
+ wire id_reg_we;
+ wire[4:0] id_reg_src1_addr, id_reg_src2_addr, id_reg_dest_addr;
+ wire[31:0] id_reg_a_content, id_reg_b_content;
+ wire[2:0] id_branch_code;
+ wire id_is_a_jump;
+ wire id_regb_immed;
+ wire[31:0] id_immediate;
+ wire id_mem_to_reg;
+ wire id_mem_we;
+ wire id_stall;
+ wire id_is_byte, id_is_ecall, id_is_iret;
+ wire[1:0] id_is_mov;
+ wire[6:0] id_io_code;
+ wire[31:0] id_is_illegal;
+ wire[31:0] id_reg_rm, id_rm2, id_rm1, id_rm0, id_current_rm1, id_current_rm2, id_current_rm4;
+ wire id_is_tlbwrite, is_iret, id_hit_itlb;
+ wire[31:0] id_reg_dest_value;
+
+ wire[31:0] ex_reg_a, ex_reg_b;
+ wire[31:0] ex_res_alu, ex_res_mul;
+ wire[31:0] ex_reg_opX, ex_reg_opY;
+ wire[3:0] ex_alu_op;
+ wire[4:0] ex_reg_addr_dest;
+ wire ex_z;
+ wire ex_reg_write_enable;
+ wire ex_mem_to_reg;
+ wire ex_mem_we;
+ wire ex_is_branch_taken;
+ wire[31:0] ex_immed;
+ wire ex_regb_immed;
+ wire[31:0] ex_pc;
+ wire[2:0] ex_branch_code;
+ wire ex_is_a_jump;
+ wire[4:0] ex_reg_a_addr, ex_reg_b_addr;
+ wire[31:0] ex_exc_code;
+ wire[31:0] ex_rm0, ex_rm1, ex_rm2;
+ wire ex_is_byte, ex_pend_haz, ex_is_ecall;
+ wire[1:0] ex_is_mov;
+ wire[6:0] ex_io_code;
+ wire[31:0] ex_reg_rm, ex_reg_rm3, ex_current_rm1, ex_current_rm2, ex_current_rm4, ex_physical_tlb_addr;
+ wire ex_is_tlbwrite, ex_is_iret, ex_hit_itlb;
+
+ wire mem_z;
+ wire[31:0] mem_branch_or_jump_address;
+ wire mem_is_branch_taken;
+ wire mem_is_a_jump;
+ wire mem_is_branch_or_jump_taken;
+ wire mem_reg_write_enable;
+ wire[4:0] mem_reg_addr_dest;
+ wire[31:0] mem_reg_data;
+ wire mem_mem_to_reg;
+ wire mem_mem_we;
+ wire[31:0] mem_reg_b;
+ wire[31:0] mem_rm0, mem_rm1, mem_rm2, mem_rm3, mem_current_rm1, mem_current_rm2, mem_current_rm4, mem_physical_tlb_addr;
+ wire mem_is_byte;
+ wire[1:0] mem_is_mov;
+ wire[4:0] mem_reg_b_addr;
+ wire[6:0] mem_io_code;
+ wire mem_is_iret, mem_hit_itlb, mem_is_ecall, mem_is_tlbwrite;
+ wire[31:0] mem_pc;
+ wire mem_stall_read_sw;
+
+ wire[31:0] wb_alu_res;
+ wire[31:0] wb_current_rm4;
+ wire[4:0] wb_addr_d, wb_addr_d_from_mem, wb_addr_d_from_m5;
+ wire wb_reg_write_enable, wb_reg_write_enable_from_mem, wb_reg_write_enable_from_m5;
+ wire[31:0] wb_data_to_reg, wb_data_to_reg_from_mem, wb_data_to_reg_from_m5;
+ wire[31:0] wb_rm0, wb_rm1, wb_rm2;
+ wire wb_is_iret, wb_hit_dtlb, wb_hit_itlb;
+ wire[1:0] wb_is_mov;
+ wire[6:0] wb_io_code;
+ wire[31:0] wb_pc;
+ wire[31:0] wb_read_interactive_value;
+ wire wb_read_interactive_enable;
+
+ // SB
+ wire was_stall_dcache, sb_data_to_cache_aux_in, sb_data_to_cache_aux_out, sb_hit_aux_in,sb_hit_aux_out, sb_is_byte_aux_out, sb_is_byte_aux_in;
+ wire[31:0] sb_addr_out_aux_in, sb_data_out_aux_in, sb_addr_out_aux_out, sb_data_out_aux_out;
+ wire sb_hit, sb_full, sb_empty, sb_is_byte, sb_continue_drain_out, sb_data_to_cache_out, sb_drain;
+
+ wire wb_or_hf_reg_write_enable;
+ wire[31:0] wb_or_hf_data_to_reg;
+ wire[4:0] wb_or_hf_addr_to_reg;
+ wire[31:0] wb_or_hf_rm0, wb_or_hf_rm1, wb_or_hf_rm2;
+ wire id_is_flush, ex_is_flush, mem_is_flush, wb_is_flush;
+
+ wire is_exception, is_exception_reached;
+ reg is_exception_pending;
+ reg f_PSW;
+ wire id_PSW, ex_PSW, mem_PSW, wb_PSW;
+ wire stall_print;
+
+ // DEBUG
+ // Number of current cycle
+ reg[31:0] cycleNumber;
+ initial cycleNumber = 0;
+ always@(posedge clk) cycleNumber = cycleNumber + 1'b1;
+
+
+ // IF stage
+
+ reg[31:0] pc;
+ wire[31:0] pc_next, id_pc, id_inst, f_pc;
+
+ always@(reset or is_branch_or_jump_taken_wire)
+ begin
+ if(reset) begin
+ flush <= 1'b1;
+ end
+ else begin
+ flush <= is_branch_or_jump_taken_wire;
+ end
+ end
+
+ assign stall_icache = !hit_icache;
+
+ // Trigger flush memory request in case of exception
+ assign is_exception = is_exception_pending || is_exception_reached;
+ assign reset_mem_req = is_exception;
+
+ reg[31:0] branch_or_jump_address_ff;
+ reg is_branch_or_jump_taken_ff;
+ reg was_a_stall;
+
+ assign branch_or_jump_address_wire = was_a_stall ? ((is_iret_wire) ? global_rm0 : branch_or_jump_address_ff) : ((is_iret_wire) ? global_rm0 : mem_branch_or_jump_address);
+ assign is_branch_or_jump_taken_wire = was_a_stall ? is_branch_or_jump_taken_ff : mem_is_branch_or_jump_taken;
+ assign is_iret_wire = was_a_stall ? is_iret_ff : mem_is_iret;
+
+ always@(posedge clk) begin
+ if (reset) begin
+ pc <= `PC_INITIAL;
+ was_a_stall <= 1'b0;
+ is_branch_or_jump_taken_ff <= 1'b0;
+ f_PSW <= 1'b1;
+ is_iret_ff <= 1'b0;
+ boot <= 1'b1;
+ is_exception_pending <= 1'b0;
+ end else if (is_exception | boot) begin
+ pc <= `PC_EXCEPTIONS;
+ f_PSW <= 1'b1;
+ boot <= 1'b0;
+ is_exception_pending <= 1'b0;
+ end else if ((id_stall | stall_icache | stall_dcache | mem_stall_read_sw | stall_print)) begin
+ pc <= pc;
+ was_a_stall <= 1'b1;
+ f_PSW <= f_PSW;
+ if(mem_is_branch_or_jump_taken) begin
+ branch_or_jump_address_ff <= is_branch_or_jump_taken_ff ? branch_or_jump_address_ff : mem_branch_or_jump_address;
+ is_branch_or_jump_taken_ff <= mem_is_branch_or_jump_taken;
+ is_iret_ff <= mem_is_iret;
+ end
+ is_exception_pending <= is_exception_pending || is_exception_reached;
+ end else begin
+ pc <= (is_branch_or_jump_taken_wire == 1'b0) ? pc_next : branch_or_jump_address_wire;
+ was_a_stall <= 1'b0;
+ is_branch_or_jump_taken_ff <= 1'b0;
+ f_PSW <= is_iret_wire ? 1'b0 : f_PSW;
+ is_iret_ff <= 1'b0;
+ is_exception_pending <= is_exception_pending || is_exception_reached;
+ end
+ end
+
+ assign pc_next = pc+4;
+ assign mem_addr_f = pc;
+ wire[31:0] f_inst = mem_data_rd_f;
+
+ wire[31:0] f_exc_code_in = (!hit_itlb && !privilege_mode) ? `EXC_ITLB_MISS : 0;
+
+ IF_ID IF_ID(.clk(clk), .stall_icache(stall_icache), .stall(id_stall | stall_dcache | (sb_drain && sb_full) | stall_print), .flush(flush | is_exception | mem_stall_read_sw), .pc_in(pc),
+ .psw_in(f_PSW), .is_flush_in(1'b0),
+ .inst_in(f_inst), .is_hit_itlb_in(hit_itlb), .exc_code_in(f_exc_code_in), .pc_out(id_pc), .inst_out(id_inst), .is_hit_itlb_out(id_hit_itlb), .rm2_out(id_rm2),
+ .psw_out(id_PSW), .rm1_out(id_rm1), .rm0_out(id_rm0), .is_flush_out(id_is_flush));
+
+
+ // ID stage
+
+ assign id_reg_src1_addr = id_inst[19:15];
+ assign id_reg_src2_addr = id_inst[24:20];
+
+ hazardDetectionUnit hazardDetectionUnit(
+ .ex_reg_dest_addr_in(ex_reg_addr_dest),
+ .ex_mem_read_in(ex_mem_to_reg),
+ .id_reg_a_addr_in(id_reg_src1_addr),
+ .id_reg_b_addr_in(id_reg_src2_addr),
+ .stall_out(id_stall)
+ );
+
+ controlunit controlunit(
+ .rst(reset),
+ .ir(id_inst),
+ .op_alu(id_alu_op),
+ .wrd_reg(id_reg_we),
+ .addr_d(id_reg_dest_addr),
+ .rb_immed(id_regb_immed),
+ .imm(id_immediate),
+ .mem_to_reg(id_mem_to_reg),
+ .wrd_mem(id_mem_we),
+ .branch_code(id_branch_code),
+ .is_a_jump(id_is_a_jump),
+ .is_byte(id_is_byte),
+ .is_mov(id_is_mov),
+ .is_illegal(id_is_illegal),
+ .is_tlbwrite(id_is_tlbwrite),
+ .is_iret(id_is_iret),
+ .is_ecall(id_is_ecall),
+ .io_code(id_io_code)
+ );
+
+ regfile regfile(
+ .clk(clk),
+ .reset(reset),
+ .wrd(wb_or_hf_reg_write_enable),
+ .d(wb_or_hf_data_to_reg),
+ .addr_a(id_reg_src1_addr),
+ .addr_b(id_reg_src2_addr),
+ .addr_d(wb_or_hf_addr_to_reg),
+ .a(id_reg_a_content),
+ .b(id_reg_b_content),
+ .dest_read(id_reg_dest_addr),
+ .dest_value(id_reg_dest_value)
+ );
+
+ specialreg specialreg(
+ .clk(clk),
+ .reset(reset),
+ .in_rm0(wb_or_hf_rm0),
+ .in_rm1(wb_or_hf_rm1),
+ .in_rm2(is_branch_or_jump_taken_wire ? 0 : wb_or_hf_rm2),
+ .in_other_rm(wb_data_to_reg),
+ .sel(id_reg_src2_addr[2:0]),
+ .we(wb_is_mov == `MOV_REGULAR_TO_RM || wb_read_interactive_enable),
+ .out_rm0(global_rm0),
+ .out_rm1(id_current_rm1),
+ .out_rm2(id_current_rm2),
+ .out_rm(id_reg_rm),
+ .out_rm4(id_current_rm4)
+ );
+
+
+ ID_EX ID_EX(.clk(clk), .flush(flush | is_exception), .haz(id_stall | ex_pend_haz), .stall(stall_dcache | (sb_drain && sb_full) | mem_stall_read_sw | stall_print), .reg_a_in(id_reg_a_content), .reg_b_in(id_reg_b_content), .alu_op_in(id_alu_op),
+ .reg_addr_dest_in(id_reg_dest_addr), .reg_write_enable_in(id_reg_we), .rb_imm_in(id_regb_immed), .immed_in(id_immediate), .io_code_in(id_io_code),
+ .mem_to_reg_in(id_mem_to_reg), .mem_we_in(id_mem_we), .pc_in(id_pc), .branch_code_in(id_branch_code), .is_flush_in(1'b0),
+ .is_a_jump_in(id_is_a_jump), .reg_a_addr_in(id_reg_src1_addr), .reg_b_addr_in(id_reg_src2_addr), .is_byte_in(id_is_byte),
+ .is_mov_in(id_is_mov), .reg_rm_in(id_reg_rm), .psw_in(id_PSW), .exc_code_in(id_is_illegal), .is_tlbwrite_in(id_is_tlbwrite), .is_iret_in(id_is_iret), .is_ecall_in(id_is_ecall),
+ .is_hit_itlb_in(id_hit_itlb), .rm2_in(id_rm2), .rm1_in(id_rm1), .rm0_in(id_rm0), .stored_rm1_in(id_current_rm1), .stored_rm2_in(id_current_rm2), .stored_rm4_in(id_current_rm4), .fw_reg_a_in(ex_reg_opX), .fw_reg_b_in(ex_reg_opY),
+ .reg_a_out(ex_reg_a), .reg_b_out(ex_reg_b), .alu_op_out(ex_alu_op), .reg_addr_dest_out(ex_reg_addr_dest), .reg_write_enable_out(ex_reg_write_enable),
+ .rb_imm_out(ex_regb_immed), .immed_out(ex_immed), .mem_to_reg_out(ex_mem_to_reg), .mem_we_out(ex_mem_we), .pc_out(ex_pc), .io_code_out(ex_io_code),
+ .branch_code_out(ex_branch_code), .is_a_jump_out(ex_is_a_jump), .reg_a_addr_out(ex_reg_a_addr), .reg_b_addr_out(ex_reg_b_addr), .is_flush_out(ex_is_flush),
+ .is_byte_out(ex_is_byte), .is_mov_out(ex_is_mov), .reg_rm_out(ex_reg_rm), .psw_out(ex_PSW), .stored_rm1_out(ex_current_rm1), .stored_rm2_out(ex_current_rm2), .stored_rm4_out(ex_current_rm4),
+ .is_tlbwrite_out(ex_is_tlbwrite), .is_iret_out(ex_is_iret), .is_hit_itlb_out(ex_hit_itlb), .rm2_out(ex_rm2), .rm1_out(ex_rm1), .rm0_out(ex_rm0), .pending_haz(ex_pend_haz), .is_ecall_out(ex_is_ecall));
+
+
+ // EX stage
+
+ wire[1:0] ex_forward_x, ex_forward_y;
+
+ forwardingunit forwardingunit(
+ .ex_reg_a_in(ex_reg_a_addr),
+ .ex_reg_b_in(ex_reg_b_addr),
+ .mem_reg_d_in(mem_reg_addr_dest),
+ .wb_reg_d_in(wb_addr_d),
+ .mem_reg_we_in(mem_reg_write_enable),
+ .wb_reg_we_in(wb_reg_write_enable),
+ .forward_x(ex_forward_x),
+ .forward_y(ex_forward_y)
+ );
+
+ mux3_1 muxOpX(ex_forward_x, ex_reg_a, wb_data_to_reg, mem_reg_data, ex_reg_opX);
+ mux3_1 muxOpY(ex_forward_y, ex_reg_b, wb_data_to_reg, mem_reg_data, ex_reg_opY);
+
+ // Bypass ALU-ALU to ST
+ wire[31:0] ex_reg_b_fw;
+
+ wire[1:0] forwarding_reg_b;
+
+ forwardingunit_st forwardingunit_st(
+ .mem_we(ex_mem_we),
+ .ex_reg_b_in(ex_reg_b_addr),
+ .mem_reg_b_in(mem_reg_b_addr),
+ .forwarding_y(ex_forward_y),
+ .forwarding_regb(forwarding_reg_b)
+ );
+
+ mux3_1 muxRegB(forwarding_reg_b, ex_reg_b, ex_reg_opY, mem_reg_b, ex_reg_b_fw);
+
+ wire[31:0] ex_opX, ex_opX_pre;
+ wire[31:0] ex_opY, ex_opY_pre;
+
+ assign ex_opX_pre = (ex_branch_code != `FUNCT3_BRANCH_NO) ? ex_pc : ex_reg_opX;
+ assign ex_opY_pre = (ex_regb_immed > 0) ? ex_immed : ex_reg_opY;
+
+ assign ex_opX = (ex_is_mov == 2'b01) ? ex_reg_rm : ( (ex_is_mov == 2'b10) ? 32'b0 : ex_opX_pre);
+ assign ex_opY = (ex_is_mov == 2'b01) ? 32'b0 : ex_opY_pre;
+
+ branchComparer branchComparer(
+ .branch_code_in(ex_branch_code),
+ .reg_a_content_in(ex_reg_opX),
+ .reg_b_content_in(ex_reg_opY),
+ .is_branch_taken_out(ex_is_branch_taken)
+ );
+
+ alu alu(
+ .x(ex_opX),
+ .y(ex_opY),
+ .op(ex_alu_op),
+ .w(ex_res_alu),
+ .z(ex_z),
+ .exception_code(ex_exc_code)
+ );
+
+ TLBAddressAdder #(.CORE_ID(CORE_ID)) TLBAddressAdder(
+ .address_in(ex_current_rm1),
+ .exception_code_in(ex_current_rm2),
+ .address_out(ex_physical_tlb_addr)
+ );
+
+
+ EX_MEM EX_MEM(.clk(clk), .flush(flush | is_exception), .stall(stall_dcache | (sb_drain && sb_full) | mem_stall_read_sw | stall_print), .reg_write_enable_in(ex_reg_write_enable), .reg_dest_in(ex_reg_addr_dest),
+ .reg_data_in(ex_res_alu), .mem_to_reg_in(ex_mem_to_reg), .mem_we_in(ex_mem_we), .reg_b_in(ex_reg_b_fw), .pc_in(ex_pc), .is_ecall_in(ex_is_ecall), .io_code_in(ex_io_code),
+ .pc_candidate_address_in(ex_res_alu), .z_in(ex_z), .is_branch_taken_in(ex_is_branch_taken), .is_a_jump_in(ex_is_a_jump), .physical_tlb_addr_in(ex_physical_tlb_addr), .is_mov_in(ex_is_mov),
+ .exc_code_in(ex_exc_code), .rm0_in(ex_rm0), .rm1_in(ex_rm1), .rm2_in(ex_rm2), .psw_in(ex_PSW), .is_byte_in(ex_is_byte), .stored_rm1_in(ex_current_rm1), .stored_rm2_in(ex_current_rm2), .stored_rm4_in(ex_current_rm4),
+ .reg_b_addr_in(ex_reg_b_addr), .sb_addr_out_in(sb_addr_out_aux_in), .sb_is_byte_in(sb_is_byte_aux_in), .sb_data_out_in(sb_data_out_aux_in), .sb_data_to_cache_in(sb_data_to_cache_aux_in),
+ .sb_hit_in(sb_hit_aux_in), .was_stall_dcache_in(stall_dcache), .is_tlbwrite_in(ex_is_tlbwrite), .is_iret_in(ex_is_iret), .is_hit_itlb_in(ex_hit_itlb), .is_flush_in(1'b0),
+ .reg_write_enable_out(mem_reg_write_enable), .reg_dest_out(mem_reg_addr_dest), .reg_data_out(mem_reg_data), .mem_to_reg_out(mem_mem_to_reg), .is_mov_out(mem_is_mov),
+ .mem_we_out(mem_mem_we), .reg_b_out(mem_reg_b), .pc_candidate_address_out(mem_branch_or_jump_address), .z_out(mem_z), .is_branch_taken_out(mem_is_branch_taken), .is_flush_out(mem_is_flush), .io_code_out(mem_io_code),
+ .is_a_jump_out(mem_is_a_jump), .rm0_out(mem_rm0), .rm1_out(mem_rm1), .rm2_out(mem_rm2), .psw_out(mem_PSW), .is_byte_out(mem_is_byte), .sb_is_byte_out(sb_is_byte_aux_out), .stored_rm1_out(mem_current_rm1), .stored_rm2_out(mem_current_rm2),
+ .reg_b_addr_out(mem_reg_b_addr), .sb_addr_out_out(sb_addr_out_aux_out), .sb_data_out_out(sb_data_out_aux_out), .sb_data_to_cache_out(sb_data_to_cache_aux_out), .physical_tlb_addr_out(mem_physical_tlb_addr), .stored_rm4_out(mem_current_rm4),
+ .sb_hit_out(sb_hit_aux_out), .was_stall_dcache_out(was_stall_dcache), .is_tlbwrite_out(mem_is_tlbwrite), .is_iret_out(mem_is_iret), .is_hit_itlb_out(mem_hit_itlb), .pc_out(mem_pc),.is_ecall_out(mem_is_ecall));
+
+ assign mem_is_branch_or_jump_taken = mem_is_branch_taken | mem_is_a_jump;
+ assign stall_dcache = (!hit_dcache & mem_mem_to_reg & sb_hit_aux_in) ? 1'b0 : !hit_dcache;
+
+
+ // MEM stage
+ assign dcache_re = mem_mem_to_reg;
+
+ wire[31:0] sb_addr_out, sb_data_out;
+ assign sb_drain = sb_continue_drain_out;
+
+ assign privilege_mode = f_PSW;
+ assign is_tlbwrite = mem_is_tlbwrite;
+ assign exception_type = mem_current_rm2;
+ assign current_address_rm2 = mem_current_rm1;
+ assign mem_physical_tlb_addr_out = mem_physical_tlb_addr[19:0];
+
+ storebuffer storebuffer(
+ .clk(clk),
+ .reset(reset),
+ .addr_in(mem_reg_data),
+ .data_in(mem_reg_b),
+ .is_byte(mem_is_byte),
+ .sb_we(mem_mem_we && !flush),
+ .sb_re(mem_mem_to_reg),
+ .stall_dcache(stall_dcache),
+ .hit_dtlb(hit_dtlb),
+ .sb_hit(sb_hit_aux_in),
+ .full_out(sb_full),
+ .empty_out(sb_empty),
+ .addr_out(sb_addr_out_aux_in),
+ .data_out(sb_data_out_aux_in),
+ .is_byte_out(sb_is_byte_aux_in),
+ .drain_out(sb_continue_drain_out),
+ .is_data_to_cache(sb_data_to_cache_aux_in)
+ );
+
+ assign sb_addr_out = (was_stall_dcache) ? sb_addr_out_aux_out : sb_addr_out_aux_in;
+ assign sb_data_out = (was_stall_dcache) ? sb_data_out_aux_out : sb_data_out_aux_in;
+ assign sb_data_to_cache_out = (was_stall_dcache) ? sb_data_to_cache_aux_out : sb_data_to_cache_aux_in;
+ assign sb_hit = (was_stall_dcache) ? sb_hit_aux_out : sb_hit_aux_in;
+ assign sb_is_byte = (was_stall_dcache) ? sb_is_byte_aux_out : sb_is_byte_aux_in;
+
+ assign mem_addr_m = (sb_data_to_cache_out) ? sb_addr_out : mem_reg_data;
+ assign mem_data_wr = sb_data_out; // regb content
+ assign mem_isbyte = mem_mem_to_reg ? mem_is_byte : sb_is_byte;
+ assign mem_wrd = sb_data_to_cache_out;
+ wire[31:0] data_from_mem = (sb_hit) ? sb_data_out : mem_data_rd_m;
+
+ wire[31:0] mem_exc_code_in = ( (mem_mem_to_reg || mem_wrd || (mem_mem_we && !hit_dtlb)) && !hit_dtlb && !privilege_mode) ? `EXC_DTLB_MISS : 0;
+
+ assign read_interactive_req = (mem_io_code == `FUNCT7_IO_READ_SW);
+ assign mem_stall_read_sw = read_interactive_req && !is_read_interactive_enabled;
+
+
+ // WB stage
+
+ wire[31:0] wb_mem_data;
+ wire wb_mem_to_reg;
+ wire mem_flush = (stall_dcache && hit_dtlb) | is_exception;
+
+ MEM_WB MEM_WB(.clk(clk), .flush(mem_flush), .stall(stall_print), .reg_dest_in(mem_reg_addr_dest), .reg_write_enable_in(mem_reg_write_enable), .reg_data_alu_in(mem_reg_data), .io_code_in(mem_io_code), .read_interactive_value_in(read_interactive_value), .is_read_interactive_enabled_in(is_read_interactive_enabled),
+ .mem_data_in(data_from_mem), .mem_to_reg_in(mem_mem_to_reg), .rm0_in(mem_rm0), .rm1_in(mem_rm1), .rm2_in(mem_rm2), .psw_in(mem_PSW), .is_iret_in(mem_is_iret), .is_ecall_in(mem_is_ecall), .stored_rm4_in(mem_current_rm4),
+ .is_hit_dtlb_in(hit_dtlb), .is_hit_itlb_in(mem_hit_itlb), .exc_code_in(mem_exc_code_in), .mem_addr_in(mem_addr_m), .pc_in(mem_pc), .is_flush_in(1'b0), .is_mov_in(mem_is_mov),
+ .reg_dest_out(wb_addr_d_from_mem), .reg_data_alu_out(wb_alu_res), .reg_write_enable_out(wb_reg_write_enable_from_mem), .mem_data_out(wb_mem_data), .io_code_out(wb_io_code),
+ .mem_to_reg_out(wb_mem_to_reg), .rm0_out(wb_rm0), .rm1_out(wb_rm1), .rm2_out(wb_rm2), .is_iret_out(wb_is_iret), .is_hit_dtlb_out(wb_hit_dtlb), .is_mov_out(wb_is_mov),
+ .is_hit_itlb_out(wb_hit_itlb), .pc_out(wb_pc), .is_flush_out(wb_is_flush), .stored_rm4_out(wb_current_rm4), .read_interactive_value_out(wb_read_interactive_value), .is_read_interactive_enabled_out(wb_read_interactive_enable));
+
+ assign wb_data_to_reg_from_mem = (wb_mem_to_reg > 0) ? wb_mem_data : wb_alu_res;
+
+ assign wb_reg_write_enable = (wb_read_interactive_enable ? 1'b0 : wb_reg_write_enable_from_mem );
+ assign wb_data_to_reg = (wb_read_interactive_enable ? wb_read_interactive_value : wb_data_to_reg_from_mem);
+ assign wb_addr_d = wb_addr_d_from_mem;
+
+ assign print_output = wb_current_rm4;
+ assign print_hex_enable = (wb_io_code == `FUNCT7_IO_PRINT_HEX);
+ assign stall_print = !is_print_done;
+
+ assign wb_or_hf_addr_to_reg = wb_addr_d;
+ assign wb_or_hf_data_to_reg = wb_data_to_reg;
+ assign wb_or_hf_reg_write_enable = wb_reg_write_enable;
+
+ assign is_exception_reached = (wb_rm2 > 0 && !is_branch_or_jump_taken_wire);
+
+ assign wb_or_hf_rm0 = wb_rm0;
+ assign wb_or_hf_rm1 = wb_rm1;
+ assign wb_or_hf_rm2 = wb_rm2;
+
+endmodule
diff --git a/verilog/rtl/elpis/decoder.v b/verilog/rtl/elpis/decoder.v
new file mode 100644
index 0000000..8a1a6ba
--- /dev/null
+++ b/verilog/rtl/elpis/decoder.v
@@ -0,0 +1,284 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module decoder(
+ input rst,
+ input[31:0] instr,
+ output reg[3:0] op_alu,
+ output reg wrd_reg,
+ output reg[4:0] addr_d,
+ output reg rb_immed, //rb (0) or immediate(1)
+ output reg[31:0] imm,
+ output reg mem_to_reg,
+ output reg wrd_mem,
+ output reg[2:0] branch_code,
+ output reg is_a_jump,
+ output reg is_byte,
+ output reg[1:0] is_mov,
+ output reg is_illegal,
+ output reg is_tlbwrite,
+ output reg is_iret,
+ output reg is_ecall,
+ output reg[6:0] io_code
+);
+
+ wire[6:0] opcode = instr[6:0];
+ wire[4:0] reg_dest = instr[11:7];
+ wire[2:0] funct3 = instr[14:12];
+ wire[6:0] funct7 = instr[31:25];
+ wire[4:0] shamt = instr[24:20];
+ wire[11:0] ld_ali_immediate = instr[31:20];
+ wire[11:0] st_immediate = {instr[31:25], instr[11:7]};
+ wire[12:0] branch_inmediate = {instr[31], instr[7], instr[30:25], instr[11:8], 1'b0};
+ wire[19:0] jump_inmediate = {instr[31:20], instr[14:7]};
+
+ always@(*) begin
+ wrd_reg = 0;
+ wrd_mem = 0;
+ rb_immed = 0;
+ mem_to_reg = 0;
+ branch_code = `FUNCT3_BRANCH_NO;
+ is_a_jump = 0;
+ is_byte = 0;
+ is_mov = 0;
+ is_illegal = 0;
+ is_tlbwrite = 0;
+ is_iret = 0;
+ is_ecall = 0;
+ io_code = 7'b0;
+ op_alu = 0;
+ imm = 32'b0;
+ addr_d = 5'b0;
+ case(opcode)
+ `OPCODE_AL: begin
+ case(funct3)
+ `FUNCT3_OP_ADD_SUB: begin
+ addr_d = reg_dest;
+ if (instr != `NOP) begin
+ wrd_reg = 1;
+ end
+ case(funct7)
+ `FUNCT7_OP_ADD: begin
+ op_alu = `ALU_OP_ADD;
+ end
+ `FUNCT7_OP_SUB: begin
+ op_alu = `ALU_OP_SUB;
+ end
+ default: begin
+ is_illegal = 1;
+ wrd_reg = 0;
+ end
+ endcase
+ end
+ `FUNCT3_OP_OR: begin
+ addr_d = reg_dest;
+ wrd_reg = 1;
+ op_alu = `ALU_OP_OR;
+ end
+ `FUNCT3_OP_XOR: begin
+ addr_d = reg_dest;
+ wrd_reg = 1;
+ op_alu = `ALU_OP_XOR;
+ end
+ `FUNCT3_OP_AND: begin
+ addr_d = reg_dest;
+ wrd_reg = 1;
+ op_alu = `ALU_OP_AND;
+ end
+ `FUNCT3_OP_SLL: begin
+ addr_d = reg_dest;
+ wrd_reg = 1;
+ op_alu = `ALU_OP_SLL;
+ end
+ `FUNCT3_OP_SRL_SRA: begin
+ addr_d = reg_dest;
+ wrd_reg = 1;
+ case(funct7)
+ `FUNCT7_OP_SRL: begin
+ op_alu = `ALU_OP_SRL;
+ end
+ `FUNCT7_OP_SRA: begin
+ op_alu = `ALU_OP_SRA;
+ end
+ default: begin
+ wrd_reg = 0;
+ is_illegal = 1;
+ end
+ endcase
+ end
+ default:
+ is_illegal = 1;
+ endcase
+ end
+ `OPCODE_ALI: begin
+ rb_immed = 1;
+ addr_d = reg_dest;
+ wrd_reg = 1;
+ case(funct3)
+ `FUNCT3_OP_ADD_SUB: begin
+ imm = $signed(ld_ali_immediate);
+ op_alu = `ALU_OP_ADD;
+ end
+ `FUNCT3_OP_OR: begin
+ imm = $signed(ld_ali_immediate);
+ op_alu = `ALU_OP_OR;
+ end
+ `FUNCT3_OP_XOR: begin
+ imm = $signed(ld_ali_immediate);
+ op_alu = `ALU_OP_XOR;
+ end
+ `FUNCT3_OP_AND: begin
+ imm = $signed(ld_ali_immediate);
+ op_alu = `ALU_OP_AND;
+ end
+ `FUNCT3_OP_SLL: begin
+ imm = $signed(shamt);
+ op_alu = `ALU_OP_SLL;
+ end
+ `FUNCT3_OP_SRL_SRA: begin
+ imm = $signed(shamt);
+ case(funct7)
+ `FUNCT7_OP_SRL: begin
+ op_alu = `ALU_OP_SRL;
+ end
+ `FUNCT7_OP_SRA: begin
+ op_alu = `ALU_OP_SRA;
+ end
+ default: begin
+ wrd_reg = 0;
+ is_illegal = 1;
+ end
+ endcase
+ end
+ default: begin
+ is_illegal = 1;
+ wrd_reg = 0;
+ end
+ endcase
+ end
+ `OPCODE_LD: begin
+ wrd_reg = 1;
+ mem_to_reg = 1;
+ rb_immed = 1;
+ op_alu = `ALU_OP_ADD;
+ addr_d = reg_dest;
+ imm = $signed(ld_ali_immediate);
+ case (funct3)
+ `FUNCT3_OP_LB:
+ is_byte = 1;
+ `FUNCT3_OP_LW: begin
+ is_byte = 0;
+ end
+ default:
+ is_illegal = 1;
+ endcase
+ end
+ `OPCODE_ST: begin
+ wrd_mem = 1;
+ rb_immed = 1;
+ op_alu = `ALU_OP_ADD;
+ imm = $signed(st_immediate);
+ case (funct3)
+ `FUNCT3_OP_SB:
+ is_byte = 1;
+ `FUNCT3_OP_SW: begin
+
+ end
+ default:
+ is_illegal = 1;
+ endcase
+ end
+ `OPCODE_BRANCH: begin
+ op_alu = `ALU_OP_BRANCH;
+ rb_immed = 1;
+ imm = $signed(branch_inmediate);
+ branch_code = funct3;
+ case(funct3)
+ `FUNCT3_BRANCH_BEQ: begin
+
+ end
+ `FUNCT3_BRANCH_BNE: begin
+
+ end
+ `FUNCT3_BRANCH_BLT: begin
+
+ end
+ `FUNCT3_BRANCH_BGE: begin
+
+ end
+ default:
+ is_illegal = 1;
+ endcase
+ end
+ `OPCODE_JUMP: begin
+ is_a_jump = 1;
+ op_alu = `ALU_OP_BRANCH;
+ rb_immed = 1;
+ imm = $signed(jump_inmediate);
+ end
+ `OPCODE_MOV: begin
+ op_alu = `ALU_OP_ADD;
+ addr_d = reg_dest;
+ case(funct7)
+ `FUNCT7_MOV_RM_TO_REGULAR: begin
+ wrd_reg = 1;
+ is_mov = `MOV_RM_TO_REGULAR;
+ end
+ `FUNCT7_MOV_REGULAR_TO_RM: begin
+ is_mov = `MOV_REGULAR_TO_RM;
+ end
+ default:
+ is_illegal = 1;
+ endcase
+ end
+ `OPCODE_TLBWRITE: begin
+ op_alu = `ALU_OP_ADD;
+ is_tlbwrite = 1;
+ end
+ `OPCODE_IRET: begin
+ is_a_jump = 1;
+ is_iret = 1;
+ op_alu = `ALU_OP_ADD;
+ end
+ `OPCODE_ECALL: begin
+ imm = $signed(ld_ali_immediate);
+ rb_immed = 1;
+ is_ecall = 1;
+ op_alu = `ALU_OP_ADD;
+ end
+ `OPCODE_IO: begin
+ wrd_reg = 0;
+ case(funct7)
+ `FUNCT7_IO_PRINT_HEX: begin
+ io_code = `FUNCT7_IO_PRINT_HEX;
+ end
+ `FUNCT7_IO_READ_SW: begin
+ io_code = `FUNCT7_IO_READ_SW;
+ end
+ default:
+ is_illegal = 1;
+ endcase
+ end
+ default:
+ if (rst) is_illegal = 0;
+ else is_illegal = 1;
+ endcase
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/definitions.v b/verilog/rtl/elpis/definitions.v
new file mode 100644
index 0000000..9d00e46
--- /dev/null
+++ b/verilog/rtl/elpis/definitions.v
@@ -0,0 +1,163 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+
+// NOP defined as: add $0,$0,$0
+`define NOP 32'h00000033
+
+// PC Initial direction
+`define PC_INITIAL 32'h00000000
+
+// PC Exceptions
+`define PC_EXCEPTIONS 32'h00002000
+
+// ALU Opcodes
+`define ALU_OP_ADD 4'b0000
+`define ALU_OP_SUB 4'b0001
+`define ALU_OP_BRANCH 4'b0010
+`define ALU_OP_AND 4'b0011
+`define ALU_OP_OR 4'b0100
+`define ALU_OP_XOR 4'b0101
+`define ALU_OP_SRA 4'b0110
+`define ALU_OP_SRL 4'b0111
+`define ALU_OP_SLL 4'b1000
+
+// Decode constants for move instructions
+`define MOV_RM_TO_REGULAR 2'b01
+`define MOV_REGULAR_TO_RM 2'b10
+
+// Instruction opcode RISC-V
+`define OPCODE_AL 7'b0110011
+`define OPCODE_ALI 7'b0010011
+`define OPCODE_LD 7'b0000011
+`define OPCODE_ST 7'b0100011
+`define OPCODE_JUMP 7'b1101111 // JAL encoding of RISCV but used as jump in ppt. Ex: jump x3
+`define OPCODE_BRANCH 7'b1100011
+`define OPCODE_MOV 7'b0101111
+`define OPCODE_TLBWRITE 7'b0101110
+`define OPCODE_IRET 7'b1111111
+`define OPCODE_IO 7'b1111101
+`define OPCODE_ECALL 7'b1110011 // "ECALL" encoding. It uses inmediates for the system behavior.
+
+
+// FUNCT3 for RISC-V instructions opcode
+`define FUNCT3_OP_ADD_SUB 3'b000
+`define FUNCT3_OP_SLL 3'b001
+`define FUNCT3_OP_XOR 3'b100
+`define FUNCT3_OP_SRL_SRA 3'b101
+`define FUNCT3_OP_OR 3'b110
+`define FUNCT3_OP_AND 3'b111
+
+`define FUNCT3_OP_LB 3'b000
+`define FUNCT3_OP_LH 3'b001
+`define FUNCT3_OP_LW 3'b010
+`define FUNCT3_OP_SB 3'b000
+`define FUNCT3_OP_SH 3'b001
+`define FUNCT3_OP_SW 3'b010
+
+`define FUNCT3_BRANCH_BEQ 3'b000
+`define FUNCT3_BRANCH_BNE 3'b001
+`define FUNCT3_BRANCH_BLT 3'b100
+`define FUNCT3_BRANCH_BGE 3'b101
+`define FUNCT3_BRANCH_NO 3'b111
+
+// FUNCT7 for RISC-V instructions opcode
+`define FUNCT7_OP_ADD 7'b0000000
+`define FUNCT7_OP_SUB 7'b0100000
+`define FUNCT7_OP_MUL 7'b0000001
+`define FUNCT7_OP_SRL 7'b0000000
+`define FUNCT7_OP_SRA 7'b0100000
+
+// FUNCT7 for move instructions
+`define FUNCT7_MOV_RM_TO_REGULAR 7'b0000000
+`define FUNCT7_MOV_REGULAR_TO_RM 7'b0000001
+
+// FUNCT7 for IO instructions
+`define FUNCT7_IO_PRINT_HEX 7'b0000001
+`define FUNCT7_IO_READ_SW 7'b0000010
+
+// Constants for memory
+`define MEMORY_DELAY_CYCLES 5
+`define MEMORY_SIZE 128 // 2^20 - 2^5 = 2^15.
+
+// Constants for cache
+`define CACHE_LINE_SIZE 128
+`define NUM_CACHE_LINES 4
+`define CACHE_TAG_SIZE 26
+`define IDLE_STATE 3'b000
+`define ALLOCATE_STATE 3'b001
+`define WRITE_BACK_STATE 3'b010
+
+// Constants for arbiter
+`define ARB_IDLE_STATE 3'b000
+`define ARB_DCACHE_REQUEST 3'b001
+`define ARB_ICACHE_REQUEST 3'b010
+`define ARB_DCACHE_WAIT 3'b011
+`define ARB_ICACHE_WAIT 3'b100
+
+// Constants for IO arbiter
+`define ARB_IO_IDLE_STATE 2'b00
+`define ARB_IO_CORE1_USE 2'b01
+
+// Exception codes
+`define EXC_OVERFLOW 3'b001
+`define EXC_UNDERFLOW 3'b010
+`define EXC_ILLEGAL_INST 3'b011
+`define EXC_ITLB_MISS 3'b100
+`define EXC_DTLB_MISS 3'b101
+
+// IO codes
+`define IO_PRINT_HEX 3'b110
+`define IO_READ_SW 3'b111
+
+// Constants for store buffer
+`define SB_NUM_ENTRIES 3'd4
+
+// Cache types
+`define CACHE_TYPE_DCACHE 1'b0
+`define CACHE_TYPE_ICACHE 1'b1
+
+// Offset of data space at OS
+`define OFFSET_OS_DATA_CORE0 8'h00
+
+// Constants for TLB
+`define ITLB_BASE_ADDRESS_SHIFT_CORE0 16'h1000 // 1024
+`define DTLB_BASE_ADDRESS_SHIFT_CORE0 16'h4000 // 4096
+`define NUM_TLB_LINES 5'd16
+
+// Constants for History File
+`define HF_NUM_ENTRIES 5'd16
+
+// Constants for FIFO coherence response states
+`define FIFO_COH_NOT_SENT 2'b00
+`define FIFO_COH_FIRST_SENT 2'b01
+`define FIFO_COH_COMPLETE_SENT 2'b10
+
+// Implementation of ceiling log2
+`define CLOG2(x) \
+ ((x <= 0) ? -1 : \
+ (x == 1) ? 0 : \
+ (x <= 2) ? 1 : \
+ (x <= 4) ? 2 : \
+ (x <= 8) ? 3 : \
+ (x <= 16) ? 4 : \
+ (x <= 32) ? 5 : \
+ (x <= 64) ? 6 : \
+ (x <= 128) ? 7 : \
+ (x <= 256) ? 8 : \
+ (x <= 512) ? 9 : \
+ (x <= 1024) ? 10 : \
+ (x <= 2048) ? 11 : \
+ (x <= 4096) ? 12 : \
+ (x <= 8192) ? 13 : )
+
diff --git a/verilog/rtl/elpis/forwardingunit.v b/verilog/rtl/elpis/forwardingunit.v
new file mode 100644
index 0000000..a3c21b3
--- /dev/null
+++ b/verilog/rtl/elpis/forwardingunit.v
@@ -0,0 +1,73 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module forwardingunit(
+ input[4:0] ex_reg_a_in,
+ input[4:0] ex_reg_b_in,
+ input[4:0] mem_reg_d_in,
+ input[4:0] wb_reg_d_in,
+ input mem_reg_we_in,
+ input wb_reg_we_in,
+ output reg[1:0] forward_x,
+ output reg[1:0] forward_y
+);
+
+ always@(*) begin
+ if (wb_reg_we_in & (wb_reg_d_in != 0) &
+ !(mem_reg_we_in & (mem_reg_d_in != 0) & (mem_reg_d_in == ex_reg_a_in)) &
+ (wb_reg_d_in == ex_reg_a_in))
+ forward_x <= 2'b01;
+ else if (mem_reg_we_in & (mem_reg_d_in != 0) & (mem_reg_d_in == ex_reg_a_in))
+ forward_x <= 2'b10;
+ else
+ forward_x <= 2'b00;
+
+ if (wb_reg_we_in & (wb_reg_d_in != 0) &
+ !(mem_reg_we_in & (mem_reg_d_in != 0) & (mem_reg_d_in == ex_reg_b_in)) &
+ (wb_reg_d_in == ex_reg_b_in) )
+ forward_y <= 2'b01;
+ else if (mem_reg_we_in & (mem_reg_d_in != 0) & (mem_reg_d_in == ex_reg_b_in))
+ forward_y <= 2'b10;
+ else
+ forward_y <= 2'b00;
+ end
+
+endmodule
+
+
+module forwardingunit_st(
+ input mem_we,
+ input[4:0] ex_reg_b_in,
+ input[4:0] mem_reg_b_in,
+ input[1:0] forwarding_y,
+ output reg[1:0] forwarding_regb
+);
+
+ always@(*) begin
+ if (mem_we && forwarding_y)
+ forwarding_regb <= 2'b01;
+ else if (mem_we && (ex_reg_b_in == mem_reg_b_in))
+ forwarding_regb <= 2'b10;
+ else
+ forwarding_regb <= 2'b00;
+ end
+
+endmodule
+
+
\ No newline at end of file
diff --git a/verilog/rtl/elpis/hazardDetectionUnit.v b/verilog/rtl/elpis/hazardDetectionUnit.v
new file mode 100644
index 0000000..7e24335
--- /dev/null
+++ b/verilog/rtl/elpis/hazardDetectionUnit.v
@@ -0,0 +1,29 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module hazardDetectionUnit(input[4:0] ex_reg_dest_addr_in, input ex_mem_read_in, input[4:0] id_reg_a_addr_in, input[4:0] id_reg_b_addr_in, output reg stall_out);
+
+ always@(*) begin
+ if (ex_mem_read_in & ((ex_reg_dest_addr_in == id_reg_a_addr_in) | (ex_reg_dest_addr_in == id_reg_b_addr_in))) // Load stalls
+ stall_out <= 1'b1;
+ else
+ stall_out <= 1'b0;
+ end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/elpis/memory.v b/verilog/rtl/elpis/memory.v
new file mode 100644
index 0000000..e193c45
--- /dev/null
+++ b/verilog/rtl/elpis/memory.v
@@ -0,0 +1,183 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module memory
+ (
+`ifdef USE_POWER_PINS
+ inout vdda1, // User area 1 3.3V supply
+ inout vdda2, // User area 2 3.3V supply
+ inout vssa1, // User area 1 analog ground
+ inout vssa2, // User area 2 analog ground
+ inout vccd1, // User area 1 1.8V supply
+ inout vccd2, // User area 2 1.8v supply
+ inout vssd1, // User area 1 digital ground
+ inout vssd2, // User area 2 digital ground
+`endif
+ input clk,
+ input reset,
+ input we,
+ input[19:0] addr_in,
+ input[127:0] wr_data,
+ input requested,
+ input reset_mem_req,
+ output reg[127:0] rd_data_out,
+ // output[127:0] rd_data_out,
+ output ready,
+ input is_loading_memory_into_core,
+ input[19:0] addr_to_core_mem,
+ input[31:0] data_to_core_mem
+);
+ wire[19:0] addr_output_mem;
+ wire[7:0] first_bit_out_current;
+ reg[7:0] first_bit_out_previous;
+ wire[31:0] auxiliar_mem_out;
+
+ // (* ramstyle = "M9K" *) reg[31:0] mem[0:`MEMORY_SIZE-1];
+ reg[$clog2(`MEMORY_DELAY_CYCLES):0] cycles;
+
+ assign ready = cycles == 0;
+
+ assign addr_output_mem = addr_in + (cycles % 3'd4);
+ assign first_bit_out_current = 6'd32 * (cycles % 3'd4);
+
+ integer i;
+ always@(posedge clk) begin
+ if(reset) begin
+ cycles <= 0;
+ end else if (reset_mem_req) begin
+ cycles <= 0;
+ end else if ((ready && requested))begin
+ cycles <= `MEMORY_DELAY_CYCLES;
+ end else if(cycles!=0) begin
+ cycles <= cycles-1'b1 ;
+ end
+
+ // if (we && requested && !is_loading_memory_into_core) begin
+ // if(cycles == 4)
+ // mem[addr_in] <= wr_data[31:0];
+ // else if (cycles == 3) begin
+ // mem[addr_in+1] <= wr_data[63:32];
+ // end else if (cycles == 2) begin
+ // mem[addr_in+2] <= wr_data[95:64];
+ // end else if (cycles == 1) begin
+ // mem[addr_in+3] <= wr_data[127:96];
+ // end
+ // end else if(is_loading_memory_into_core) begin
+ // mem[addr_to_core_mem] <= data_to_core_mem;
+ // end
+
+ // auxiliar_mem_out <= mem[addr_output_mem];
+ first_bit_out_previous <= first_bit_out_current;
+ rd_data_out[first_bit_out_previous +:32] <= auxiliar_mem_out;
+ end
+
+ wire[31:0] dummy_out;
+
+ reg[19:0] addr_to_sram;
+
+ always@(*) begin
+ if (we && requested && !is_loading_memory_into_core) begin
+ if(cycles == 4)
+ addr_to_sram <= addr_in;
+ else if (cycles == 3) begin
+ addr_to_sram <= addr_in+1;
+ end else if (cycles == 2) begin
+ addr_to_sram <= addr_in+2;
+ end else if (cycles == 1) begin
+ addr_to_sram <= addr_in+3;
+ end
+ end else if(is_loading_memory_into_core) begin
+ addr_to_sram <= addr_to_core_mem;
+ end else begin
+ addr_to_sram <= addr_output_mem;
+ end
+ end
+
+ reg[31:0] data_to_sram;
+ always@(*) begin
+ if (we && requested && !is_loading_memory_into_core) begin
+ if(cycles == 4)
+ data_to_sram <= wr_data[31:0];
+ else if (cycles == 3) begin
+ data_to_sram <= wr_data[63:32];
+ end else if (cycles == 2) begin
+ data_to_sram <= wr_data[95:64];
+ end else if (cycles == 1) begin
+ data_to_sram <= wr_data[127:96];
+ end
+ end else if(is_loading_memory_into_core) begin
+ data_to_sram <= data_to_core_mem;
+ end else begin
+ data_to_sram <= 32'b0;
+ end
+ end
+
+
+ sram_32_1024_sky130 CPURAM(
+ `ifdef USE_POWER_PINS
+ .vccd1(vccd1),
+ .vssd1(vssd1),
+ `endif
+ .clk0(clk),
+ .csb0(1'b0),
+ .web0(!we),
+ .spare_wen0(1'b0),
+ .addr0(addr_to_sram),
+ .din0(data_to_sram),
+ .dout0(auxiliar_mem_out)
+ );
+
+ // always @(*) begin
+ // auxiliar_mem_out <= we ? 32'b0 : data_to_sram;
+ // end
+
+ //OPENLANE
+ // reg[31:0] mem[0:`MEMORY_SIZE-1];
+ // reg[$clog2(`MEMORY_DELAY_CYCLES):0] cycles;
+
+ // assign ready = cycles == 0;
+
+ // // integer i;
+ // always@(posedge clk) begin
+ // if(reset) begin
+ // cycles <= 0;
+ // end else if (reset_mem_req) begin
+ // cycles <= 0;
+ // end else if ((ready && requested))begin
+ // cycles <= `MEMORY_DELAY_CYCLES;
+ // end else if(cycles!=0) begin
+ // cycles <= cycles-1'b1 ;
+ // end
+
+ // if (we && requested && !is_loading_memory_into_core) begin
+ // mem[addr_in+3] <= wr_data[127:96];
+ // mem[addr_in+2] <= wr_data[95:64];
+ // mem[addr_in+1] <= wr_data[63:32];
+ // mem[addr_in] <= wr_data[31:0];
+ // end else if(is_loading_memory_into_core) begin
+ // mem[addr_to_core_mem] <= data_to_core_mem;
+ // end
+ // end
+
+ // assign rd_data_out[127:96] = mem[addr_in+3];
+ // assign rd_data_out[95:64] = mem[addr_in+2];
+ // assign rd_data_out[63:32] = mem[addr_in+1];
+ // assign rd_data_out[31:0] = mem[addr_in];
+
+endmodule
diff --git a/verilog/rtl/elpis/regfile.v b/verilog/rtl/elpis/regfile.v
new file mode 100644
index 0000000..b616590
--- /dev/null
+++ b/verilog/rtl/elpis/regfile.v
@@ -0,0 +1,52 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module regfile(
+ input clk,
+ input reset,
+ input wrd, // write permission
+ input[31:0] d, // data
+ input[4:0] addr_a, // source register A
+ input[4:0] addr_b, // source register B
+ input[4:0] addr_d, // destination register
+ output[31:0] a, // read port A
+ output[31:0] b, // read port B
+ input[4:0] dest_read,
+ output[31:0] dest_value
+);
+
+ reg[31:0] registers[31:0];
+ integer i;
+
+ always@(negedge clk) begin
+ if (reset) begin
+ for (i=0; i < 32; i = i+1) begin
+ registers[i] <= 0;
+ end
+ end else if (wrd && (addr_d > 0)) begin
+ registers[addr_d] <= d;
+ end
+ end
+
+ assign a = registers[addr_a];
+ assign b = registers[addr_b];
+ assign dest_value = registers[dest_read];
+
+endmodule
+
diff --git a/verilog/rtl/elpis/specialreg.v b/verilog/rtl/elpis/specialreg.v
new file mode 100644
index 0000000..14414c7
--- /dev/null
+++ b/verilog/rtl/elpis/specialreg.v
@@ -0,0 +1,71 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module specialreg(
+ input clk,
+ input reset,
+ input[31:0] in_rm0,
+ input[31:0] in_rm1,
+ input[31:0] in_rm2,
+ input[31:0] in_other_rm,
+ input[2:0] sel,
+ input we,
+ output reg[31:0] out_rm0,
+ output reg[31:0] out_rm1,
+ output reg[31:0] out_rm2,
+ output reg[31:0] out_rm,
+ output reg[31:0] out_rm4
+);
+
+ reg[31:0] rm[4:0];
+ integer i;
+
+ /* rm0 : holds PC the OS should return to on exceptions
+ rm1 : holds an @ for certain exceptions
+ rm2 : holds info on the type of exception
+ rm3 : Privilege Status Word - Holds the current privilege of the machine. --> PSW/RM3 in datapath
+ rm4 : Holds the input/output information
+ */
+
+ always@(negedge clk) begin
+ if (reset) begin
+ for (i=1; i < 5; i = i+1) begin
+ rm[i] <= 0;
+ end
+ rm[0] <= `PC_INITIAL;
+ end else if (in_rm2) begin
+ rm[0] <= in_rm0;
+ rm[1] <= in_rm1;
+ rm[2] <= in_rm2;
+ end else begin
+ if (we) begin
+ rm[4] <= in_other_rm;
+ end
+ end
+ end
+
+ always@(*) begin
+ out_rm <= rm[sel];
+ out_rm0 <= rm[0];
+ out_rm1 <= rm[1];
+ out_rm2 <= rm[2];
+ out_rm4 <= rm[4];
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/sram_32_1024_sky130.v b/verilog/rtl/elpis/sram_32_1024_sky130.v
new file mode 100644
index 0000000..75a2d54
--- /dev/null
+++ b/verilog/rtl/elpis/sram_32_1024_sky130.v
@@ -0,0 +1,77 @@
+// OpenRAM SRAM model
+// Words: 1024
+// Word size: 32
+
+module sram_32_1024_sky130(
+`ifdef USE_POWER_PINS
+ vccd1,
+ vssd1,
+`endif
+// Port 0: RW
+ clk0,csb0,web0,spare_wen0,addr0,din0,dout0
+ );
+
+ parameter DATA_WIDTH = 33 ;
+ parameter ADDR_WIDTH = 11 ;
+ parameter RAM_DEPTH = 1 << ADDR_WIDTH;
+ // FIXME: This delay is arbitrary.
+ parameter DELAY = 3 ;
+ parameter VERBOSE = 1 ; //Set to 0 to only display warnings
+ parameter T_HOLD = 1 ; //Delay to hold dout value after posedge. Value is arbitrary
+
+`ifdef USE_POWER_PINS
+ inout vccd1;
+ inout vssd1;
+`endif
+ input clk0; // clock
+ input csb0; // active low chip select
+ input web0; // active low write control
+ input [ADDR_WIDTH-1:0] addr0;
+ input spare_wen0; // spare mask
+ input [DATA_WIDTH-1:0] din0;
+ output [DATA_WIDTH-1:0] dout0;
+
+ reg csb0_reg;
+ reg web0_reg;
+ reg spare_wen0_reg;
+ reg [ADDR_WIDTH-1:0] addr0_reg;
+ reg [DATA_WIDTH-1:0] din0_reg;
+ reg [DATA_WIDTH-1:0] dout0;
+
+ // All inputs are registers
+ always @(posedge clk0)
+ begin
+ csb0_reg = csb0;
+ web0_reg = web0;
+ spare_wen0_reg = spare_wen0;
+ addr0_reg = addr0;
+ din0_reg = din0;
+ #(T_HOLD) dout0 = 32'bx;
+ if ( !csb0_reg && web0_reg && VERBOSE )
+ $display($time," Reading %m addr0=%b dout0=%b",addr0_reg,mem[addr0_reg]);
+ if ( !csb0_reg && !web0_reg && VERBOSE )
+ $display($time," Writing %m addr0=%b din0=%b",addr0_reg,din0_reg);
+ end
+
+reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];
+
+ // Memory Write Block Port 0
+ // Write Operation : When web0 = 0, csb0 = 0
+ always @ (negedge clk0)
+ begin : MEM_WRITE0
+ if ( !csb0_reg && !web0_reg ) begin
+ mem[addr0_reg][30:0] = din0_reg[30:0];
+ if (spare_wen0_reg)
+ mem[addr0_reg][32] = din0_reg[32];
+ end
+ end
+
+ // Memory Read Block Port 0
+ // Read Operation : When web0 = 1, csb0 = 0
+ always @ (negedge clk0)
+ begin : MEM_READ0
+ if (!csb0_reg && web0_reg)
+ dout0 <= #(DELAY) mem[addr0_reg];
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/storebuffer.v b/verilog/rtl/elpis/storebuffer.v
new file mode 100644
index 0000000..bc173fc
--- /dev/null
+++ b/verilog/rtl/elpis/storebuffer.v
@@ -0,0 +1,138 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module storebuffer(
+ input clk,
+ input reset,
+ input[31:0] addr_in,
+ input[31:0] data_in,
+ input is_byte,
+ input sb_we, // Add a new entry into SB
+ input sb_re, // Read request (bypass) from an entry of SB
+ input stall_dcache,
+ input hit_dtlb,
+ output reg sb_hit,
+ output full_out,
+ output empty_out,
+ output reg[31:0] addr_out,
+ output reg[31:0] data_out,
+ output reg is_byte_out,
+ output reg drain_out,
+ output reg is_data_to_cache
+);
+ reg useless_bit, hold_value_to_cache;
+ reg[31:0] sb_addr[0:`SB_NUM_ENTRIES-1];
+ reg[31:0] sb_data[0:`SB_NUM_ENTRIES-1];
+ reg sb_size[0:`SB_NUM_ENTRIES-1]; // 0 - word, 1 - byte
+ reg sb_valid[0:`SB_NUM_ENTRIES-1];
+
+ reg[$clog2(`SB_NUM_ENTRIES)-1:0] head;
+ reg[$clog2(`SB_NUM_ENTRIES)-1:0] tail;
+ reg[$clog2(`SB_NUM_ENTRIES)-1:0] tail_last;
+ reg[$clog2(`SB_NUM_ENTRIES):0] entry_count;
+
+ wire[31:0] ld_first_byte, ld_last_byte;
+ wire[1:0] offset;
+
+ assign ld_first_byte = addr_in;
+ assign ld_last_byte = (is_byte) ? addr_in : (addr_in+3);
+ assign offset = addr_in[1:0];
+
+ assign empty_out = (entry_count == 0);
+ assign full_out = (entry_count == `SB_NUM_ENTRIES);
+
+ reg[1:0] hit_pos;
+ integer i;
+ always@(*) begin
+ sb_hit = 1'b0;
+ for (i = 0; (i < `SB_NUM_ENTRIES); i=i+1) begin
+ if (sb_valid[i] && (sb_addr[i] <= ld_first_byte) && ( (sb_addr[i] + (sb_size[i] ? 0 : 3'b11) ) >= ld_last_byte) ) begin
+ sb_hit = 1'b1;
+ hit_pos = i[1:0];
+ end
+ end
+ if (!sb_hit) begin
+ hit_pos = 2'b0;
+ end
+ end
+
+ always@(posedge clk) begin
+ if (reset) begin
+ head <= 2'b0;
+ tail <= 2'b0;
+ entry_count <= 3'b0;
+ for(i = 0; i < `SB_NUM_ENTRIES; i=i+1) begin
+ sb_valid[i] <= 1'b0;
+ end
+ end else begin
+ if (sb_re && sb_hit) begin
+ data_out <= (is_byte && sb_size[hit_pos]) ? {24'b0, sb_data[hit_pos][offset*'d8]} : sb_data[hit_pos];
+ end
+
+ if(sb_we && sb_hit) begin
+ if (is_byte && !sb_size[hit_pos]) begin
+ // We have a word and want to write a byte
+ sb_data[hit_pos][offset*8+:8] <= data_in[7:0];
+ end else if (is_byte && sb_size[hit_pos]) begin
+ // We have a byte and want to write a byte
+ sb_data[hit_pos] <= {24'b0, data_in[7:0]};
+ end else begin
+ // We have (byte or word) and we want to write a word
+ sb_data[hit_pos] <= data_in;
+ sb_size[hit_pos] <= 1'b0;
+ end
+ end
+
+ if ((full_out && !stall_dcache) || (!sb_we && !sb_re && !empty_out && !stall_dcache)) begin
+ drain_out <= 1'b1;
+ tail_last <= tail;
+ is_data_to_cache <= 1'b1;
+ addr_out <= sb_addr[tail];
+ data_out <= sb_data[tail];
+ is_byte_out <= sb_size[tail];
+ entry_count <= entry_count - 1'b1;
+ sb_valid[tail] <= 1'b0;
+ {useless_bit, tail} <= (tail+1'b1)%`SB_NUM_ENTRIES;
+ hold_value_to_cache <= 1'b1;
+ end else if(stall_dcache && hold_value_to_cache) begin
+ drain_out <= 1'b1;
+ is_data_to_cache <= 1'b1;
+ addr_out <= sb_addr[tail_last];
+ data_out <= sb_data[tail_last];
+ is_byte_out <= sb_size[tail_last];
+ hold_value_to_cache <= 1'b1;
+ end else begin
+ drain_out <= 1'b0;
+ is_data_to_cache <= 1'b0;
+ hold_value_to_cache <= 1'b0;
+ tail_last <= 'b0;
+ end
+
+ if (sb_we && !full_out && !sb_hit && hit_dtlb) begin
+ sb_addr[head] <= addr_in;
+ sb_data[head] <= data_in;
+ sb_size[head] <= is_byte;
+ sb_valid[head] <= 1'b1;
+ entry_count <= entry_count + 1'b1;
+ {useless_bit, head} <= (head + 1'b1)%`SB_NUM_ENTRIES;
+ end
+ end
+ end
+
+endmodule
diff --git a/verilog/rtl/elpis/tlb.v b/verilog/rtl/elpis/tlb.v
new file mode 100644
index 0000000..af5e6d5
--- /dev/null
+++ b/verilog/rtl/elpis/tlb.v
@@ -0,0 +1,132 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module tlb #(parameter CORE_ID=0, parameter CACHE_TYPE=`CACHE_TYPE_ICACHE)(
+ input clk,
+ input reset,
+ input[31:0] virtual_addr,
+ input[31:0] virtual_addr_write_in,
+ input privilege_mode, // 0 - users, 1 - system
+ input tlb_we,
+ input tlb_re,
+ input[19:0] physical_addr_write_in,
+ input[19:0] physical_addr_in,
+ output [19:0] physical_addr_out,
+ output hit_tlb,
+ output exc_protected_page
+);
+
+ reg[19:0] tlb_pages[0:`NUM_TLB_LINES-1];
+ reg[7:0] tlb_frames[0:`NUM_TLB_LINES-1];
+ reg tlbValidBits[0:`NUM_TLB_LINES-1];
+ reg tlb_lru[0:`NUM_TLB_LINES-1];
+
+ wire[19:0] page;
+ wire[19:0] candidate_physical_addr_out;
+
+ assign exc_protected_page = (tlb_we && !privilege_mode) ? 1'b1 : 1'b0;
+ assign page = tlb_we ? virtual_addr_write_in[31:12] : virtual_addr[31:12];
+
+ wire[$clog2(`NUM_TLB_LINES)-1:0] id_candidate_write;
+ reg[$clog2(`NUM_TLB_LINES)-1:0] id_candidate_read, id_candidate_write_empty, id_candidate_write_no_empty, id_last_accessed;
+ reg found_read, found_write_empty;
+
+ integer i;
+ always@(*) begin : get_id_read
+ id_candidate_read = 4'b0;
+ found_read = 1'b0;
+ for (i=0; i < `NUM_TLB_LINES; i=i+1) begin
+ if ((page == tlb_pages[i]) && tlbValidBits[i]) begin
+ id_candidate_read = i[3:0];
+ found_read = 1'b1;
+ end
+ end
+ end
+
+ integer j;
+ always@(*) begin : get_id_write_empty
+ id_candidate_write_empty = 0;
+ found_write_empty = 0;
+ for (j=0; j < `NUM_TLB_LINES; j=j+1) begin
+ if ((tlbValidBits[j] == 0) && !found_write_empty) begin
+ found_write_empty = 1'b1;
+ id_candidate_write_empty = j[3:0];
+ end
+ end
+ end
+
+ integer k, n_1_lru;
+ always@(*) begin : get_id_candidate_write_no_empty
+ id_candidate_write_no_empty = 0;
+ for (k=0; k < `NUM_TLB_LINES; k=k+1) begin
+ if (tlb_lru[k] == 1'b0) begin
+ id_candidate_write_no_empty = k[$clog2(`NUM_TLB_LINES)-1:0];
+ end
+ end
+ end
+
+ integer u;
+ always@(posedge clk) begin : count_n_1_lru
+ if (reset) begin
+ n_1_lru = 0;
+ end else begin
+ n_1_lru = n_1_lru + (tlb_we && privilege_mode);
+ end
+ end
+
+ integer c;
+ always@(posedge clk) begin : plru_management
+ if (reset) begin
+ for (c=0; c < `NUM_TLB_LINES; c=c+1) begin
+ tlb_lru[c] <= 1'b0;
+ end
+ end else begin
+ if(n_1_lru == `NUM_TLB_LINES) begin
+ for (c=0; c < `NUM_TLB_LINES; c=c+1) begin
+ tlb_lru[c] <= id_last_accessed == c;
+ end
+ end
+ tlb_lru[id_last_accessed] <= 1'b1;
+ end
+ end
+
+ assign hit_tlb = found_read || privilege_mode;
+ assign candidate_physical_addr_out = (tlb_re && !privilege_mode && found_read) ? {tlb_frames[id_candidate_read], virtual_addr[11:0]} : (privilege_mode ? virtual_addr[19:0] : 20'b0);
+ assign physical_addr_out = candidate_physical_addr_out;
+ assign id_candidate_write = found_write_empty ? id_candidate_write_empty : id_candidate_write_no_empty;
+
+ integer l;
+ always@(posedge clk) begin : write_tlb_structures
+ if (reset) begin
+ for (l=0; l < `NUM_TLB_LINES; l=l+1) begin
+ tlbValidBits[l] <= 0;
+ end
+ end else begin
+ if (tlb_we && privilege_mode) begin // TLBwrite
+ tlb_pages[id_candidate_write] <= page;
+ tlb_frames[id_candidate_write] <= physical_addr_write_in[19:12];
+ tlbValidBits[id_candidate_write] <= 1'b1;
+ id_last_accessed <= id_candidate_write;
+ end else if (tlb_re && !privilege_mode && found_read) begin // TLBRead
+ id_last_accessed <= id_candidate_read;
+ end
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/elpis/top.v b/verilog/rtl/elpis/top.v
new file mode 100644
index 0000000..47d5455
--- /dev/null
+++ b/verilog/rtl/elpis/top.v
@@ -0,0 +1,147 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module top
+#(parameter MEMORY_FILE = 0)
+(
+ input clk,
+ input reset_chip,
+ input reset_core,
+ input is_loading_memory_into_core,
+ input[19:0] addr_to_core_mem,
+ input[31:0] data_to_core_mem,
+ input[31:0] read_value_to_Elpis,
+ input read_enable_to_Elpis,
+ output output_enabled_from_elpis_to_pico,
+ output[31:0] output_data_from_elpis_to_pico
+);
+
+ wire print_hex_enable, req_out_core0, read_interactive_req_core0, is_ready_dataout_core0, is_ready_print_core0;
+ wire[31:0] core0_data_print;
+ wire[31:0] print_output;
+ wire[31:0] data_out_to_core;
+
+ wire core0_need_reset_mem_req, need_reset_mem_req, is_mem_ready, core0_is_mem_we;
+ wire[19:0] core0_to_mem_address;
+ wire[127:0] read_data_from_mem, core0_to_mem_data;
+ wire is_mem_req;
+
+ // memory module
+ memory #(.MEMORY_FILE(MEMORY_FILE)) memory(
+ .clk(clk),
+ .reset(reset_chip),
+ .we(core0_is_mem_we),
+ .addr_in(core0_to_mem_address),
+ .wr_data(core0_to_mem_data),
+ .requested(is_mem_req),
+ .reset_mem_req(core0_need_reset_mem_req),
+ .rd_data_out(read_data_from_mem),
+ .ready(is_mem_ready),
+ .is_loading_memory_into_core(is_loading_memory_into_core),
+ .addr_to_core_mem(addr_to_core_mem),
+ .data_to_core_mem(data_to_core_mem)
+ );
+
+ // reg[19:0] dummyAddr;
+ // always@(posedge clk) begin
+ // if(reset_chip) begin
+ // output_enabled_from_elpis_to_pico <= 1'b0;
+ // output_data_from_elpis_to_pico <= 32'b0;
+ // core0_to_mem_address <= 20'b0;
+ // dummyAddr <= 20'b0;
+ // end else begin
+ // output_enabled_from_elpis_to_pico <= is_mem_ready;
+ // output_data_from_elpis_to_pico <= read_data_from_mem[31:0];
+ // core0_to_mem_address <= dummyAddr;
+ // dummyAddr <= dummyAddr + 1'b1;
+ // end
+ // end
+
+ core #(.CORE_ID(0)) core0(
+ .clk(clk),
+ .rst(reset_core),
+ .read_interactive_value(data_out_to_core),
+ .read_interactive_ready(is_ready_dataout_core0),
+ .hex_out(core0_data_print),
+ .read_interactive_req(read_interactive_req_core0),
+ .hex_req(req_out_core0),
+ .is_print_done(is_ready_print_core0),
+ .is_memory_we(core0_is_mem_we),
+ .mem_addr_out(core0_to_mem_address),
+ .mem_data_out(core0_to_mem_data),
+ .is_mem_req_reset(core0_need_reset_mem_req),
+ .data_from_mem(read_data_from_mem),
+ .is_mem_ready(is_mem_ready),
+ .is_mem_req(is_mem_req)
+ );
+
+ //COre without arbiters
+ // assign read_data_from_mem = data_to_core_mem;
+ // assign is_mem_ready = is_loading_memory_into_core;
+ // assign output_enabled_from_elpis_to_pico = is_ready_print_core0;
+ // assign output_data_from_elpis_to_pico = core0_data_print;
+ // assign data_out_to_core = read_value_to_Elpis;
+ // assign read_enable_to_Elpis = is_ready_dataout_core0;
+
+ assign output_data_from_elpis_to_pico = print_output;
+ assign output_enabled_from_elpis_to_pico = print_hex_enable;
+
+ io_input_arbiter io_input_arbiter(
+ .clk(clk),
+ .reset(reset_chip),
+ .req_core0(read_interactive_req_core0),
+ .read_value(read_value_to_Elpis),
+ .read_enable(read_enable_to_Elpis),
+ .is_ready_core0(is_ready_dataout_core0),
+ .data_out(data_out_to_core)
+ );
+
+ io_output_arbiter io_output_arbiter(
+ .clk(clk),
+ .reset(reset_chip),
+ .req_core0(req_out_core0),
+ .data_core0(core0_data_print),
+ .print_hex_enable(print_hex_enable),
+ .print_output(print_output),
+ .is_ready_core0(is_ready_print_core0)
+ );
+
+ //COre with arbiters
+ // assign read_data_from_mem = data_to_core_mem;
+ // assign is_mem_ready = is_loading_memory_into_core;
+
+ // Mem with arbiters
+ // reg[19:0] dummyAddr;
+ // always@(posedge clk) begin
+ // if(reset_chip) begin
+ // req_out_core0 <= 1'b0;
+ // core0_data_print <= 32'b0;
+ // core0_to_mem_address <= 20'b0;
+ // dummyAddr <= 20'b0;
+ // end else begin
+ // req_out_core0 <= is_mem_ready;
+ // core0_data_print <= read_data_from_mem[31:0];
+ // core0_to_mem_address <= dummyAddr;
+ // dummyAddr <= dummyAddr + 1'b1;
+ // end
+ // end
+
+
+
+endmodule
diff --git a/verilog/rtl/elpis/utils.v b/verilog/rtl/elpis/utils.v
new file mode 100644
index 0000000..7af7180
--- /dev/null
+++ b/verilog/rtl/elpis/utils.v
@@ -0,0 +1,45 @@
+/*
+*
+* This file is part of the Elpis processor project.
+*
+* Copyright © 2020-present. All rights reserved.
+* Authors: Aurora Tomas and Rodrigo Huerta.
+*
+* This file is licensed under both the BSD-3 license for individual/non-commercial
+* use. Full text of both licenses can be found in LICENSE file.
+*/
+
+`default_nettype none
+
+`ifdef TESTS
+ `include "elpis/definitions.v"
+`else
+ `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
+`endif
+
+module mux3_1 #(parameter NBITS=32)(input[1:0] sel_in, input[NBITS-1:0] input1, input[NBITS-1:0] input2, input[NBITS-1:0] input3, output reg[NBITS-1:0] result);
+
+ always@(*) begin
+ case (sel_in)
+ 2'b00: result <= input1;
+ 2'b01: result <= input2;
+ 2'b10: result <= input3;
+ default: result <= 32'b0;
+ endcase
+ end
+
+endmodule
+
+
+module TLBAddressAdder #(parameter CORE_ID=0)(input[31:0] address_in,input[31:0] exception_code_in, output reg[31:0] address_out);
+
+ always@(*) begin
+ if(exception_code_in==`EXC_DTLB_MISS) begin
+ address_out <= address_in + `DTLB_BASE_ADDRESS_SHIFT_CORE0;
+ end else begin
+ address_out <= address_in + `ITLB_BASE_ADDRESS_SHIFT_CORE0;
+ end
+ end
+
+endmodule
+
diff --git a/verilog/rtl/uprj_netlists.v b/verilog/rtl/uprj_netlists.v
index 3537de8..9d4c61e 100644
--- a/verilog/rtl/uprj_netlists.v
+++ b/verilog/rtl/uprj_netlists.v
@@ -24,5 +24,26 @@
`include "gl/user_proj_example.v"
`else
`include "user_project_wrapper.v"
+ `include "elpis/alu.v"
+ `include "elpis/arbiter.v"
+ `include "elpis/betweenStages.v"
+ `include "elpis/branchComparer.v"
+ `include "elpis/cache.v"
+ `include "elpis/controlunit.v"
+ `include "elpis/core.v"
+ `include "elpis/datapath.v"
+ `include "elpis/decoder.v"
+ `include "elpis/definitions.v"
+ `include "elpis/forwardingunit.v"
+ `include "elpis/hazardDetectionUnit.v"
+ `include "elpis/IO_arbiter.v"
+ `include "elpis/memory.v"
+ `include "elpis/sram_32_1024_sky130.v"
+ `include "elpis/regfile.v"
+ `include "elpis/specialreg.v"
+ `include "elpis/storebuffer.v"
+ `include "elpis/tlb.v"
+ `include "elpis/top.v"
+ `include "elpis/utils.v"
`include "user_proj_example.v"
`endif
\ No newline at end of file