prototype works

This commit is contained in:
Jose
2026-03-02 23:20:54 +01:00
parent 8f2b31259c
commit e7cd451e7e
62 changed files with 8924 additions and 220 deletions

View File

@@ -1,19 +1,19 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name:
// Design Name: Arithmetic-Logic Unit
// Module Name: alu
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Main functional unit of the EX stage
//
// Dependencies:
//
// Revision:
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
@@ -29,18 +29,18 @@ module alu(
always @(*) begin
case(sel)
4'b0000: R <= A + B; // add
4'b0001: R <= A - B; // sub
4'b0010: R <= A & B; // and
4'b0011: R <= A | B; // or
4'b0100: R <= A ^ B; // xor
4'b0101: R <= A << B[4:0]; // sll (shamt = 5 bits)
4'b0110: R <= A >> B[4:0]; // srl (logical)
4'b0111: R <= ($signed(A) < $signed(B)) ? 1 : 0; // slt signed
4'b1000: R <= (A < B) ? 1 : 0; // sltu unsigned
4'b1001: R <= $signed(A) >>> B[4:0]; // sra arithmetic right
4'b1010: R <= 32'b0; // default / nop opcional
default: R <= 32'b0;
4'b0000: R = A + B; // add
4'b0001: R = A - B; // sub
4'b0010: R = A & B; // and
4'b0011: R = A | B; // or
4'b0100: R = A ^ B; // xor
4'b0101: R = A << B[4:0]; // sll
4'b0110: R = A >> B[4:0]; // srl
4'b0111: R = ($signed(A) < $signed(B)) ? 1 : 0; // slt (shift if less than signed)
4'b1000: R = (A < B) ? 1 : 0; // sltu (shift if less than unsigned)
4'b1001: R = $signed(A) >>> B[4:0]; // sra (shift right arithmetic)
4'b1010: R = 32'b0; // nop
default: R = 32'b0; // default: nop
endcase
end

View File

@@ -1,19 +1,19 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name:
// Design Name: Control Unit
// Module Name: control
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Manages the logic in the ID stage
//
// Dependencies:
//
// Revision:
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
@@ -22,22 +22,25 @@
module control(
input [6:0] opcode,
input [2:0] funct3,
input [6:0] funct7,
input [2:0] aux,
input [6:0] func,
output reg we_reg,
output reg we_mem,
output reg mem_to_reg,
output reg alu_src,
output reg [3:0] alu_op,
output reg branch
output reg branch,
output reg jump
);
localparam OP_R = 7'b0110011;
localparam OP_I = 7'b0010011;
localparam OP_LOAD= 7'b0000011;
localparam OP_STORE=7'b0100011;
localparam OP_BRANCH=7'b1100011;
localparam OP_JAL = 7'b1101111;
// formatos de instrucciones
localparam ALU_R = 7'b0110011;
localparam ALU_I = 7'b0010011;
localparam OP_LOAD = 7'b0000011;
localparam OP_STORE = 7'b0100011;
localparam OP_BRANCH = 7'b1100011;
localparam OP_JAL = 7'b1101111;
localparam OP_JALR = 7'b1100111;
always @(*) begin
we_reg = 0;
@@ -46,12 +49,13 @@ always @(*) begin
alu_src = 0;
alu_op = 4'b0000;
branch = 0;
jump = 0;
case(opcode)
OP_R: begin
ALU_R: begin
we_reg = 1;
alu_src = 0;
case({funct7,funct3})
case({func,aux})
10'b0000000000: alu_op = 4'b0000; // ADD
10'b0100000000: alu_op = 4'b0001; // SUB
10'b0000000111: alu_op = 4'b0010; // AND
@@ -65,16 +69,16 @@ always @(*) begin
endcase
end
OP_I: begin
ALU_I: begin
we_reg = 1;
alu_src = 1;
case(funct3)
case(aux)
3'b000: alu_op = 4'b0000; // ADDI
3'b111: alu_op = 4'b0010; // ANDI
3'b110: alu_op = 4'b0011; // ORI
3'b100: alu_op = 4'b0100; // XORI
3'b001: alu_op = 4'b0101; // SLLI
3'b101: alu_op = (funct7==7'b0000000)?4'b0110:4'b0111; // SRLI/SRAI
3'b101: alu_op = (func==7'b0000000)?4'b0110:4'b1001; // SRLI/SRAI
3'b010: alu_op = 4'b1000; // SLTI
3'b011: alu_op = 4'b1001; // SLTIU
endcase
@@ -82,32 +86,32 @@ always @(*) begin
OP_LOAD: begin
we_reg = 1;
we_mem = 0;
mem_to_reg = 1;
alu_src = 1; // addr = rs1 + immediate
alu_op = 4'b0000;
alu_src = 1;
end
OP_STORE: begin
we_mem = 1;
alu_src = 1; // addr = rs1 + immediate
alu_op = 4'b0000;
alu_src = 1;
end
OP_BRANCH: begin
branch = 1;
alu_src = 0;
alu_op = 4'b0001;
end
OP_JAL: begin
we_reg = 1; // rd <- PC+4
we_reg = 1; // para guardar la dirección de retorno
jump = 1;
end
OP_JALR: begin
we_reg = 1;
alu_src = 1;
alu_op = 4'b0000;
jump = 1;
end
default: begin end
endcase
end

