I started with HDLBits [0], which has a bunch of problems that you solve by writing verilog that is then run in a simulator. It starts with simple gates and such, and then builds up from there.
I also purchased a dev board from NANDLand [1] and have been going through the tutorials written for their board. A lot of code is provided for you in the tutorials, but I've been reimplementing it all from scratch as part of the learning process. The later tutorials cover things like UART send/receive and simple VGA.
I'm not affiliated with either site, but have found both to be helpful. Good luck!
My approach was to implement very simple interfaces without using libraries.
Simulators are nice and all, but you won't feel the magic with these.
There's many cheap options[0] these days, but I'd suggest something based on iCE40[1], as they are cheap and have the most mature support in the open stack thanks to icestorm[2].
Excellent, dirt-cheap options include icestick, tinyfpga bx and blackice mx. These are all <$70.
[0]: https://joelw.id.au/FPGA/CheapFPGADevelopmentBoards