Following that thread with interest as it's broadly similar to my immediate objective, I'm simultaneously trying to understand the code in it but not be influenced by it so I can work my own 'thing' out, if that makes any sense?
I had been struggling to get out of the mindset which I'd developed from years of programming embedded micros and was reading it as a program instead of independent blocks, now it's making more sense as a collection of 'code' that works concurrently and indeed may not even talk to other blocks...
Your getting there / the idea.
The lines of code do not follow in order like instructions in a 'C' program. Some simplification:
------------------------------------------
always @(posedge clk) begin
Every equation written inside this always which uses a:
'a
<= (equation) ;'
where the 'a' is a register are all 'D' flipflops which are all synchronously clocked by the positive edge of the input 'clk'
the '
<=' is known as a blocking function. It means the the destination 'a' register is clocked by the positive edge of the 'clk' input instead of a simple '=' where 'a' would be treated as a simple integer, immediate in value, unclocked, no D-flipflop, just the raw and/or/xor gates to generate the mathematical equation.
end
-----------------------------------------
If this case, the equation may contain the outputs and inputs of any other registers going through boolean operations and even regular math like add, subtract and multiply, as well as bit shifts.
Inside that always block, you may have 100s of such equations, all triggered in parallel every positive edge of 'clk'.
Next, the 'if' statement:
------------------------------------------
always @(posedge clk) begin
if (adr_input == 2) begin
'a <= (equation) ;'
end
end
-----------------------------------------
The difference here is that all the clocked register flipflops inside the 'IF's 'begin' and 'end' basically are D flipflops with a 'clock enable' input. They are always being clocked like all the other flipflops inside the 'always @(posedge clk)' except the boolean equation inside the 'IF' statement generates a set of logic which feeds any and all 'a <= (equation) ;' D filpflops clock enable' port inside that IF's begin and end.
To see how you can wire something so simple like a 4 tap low pass filter:
-------------------------------------
input wire [7:0] input data;
reg [7:0] tap1, tap2, tap3 ;
output reg [7:0] output_data;
always @(posedge clk) begin
tap1 <= input_data;
tap2 <= tap1;
tap3 <= tap2;
output_data <= (input_data + tap1 + tap2 + tap3) >> 2 ;
end
------------------------------------
Now there are better ways to write this, but here is a simple example. The order in which I typed these lines into my verilog code doesn't matter at all. What you are looking at is how the D flipflops are wired together.
At every single clock, a new 8 bit byte is loaded into tap1, while tap1's old bye is loaded into tap2. And while this is all happening, the current input with tap1 through tap3's old byte are all summed together, with a sum shifted by 2 bits into the output_data's register flipflops 'D' inputs. So if your clock is 200Mhz, you are also getting 200 million output_data's a second.
You are looking at a text description on how to wired a breadboard with a bunch of D flipflops all clocked in parallel, with a set of logic gate doing the math to feed the D inputs. Any of the register names you use in the math expression take their values from those D flipflop's 'Q' outputs which wont change again until the next clock.