`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/06/06 15:26:45
// Design Name: 
// Module Name: Datapath
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module DataPath (
    input  wire        clk,
    input  wire        rst,
    input  wire [31:0] Instr,
    input  wire        srcReg,
    input  wire        ALUBsrc,
    input  wire        MemToReg,
    input  wire        RegWr,
    input  wire        MemWrEn,
    input  wire [2:0]  ALUop,
    input  wire [1:0]  Extop
);
    wire [4:0] rd = Instr[4:0];
    wire [4:0] rj = Instr[9:5];
    wire [4:0] rk = Instr[14:10];
    wire [31:0] immExt;
    Ext u_ext (
        .DataIn (Instr),
        .Extop  (Extop),
        .DataOut(immExt)
    );
    wire [4:0] Rb_sel = srcReg ? rd : rk;
    wire [31:0] busA, busB_reg;
    wire [31:0] WriteData;
    Registers u_regs (
        .clk  (clk),
        .RegWr(RegWr),
        .Ra   (rj),
        .Rb   (Rb_sel),
        .Rw   (rd),
        .busW (WriteData),
        .busA (busA),
        .busB (busB_reg)
    );
    wire [31:0] aluB = ALUBsrc ? immExt : busB_reg;
    wire [31:0] aluResult;
    wire        aluZero;
    ALU u_alu (
        .a      (busA),
        .b      (aluB),
        .op     (ALUop),
        .result (aluResult),
        .Zero   (aluZero)
    );
    wire [31:0] ramDataOut;
    DataRAM u_dram (
        .clk     (clk),
        .MemWrEn (MemWrEn),
        .addr    (aluResult),
        .data_in (busB_reg),
        .data_out(ramDataOut)
    );
    assign WriteData = MemToReg ? ramDataOut : aluResult;
endmodule