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