//  *********************************************************************************************
//  Project Version  : v1.0
//  Project          : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
//  -----
//  Copyright (c)    : 2025 Fraunhofer IIS, Department IDS
//  Created          : 12.Jun.2025  by Lund University [commit 5b1e415]
//  Last Modified    : 23.Oct.2025  by Hussein Elzomor [commit 2f8f03d]
//  -----
//  HISTORY          : Date         By         Comments
//                     -----------  ---------  -------------------------------------------------
//                     15.Oct.2025  H.Elzomor  Renamed file and module from soc to cpu
//                     15.Oct.2025  H.Elzomor  Added an initial condition for clk_12p5
//  *********************************************************************************************



module cpu (
  output logic[7:0]  led,
  input  logic[6:0]  btn,
  input  logic       clk_25mhz,
  input logic scan_mode				//for defining if we are in scan or in functional mode
);

  // Local Signals
    // Clock & Reset
    logic       clk;
    logic       clk12p5;
    logic       reset;
    // PC
    logic[31:0] CurrentPC;
    logic[31:0] JumpOrBranchPC;
    logic       JumpOrBranch;
    logic[31:0] NextPC;
    // Memory
    logic[31:0] DAddr;
    logic[31:0] WData;
    logic[31:0] RData;
    logic[31:0] Instruction;
    logic       WrMem;
    logic[1:0]  DWidth;
    // Register File;
    logic[4:0]  Rs1;
    logic[4:0]  Rs2;
    logic[4:0]  Rd;
    logic[31:0] RRs1;
    logic[31:0] RRs2;
    logic[31:0] WRd;
    logic       WrReg;
    // Protection
    logic       Illegal;

  // Logic
    // Clock (12.5MHz)
    //assign clk = scan_mode ? clk_25mhz : clk12p5;
    assign clk = clk_25mhz;

//    always_ff @(posedge clk_25mhz) begin
//    	if (reset)
//       		clk12p5 <= 1'b0;
//    	else if (!scan_mode)
//        	clk12p5 <= ~clk12p5;
//    end
    // Reset
    assign reset = ~btn[0];

    // LED
    assign led[0]    = Illegal;
    assign led[1]    = WrMem;
    assign led[7:2]  = NextPC[7:2];

  // Module Instantiation
    // Decoder
    decoder theDecoder (
        // PC
        .CurrentPC(CurrentPC),
        .JumpOrBranchPC(JumpOrBranchPC),
        .JumpOrBranch(JumpOrBranch),
        // Memory
        .DAddr(DAddr),
        .WData(WData),
        .RData(RData),
        .Instruction(Instruction),
        .WrMem(WrMem),
        .DWidth(DWidth),
        // Register File
        .Rs1(Rs1),
        .Rs2(Rs2),
        .Rd(Rd),
        .RRs1(RRs1),
        .RRs2(RRs2),
        .WRd(WRd),
        .WrReg(WrReg),
        // Protection
        .Illegal(Illegal)
    );

    // Register File
    reg_file theRegisters (
        .Rs1(Rs1),
        .Rs2(Rs2),
        .Rd(Rd),
        .RRs1(RRs1),
        .RRs2(RRs2),
        .WRd(WRd),
        .WrReg(WrReg),
        .reset(reset),
        .clk(clk)
    );

    // PC
    pc thePC (
        .CurrentPC(CurrentPC),
        .JumpOrBranchPC(JumpOrBranchPC),
        .JumpOrBranch(JumpOrBranch),
        .NextPC(NextPC),
        .reset(reset),
        .clk(clk)
    );

    // Main Memory
    main_mem #(
        .MEM_INIT_FILE("") // Memory loading driven from the TB
    ) theMem (
        .DAddr(DAddr),
        .IAddr(NextPC),
        .DWData(WData),
        .DRData(RData),
        .IRData(Instruction),
        .DWE(WrMem),
        .DWidth(DWidth),
        .reset(reset),
        .clk(clk)
    );

endmodule
