Unveiling UVM in SystemVerilog language: From Building UVM Agents to Functional Coverage and Debugging Techniques