prototype works
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user