View File

@@ -1,19 +1,19 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name:
// Design Name: Data Memory
// Module Name: dmem
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Stores data
//
// Dependencies:
//
// Revision:
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
@@ -29,12 +29,21 @@ module dmem(
);
reg [31:0] memory[0:255];
reg [31:0] data;
integer i;
initial begin
for (i = 0; i < 256; i = i + 1) begin
memory[i] = 32'b0;
end
end
always @(posedge clk) begin
if (we)
memory[address[9:2]] <= write_data;
data <= memory[address[9:2]];
end
assign read_data = memory[address[9:2]];
assign read_data = data;
endmodule

View File

@@ -0,0 +1,42 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name: EX/ME register
// Module Name: ex_me
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Register between EX/ME stages
//
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ex_me (
input clk, rst,
input we_reg_in, we_mem_in, mem_to_reg_in,
output reg we_reg_out, we_mem_out, mem_to_reg_out,
input [31:0] alu_in, regB_in, pc4_in,
input [4:0] rd_in,
output reg [31:0] alu_out, regB_out, pc4_out,
output reg [4:0] rd_out
);
always @(posedge clk or posedge rst) begin
if (rst) begin
we_reg_out <= 0; we_mem_out <= 0; mem_to_reg_out <= 0;
alu_out <= 0; regB_out <= 0; pc4_out <= 0; rd_out <= 0;
end else begin
we_reg_out <= we_reg_in; we_mem_out <= we_mem_in; mem_to_reg_out <= mem_to_reg_in;
alu_out <= alu_in; regB_out <= regB_in; pc4_out <= pc4_in; rd_out <= rd_in;
end
end
endmodule

View File

@@ -0,0 +1,69 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name: Forwarding
// Module Name: forwarding
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Manages forwarding MUXes selection inputs
//
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module forwarding (
input [4:0] ID_EX_Rs1,
input [4:0] ID_EX_Rs2,
input [4:0] IF_ID_Rs1,
input [4:0] IF_ID_Rs2,
input [4:0] EX_ME_Rd,
input EX_ME_RegWrite,
input [4:0] ME_WB_Rd,
input ME_WB_RegWrite,
output reg [1:0] EX_ForwardA,
output reg [1:0] EX_ForwardB,
output reg [1:0] ID_ForwardA,
output reg [1:0] ID_ForwardB
);
always @(*) begin
EX_ForwardA = 2'b00;
EX_ForwardB = 2'b00;
ID_ForwardA = 2'b00;
ID_ForwardB = 2'b00;
// Bypass A (EX)
if (EX_ME_RegWrite && (EX_ME_Rd != 0) && (EX_ME_Rd == ID_EX_Rs1))
EX_ForwardA = 2'b10;
else if (ME_WB_RegWrite && (ME_WB_Rd != 0) && (ME_WB_Rd == ID_EX_Rs1))
EX_ForwardA = 2'b01;
// Bypass B (EX)
if (EX_ME_RegWrite && (EX_ME_Rd != 0) && (EX_ME_Rd == ID_EX_Rs2))
EX_ForwardB = 2'b10;
else if (ME_WB_RegWrite && (ME_WB_Rd != 0) && (ME_WB_Rd == ID_EX_Rs2))
EX_ForwardB = 2'b01;
// Bypass A (ID)
if (EX_ME_RegWrite && (EX_ME_Rd != 0) && (EX_ME_Rd == IF_ID_Rs1))
ID_ForwardA = 2'b10;
else if (ME_WB_RegWrite && (ME_WB_Rd != 0) && (ME_WB_Rd == IF_ID_Rs1))
ID_ForwardA = 2'b01;
// Bypass B (ID)
if (EX_ME_RegWrite && (EX_ME_Rd != 0) && (EX_ME_Rd == IF_ID_Rs2))
ID_ForwardB = 2'b10;
else if (ME_WB_RegWrite && (ME_WB_Rd != 0) && (ME_WB_Rd == IF_ID_Rs2))
ID_ForwardB = 2'b01;
end
endmodule

