http://people.cs.georgetown.edu/~squier/Teaching/HardwareFundamentals/LC3-trunk/docs/LC3-uArch-PPappendC.pdfLook at Figure C3 for a block diagram of the LC3 CPU. The CPU isn't the point of this reply, the diagram is.
Notice the number of MUXes: MARMUX, PCMUX, ADDR1MUX, ADDR2MUX, SR2MUX, INMUX and that MUX with the MIOEN control signal. You would think that being able to code MUXen is an important task - and it is! There's a straight out adder and an ALU - coding those would be the next topic. The adder is trivial and the ALU is pretty simple. We also have a register file with is actually two files (arrays) in parallel. When we load a register, we write both copies but we can read them out separately so we can do R3 = R1 + R2 in one cycle. We just read R1 from one copy and R2 from the other copy and present them to the ALU (and the SR2MUX).
These are the kinds of things you need to learn how to code. All digital systems are built from these basic blocks and the complexity of a system is just a count of the number of blocks.
On page 2 there is a transition diagram. You use that to create the Finite State Machine that makes the CPU work. Every numbered state is duplicated exactly in some HDL and, in my case, I used an integer for the state type so I could match the state numbers on the diagram. It takes a little time and thought to realize that every control signal is generated in that state machine. Once you think about it, it's both obvious and brilliant!
Find a tutorial that teaches you how to code an FSM. I prefer the two process approach, the one process and three process approaches will also work. You have no idea what I'm going on about but don't worry! It will be covered in great detail when you start on the tutorials. Hint: Don't forget to provide default values for all outputs of the two and three process models. Again, this will be discussed in the tutorial (if it is worthwhile).
There's nothing on that page that resembles C++ although I could create a class for every block type and write some sequential code that would do in software what this CPU does in hardware. It might even be an interesting experiment. Hint: It's been done before... My PDP11/70s are software emulations running on a Raspberry Pi and they are faster than the real hardware. No, I didn't write the code.
https://obsolescence.wixsite.com/obsolescence/pidp-11Bottom line: Find tutorials that will teach you how to code the basic blocks. We just keep using the same blocks, over and over. Different signals, different widths but, fundamentally, the same blocks.
Here are a couple of example MUXen:
--PC Mux Control
process(PCplusOne, PCadderOutput, mBus, PCSelect)
begin
case PCSelect is
when PCplus1 => PCmuxOutput <= PCplusOne;
when PCadder => PCmuxOutput <= PCadderOutput;
when PCmBus => PCmuxOutput <= mBus;
when others => PCmuxOutput <= (others => '0');
end case;
end process;
-- MAR Mux Control
process(PCadderOutput, Zext, MARSelect)
begin
case MARSelect is
when MARadder => MARmuxOutput <= PCadderOutput;
when MARzext => MARmuxOutput <= Zext;
when others => MARmuxOutput <= (others => '0');
end case;
end process;
See how straightforward this stuff is? It's the same code, over and over!