I have a deep distrust of the the whole "tell us how you want it to behave and we'll figure out what you intended the hardware to look like" method of inferring hardware from HDL.
Ah, that's because of three things
1) nobody explained you how a logic synthesizer works
2) nobody explained you how to use the synthesizer to do EXACTLY what you want it to do.
3) nobody explains what scheduling is. It is the most powerful part of both Verilog and VHDL yet it is almost never covered ... For some reason they want to teach you procedural programming and treating this as a software language bolted on hardware. Scheduling is the real hardware access.
I agree that most logic course, if not all, handle only the abstract part. There is ZILCH attention to the synthesis part. There are two extremely good books that can teach you how it works:
Bhasker's Verilog HDL for Synthesis <- make sure you get this one. he has another one that is just plain verilog
Smith's HDL programming. This one is out of print. it is a humongous book printed on A4 format that covers Verilog and VHDL side by side. it contains tons of examples and shows you the schematic output for each of the constructs. it pops up from time to time used on amazon but is very expensive.
In short :
Here is how a synthesizer works :
module counter (input [3:0] data_in, input clk,reset,load,preset, output reg [3:0] data_out)
i just defined a counter that has a bunch of inputs and outputs : data_in0 to data_in3 , clk reset load preset and the 4 outputs data_out0 to data_out3
The synthesizer reads this block and plonks down the inputs and outputs. since the outputs are defined as REG it will plonk down a flipflop per output and tie the Q output to the pin.
module counter (input [3:0] data_in, input clk,reset,load,preset, output reg [3:0] data_out)
always @(posedge clk) begin
data_out<=data_out +1;
if (preset) data_out <=9;
if (load) data_out <=data_in;
if (reset) data_out <=0;
end
endmodule
the synthesizer reads the next line : always if you see a rising edge of CLK you need to do something. so it will take CLK and connect it to the flipflops already placed ( the output ones) it does not do anything else as it has not had any other instructions.
then it reads the next line : data_out = data_out + 1.
so it will take the output of the flipflops , send them through an adder logic and feed that back to the D inputs of the flipflops.
then it reads the next line if "(preset)" so it plonks down a multiplexer under control of the preset signal. and it reads on "data_out <= 9"
so it snips off the wires going to the flipflop's D input and connects them through the multitplexer. if preset is 0 then the mulitplexer connects A to X so whatever logic was already created still works perfectly fine. if preset is 1 then the B input is connected to X and the descirption said to apply '9' in this case. so it hardwires 1001 to that mux input. done.
next line : if (load) data_out <= data_in. ah. we snip off the data_inputs of the flipflops again and throw in another mux the A inouts come from whatever was there , the B inputs get tied to Data_in
so essentially you keep cascading multiplexers. multiplexers are a very simple logic equation A.EN + B.not(EN)
so this cascade of multiplexers becomes a very simple logic equasion after minimizing. there are no secrets, no hidden paths. everything is defined and it will work exactly as you have described it.