View File

@@ -0,0 +1,62 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name: Hazard Unit
// Module Name: hazard
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Manages hazards between memory instructions and any other
//
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module hazard (
input [4:0] IF_ID_Rs1,
input [4:0] IF_ID_Rs2,
input [4:0] ID_EX_Rd,
input ID_EX_MemRead,
input Branch_Taken,
output reg PC_En,
output reg IF_ID_En,
output reg IF_ID_Clr,
output reg ID_EX_Clr
);
always @(*) begin
PC_En = 1'b1;
IF_ID_En = 1'b1;
IF_ID_Clr = 1'b0;
ID_EX_Clr = 1'b0;
// si:
// - se lee de memoria
// - el Rd no es x0
// - el Rd es Rs1 o Rs2
// entonces:
// bloqueamos para que el dato generado en ME lo pueda coger EX
if (ID_EX_MemRead && (ID_EX_Rd != 5'b0) &&
((ID_EX_Rd == IF_ID_Rs1) || (ID_EX_Rd == IF_ID_Rs2))) begin
PC_En = 1'b0;
IF_ID_En = 1'b0;
ID_EX_Clr = 1'b1;
end
// si:
// - salto tomado
// entonces:
// flush síncrono al reg IF/ID
else if (Branch_Taken) begin
IF_ID_Clr = 1'b1;
end
end
endmodule

View File

@@ -0,0 +1,57 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name: ID/EX register
// Module Name: id_ex
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Register between ID/EX stages
//
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module id_ex (
input clk, rst, clr,
// señales de la UC y ALU
input we_reg_in, we_mem_in, mem_to_reg_in, alu_src_in, branch_in, jump_in,
input [3:0] alu_op_in,
output reg we_reg_out, we_mem_out, mem_to_reg_out, alu_src_out, branch_out, jump_out,
output reg [3:0] alu_op_out,
// PC4, A, B, C, Rd
input [31:0] pc4_in, regA_in, regB_in, regC_in,
input [4:0] rs1_in, rs2_in, rd_in,
output reg [31:0] pc4_out, regA_out, regB_out, regC_out,
output reg [4:0] rs1_out, rs2_out, rd_out
);
always @(posedge clk or posedge rst) begin
if (rst || clr) begin
we_reg_out <= 0; we_mem_out <= 0; mem_to_reg_out <= 0;
alu_src_out <= 0; branch_out <= 0; jump_out <= 0; alu_op_out <= 4'b0;
pc4_out <= 0; regA_out <= 0; regB_out <= 0; regC_out <= 0;
rs1_out <= 0; rs2_out <= 0; rd_out <= 0;
end
else begin
we_reg_out <= we_reg_in; we_mem_out <= we_mem_in;
mem_to_reg_out <= mem_to_reg_in; alu_src_out <= alu_src_in;
branch_out <= branch_in; jump_out <= jump_in; alu_op_out <= alu_op_in;
pc4_out <= pc4_in;
regA_out <= regA_in; regB_out <= regB_in; regC_out <= regC_in;
rs1_out <= rs1_in; rs2_out <= rs2_in; rd_out <= rd_in;
end
end
endmodule

View File

@@ -0,0 +1,51 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name: IF/ID register
// Module Name: if_id
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Register between IF/ID stages
//
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module if_id (
input clk,
input rst,
input en,
input clr,
input [31:0] npc_in,
input [31:0] pc4_in,
input [31:0] ir_in,
output reg [31:0] npc_out,
output reg [31:0] pc4_out,
output reg [31:0] ir_out
);
always @(posedge clk or posedge rst) begin
if (rst) begin
npc_out <= 32'b0;
pc4_out <= 32'b0;
ir_out <= 32'b0;
end else if (clr) begin
npc_out <= 32'b0;
pc4_out <= 32'b0;
ir_out <= 32'b0;
end else if (en) begin
npc_out <= npc_in;
pc4_out <= pc4_in;
ir_out <= ir_in;
end
end
endmodule

View File

@@ -1,19 +1,19 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name:
// Design Name: Instruction Memory
// Module Name: imem
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Stores instructions
//
// Dependencies:
//
// Revision:
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
@@ -29,12 +29,21 @@ module imem(
);
reg [31:0] memory[0:255];
reg [31:0] ir;
integer i;
initial begin
for (i = 0; i < 256; i = i + 1) begin
memory[i] = 32'b0;
end
end
always @(posedge clk) begin
if(we)
memory[write_addr] <= write_data;
ir <= memory[address[9:2]];
end
assign instruction = memory[address[9:2]];
assign instruction = ir;
endmodule

View File

@@ -1,37 +1,54 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name:
// Design Name: Immediate Generator
// Module Name: imm_gen
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Retrieves the immediate from the instruction (uses verilog concat)
//
// Dependencies:
//
// Revision:
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module imm_gen(
input [31:0] instr,
input [31:0] instr,
output reg [31:0] imm_out
);
always @(*) begin
case(instr[6:0])
7'b0010011,
7'b0000011:
// Formato I
7'b0010011,
7'b0000011,
7'b1100111:
imm_out = {{20{instr[31]}}, instr[31:20]};
// Formato S
7'b0100011:
imm_out = {{20{instr[31]}}, instr[31:25], instr[11:7]};
// Formato B
7'b1100011:
imm_out = {{19{instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0};
// Formato J
7'b1101111:
imm_out = {{11{instr[31]}}, instr[31], instr[19:12], instr[20], instr[30:21], 1'b0};
// Formato U
7'b0110111,
7'b0010111:
imm_out = {instr[31:12], 12'b0};
default:
imm_out = 32'b0;
endcase

View File

@@ -0,0 +1,42 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name: ME/WB register
// Module Name: me_wb
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Register between ME/WB stages
//
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module me_wb (
input clk, rst,
input we_reg_in, mem_to_reg_in,
output reg we_reg_out, mem_to_reg_out,
input [31:0] alu_in, mem_data_in, pc4_in,
input [4:0] rd_in,
output reg [31:0] alu_out, mem_data_out, pc4_out,
output reg [4:0] rd_out
);
always @(posedge clk or posedge rst) begin
if (rst) begin
we_reg_out <= 0; mem_to_reg_out <= 0;
alu_out <= 0; mem_data_out <= 0; pc4_out <= 0; rd_out <= 0;
end else begin
we_reg_out <= we_reg_in; mem_to_reg_out <= mem_to_reg_in;
alu_out <= alu_in; mem_data_out <= mem_data_in; pc4_out <= pc4_in; rd_out <= rd_in;
end
end
endmodule

View File

@@ -1,19 +1,19 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name:
// Design Name: Program Counter
// Module Name: pc
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Points to the next instruction
//
// Dependencies:
//
// Revision:
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//

View File

@@ -1,19 +1,19 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Company: nope
// Engineer: Jose
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name:
// Design Name: Register File
// Module Name: regfile
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Stores temporal values
//
// Dependencies:
//
// Revision:
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
@@ -29,6 +29,13 @@ module regfile(
reg [31:0] regs[0:31];
integer i;
initial begin
for (i = 0; i < 32; i = i + 1) begin
regs[i] = 32'b0;
end
end
assign read_data_1 = (rs1 == 0) ? 0 : regs[rs1];
assign read_data_2 = (rs2 == 0) ? 0 : regs[rs2];

View File

@@ -1,135 +1,197 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/20/2026 09:21:52 AM
// Design Name:
// Module Name: top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`default_nettype none
module top(
input clk, rst,
input [31:0] uart_data,
output [31:0] pc_out, alu_out, mem_data
module top (
input clk,
input rst,
output [1:0] leds,
output [31:0] debug
);
// = PC ===================================
wire [31:0] pc_next, pc;
wire branch_taken;
// ==========================================
// ETAPA IF
// ==========================================
wire [31:0] npc_IF, pc4_IF, ir_IF, next_pc_IF, pc_stall;
wire PC_En, IF_ID_En, IF_ID_Clr;
pc pc_inst(
.clk(clk),
.rst(rst),
.next_pc(pc_next),
.imem_addr(pc_curr)
);
assign next_pc_IF = (Branch_Taken) ? branch_target_ID : pc4_IF;
assign pc4_IF = npc_IF + 4;
assign pc_stall = (PC_En) ? next_pc_IF : npc_IF;
assign pc_out = pc_curr;
// ========================================
pc u_pc (
.clk(clk),
.rst(rst),
.next_pc(pc_stall),
.imem_addr(npc_IF)
);
// = IMEM =================================
wire [31:0] instr;
imem u_imem (
.clk(clk), .address(npc_IF), .we(1'b0),
.write_data(32'b0), .write_addr(8'b0), .instruction(ir_IF)
);
imem imem_inst(
.address(pc_curr),
.instruction(instr)
);
// ========================================
// ==========================================
// REGISTRO IF/ID
// ==========================================
wire [31:0] npc_ID, pc4_ID, ir_ID;
// = DECODE ===============================
wire [6:0] opcode = instr[6:0];
wire [4:0] rd = instr[11:7];
wire [2:0] funct3 = instr[14:12];
wire [4:0] rs1 = instr[19:15];
wire [4:0] rs2 = instr[24:20];
wire [6:0] funct7 = instr[31:25];
// ========================================
if_id u_if_id (
.clk(clk), .rst(rst), .en(IF_ID_En), .clr(IF_ID_Clr),
.npc_in(npc_IF), .pc4_in(pc4_IF), .ir_in(ir_IF),
.npc_out(npc_ID), .pc4_out(pc4_ID), .ir_out(ir_ID)
);
// regfile mux
wire [31:0] reg_write_data;
assign reg_write_data = mem_to_reg ? dmem_read_data : alu_out;
// ==========================================
// ETAPA ID
// ==========================================
wire [4:0] rs1_ID = ir_ID[19:15];
wire [4:0] rs2_ID = ir_ID[24:20];
wire [4:0] rd_ID = ir_ID[11:7];
wire [31:0] imm_ID, regA_ID, regB_ID;
// Señales de Control
wire we_reg_ID, we_mem_ID, mem_to_reg_ID, alu_src_ID, branch_ID, jump_ID;
wire [3:0] alu_op_ID;
wire Branch_Taken;
wire [31:0] branch_target_ID;
// = REGFILE ===============================
wire [31:0] reg_r1, reg_r2;
wire we_reg;
control u_control (
.opcode(ir_ID[6:0]), .aux(ir_ID[14:12]), .func(ir_ID[31:25]),
.we_reg(we_reg_ID), .we_mem(we_mem_ID), .mem_to_reg(mem_to_reg_ID),
.alu_src(alu_src_ID), .alu_op(alu_op_ID), .branch(branch_ID), .jump(jump_ID)
);
wire [31:0] write_data_WB;
regfile regfile_inst(
.clk(clk),
.regwrite(we_reg),
.rs1(rs1),
.rs2(rs2),
.rd(rd),
.write_data(reg_write_data),
.read_data_1(reg_r1),
.read_data_2(reg_r2)
);
// ========================================
regfile u_regfile (
.clk(~clk),
.regwrite(we_reg_WB), .rs1(rs1_ID), .rs2(rs2_ID), .rd(rd_WB),
.write_data(write_data_WB), .read_data_1(regA_ID), .read_data_2(regB_ID)
);
// = IMMGEN ===============================
wire [31:0] imm_out;
imm_gen u_imm_gen (
.instr(ir_ID), .imm_out(imm_ID)
);
imm_gen imm_gen_inst(
.instr(instr),
.imm_out(imm_out)
);
// ========================================
wire [1:0] ID_ForwardA, ID_ForwardB;
wire [31:0] cmp_A = (ID_ForwardA == 2'b10) ? alu_res_ME : (ID_ForwardA == 2'b01) ? write_data_WB : regA_ID;
wire [31:0] cmp_B = (ID_ForwardB == 2'b10) ? alu_res_ME : (ID_ForwardB == 2'b01) ? write_data_WB : regB_ID;
// salto si JAL/JALR o si condición de BRANCH ok
assign Branch_Taken = jump_ID | (branch_ID & (cmp_A == cmp_B));
// MUX DirSalto
wire is_jalr = (ir_ID[6:0] == 7'b1100111);
wire [31:0] base_salto = is_jalr ? cmp_A : npc_ID;
assign branch_target_ID = (base_salto + imm_ID) & ~32'b1;
// = CONTROL ===============================
wire we_mem, mem_to_reg, alu_src;
wire [3:0] alu_op;
// detector de riesgos
wire ID_EX_Clr;
hazard u_hazard (
.IF_ID_Rs1(rs1_ID), .IF_ID_Rs2(rs2_ID),
.ID_EX_Rd(rd_EX), .ID_EX_MemRead(mem_to_reg_EX),
.Branch_Taken(Branch_Taken),
.PC_En(PC_En), .IF_ID_En(IF_ID_En), .IF_ID_Clr(IF_ID_Clr), .ID_EX_Clr(ID_EX_Clr)
);
control control_inst(
.opcode(opcode),
.funct3(funct3),
.funct7(funct7),
.we_reg(we_reg),
.we_mem(we_mem),
.mem_to_reg(mem_to_reg),
.alu_src(alu_src),
.alu_op(alu_op),
.branch(branch_taken)
);
// ========================================
// ==========================================
// REGISTRO ID/EX
// ==========================================
wire [31:0] pc_EX, pc4_EX, regA_EX, regB_EX, imm_EX;
wire [4:0] rs1_EX, rs2_EX, rd_EX;
wire we_reg_EX, we_mem_EX, mem_to_reg_EX, alu_src_EX, branch_EX, jump_EX;
wire [3:0] alu_op_EX;
// = ALU ==================================
wire [31:0] alu_b = alu_src ? imm_out : reg_r2;
id_ex u_id_ex (
.clk(clk), .rst(rst), .clr(ID_EX_Clr),
.we_reg_in(we_reg_ID), .we_mem_in(we_mem_ID), .mem_to_reg_in(mem_to_reg_ID),
.alu_src_in(alu_src_ID), .branch_in(branch_ID), .alu_op_in(alu_op_ID),
.jump_in(jump_ID),
.we_reg_out(we_reg_EX), .we_mem_out(we_mem_EX), .mem_to_reg_out(mem_to_reg_EX),
.alu_src_out(alu_src_EX), .branch_out(branch_EX), .alu_op_out(alu_op_EX),
.jump_out(jump_EX),
.pc4_in(pc4_ID), .regA_in(regA_ID), .regB_in(regB_ID), .regC_in(imm_ID),
.rs1_in(rs1_ID), .rs2_in(rs2_ID), .rd_in(rd_ID),
.pc4_out(pc4_EX), .regA_out(regA_EX), .regB_out(regB_EX), .regC_out(imm_EX),
.rs1_out(rs1_EX), .rs2_out(rs2_EX), .rd_out(rd_EX)
);
alu alu_inst(
.A(reg_r1),
.B(alu_b),
.sel(alu_op),
.R(alu_out)
);
// ========================================
// ==========================================
// ETAPA EX
// ==========================================
wire [1:0] EX_ForwardA, EX_ForwardB;
wire [31:0] alu_A, alu_B_temp, alu_B, alu_res_EX_raw, alu_res_EX;
wire alu_zero_EX;
wire [31:0] alu_res_ME;
// = DMEM =================================
wire [31:0] dmem_read_data;
forwarding u_forwarding (
.ID_EX_Rs1(rs1_EX), .ID_EX_Rs2(rs2_EX), .IF_ID_Rs1(rs1_ID), .IF_ID_Rs2(rs2_ID),
.EX_ME_Rd(rd_ME), .EX_ME_RegWrite(we_reg_ME), .ME_WB_Rd(rd_WB), .ME_WB_RegWrite(we_reg_WB),
.EX_ForwardA(EX_ForwardA), .EX_ForwardB(EX_ForwardB),
.ID_ForwardA(ID_ForwardA), .ID_ForwardB(ID_ForwardB)
);
dmem dmem_inst(
.clk(clk),
.we(we_mem),
.address(alu_out),
.write_data(reg_r2),
.read_data(dmem_read_data)
);
assign alu_A = (EX_ForwardA == 2'b10) ? alu_res_ME : (EX_ForwardA == 2'b01) ? write_data_WB : regA_EX;
assign alu_B_temp = (EX_ForwardB == 2'b10) ? alu_res_ME : (EX_ForwardB == 2'b01) ? write_data_WB : regB_EX;
assign alu_B = (alu_src_EX) ? imm_EX : alu_B_temp;
assign mem_data = dmem_read_data;
// ========================================
alu u_alu (
.A(alu_A), .B(alu_B), .sel(alu_op_EX), .R(alu_res_EX_raw), .zero(alu_zero_EX)
);
// PC increment
assign pc_next = branch_taken ? (pc_curr + imm_out) : (pc_curr + 4);
// MUX post-ALU para guardar PC+4 si es un salto (JAL/JALR)
assign alu_res_EX = jump_EX ? pc4_EX : alu_res_EX_raw;
endmodule
// ==========================================
// REGISTRO EX/ME
// ==========================================
wire [31:0] regB_ME, pc4_ME;
wire [4:0] rd_ME;
wire we_reg_ME, we_mem_ME, mem_to_reg_ME;
ex_me u_ex_me (
.clk(clk), .rst(rst),
.we_reg_in(we_reg_EX), .we_mem_in(we_mem_EX), .mem_to_reg_in(mem_to_reg_EX),
.we_reg_out(we_reg_ME), .we_mem_out(we_mem_ME), .mem_to_reg_out(mem_to_reg_ME),
.alu_in(alu_res_EX), .regB_in(alu_B_temp), .pc4_in(pc4_EX), .rd_in(rd_EX),
.alu_out(alu_res_ME), .regB_out(regB_ME), .pc4_out(pc4_ME), .rd_out(rd_ME)
);
// ==========================================
// ETAPA ME & WB
// ==========================================
wire [31:0] mem_data_ME;
dmem u_dmem (
.clk(clk), .we(we_mem_ME), .address(alu_res_ME),
.write_data(regB_ME), .read_data(mem_data_ME)
);
wire [31:0] alu_res_WB, mem_data_WB, pc4_WB;
wire [4:0] rd_WB;
wire we_reg_WB, mem_to_reg_WB;
me_wb u_me_wb (
.clk(clk), .rst(rst),
.we_reg_in(we_reg_ME), .mem_to_reg_in(mem_to_reg_ME),
.we_reg_out(we_reg_WB), .mem_to_reg_out(mem_to_reg_WB),
.alu_in(alu_res_ME), .mem_data_in(mem_data_ME), .pc4_in(pc4_ME), .rd_in(rd_ME),
.alu_out(alu_res_WB), .mem_data_out(mem_data_WB), .pc4_out(pc4_WB), .rd_out(rd_WB)
);
assign write_data_WB = (mem_to_reg_WB) ? mem_data_WB : alu_res_WB;
// ==========================================
// DEBUG
// ==========================================
assign leds[0] = Branch_Taken; // se enciende cuando hay salto
assign leds[1] = ID_EX_Clr; // se enciende en bloqueos
assign debug = {
alu_res_EX[15:0],
rd_WB,
rs1_ID,
npc_IF[7:2]
};
endmodule