That's interesting. So there is a contract in there somewhere where the LHS relies on the RHS being fixed at some time and the subsequent assignment propagating to the LHS.
I don't know how a FF with feedback actually guarantees this behaviour but it must do otherwise shift registers wouldn't work!
In my example above the feedback is derived by a continuous net assignment ..
E.g.
feedback = out[0] ^ out[2]
Which gives an interesting mix of combinatorial and sequential in the assignment of the register.
This is obviously a trivial case but it is interesting that you mention the implicit rules being applied to the synthesis... I guess I have a lot to learn.
Thanks
You need to understand how synchronous logic is described in Verilog. You will use synchronous logic to design this LFSR. Let's code up a simple (standard) shift register, which shifts left on each tick of the clock.
reg [7:0] sr;
reg inbit;
always @(posedge clk or negedge rst_l) begin // 1
if (~rst_l) begin // 2
sr <= 0; // 3
end
else begin // 4
sr<= { sr[6:0], inbit }; // 5
end
end
Let's look at this in detail.
Line 1 is the start of the block and includes the sensitivity list. The sensitivity list details all signals that trigger the block. Changes on any other signals are ignored. In this case, our block is sensitive to the rising edge of the clock and the falling edge of an asynchronous reset.
Line 2: test for the assertion of the async reset. How do we know it's an asynchronous reset? It doesn't care about the clock. And we wrote it first in our block, so it has precedence over the clock. If the reset is low, then the shift register is cleared and the block suspends until the next event on the sensitivity list. Do note the use of the
<= non-blocking assignment operator. it's not the same as the standard blocking assignment
= and "non-blocking" means that the assignment is scheduled and could be overwritten if there is a later assignment to the same signal in the block.
The last assignment wins. It is vital that you understand the difference. "Blocking" means that the left-hand-side signal takes on the new value
immediately and in real hardware with a flip-flop, that is
not what happens.
Also note that in a synchronous system, the clock is always running. You can -- and likely will -- get a rising edge of clk when the reset is asserted. The code above says, "OK, fine, I saw a rising edge on the clock. But reset is active, so I will clear the shift register and basically ignore the clock." This is exactly the behavior you want.
Line 3 is where we clear the shift register.
Line 4: "else." Since the block is triggered by only two events -- rising clock, falling reset -- and we've already tested for the assertion of reset, then the only possible reason the block was triggered is because we saw the clock rising edge.
Line 5: on the clock rising edge: look at the
current state of the signals
sr and
inbit. What are their values at the instant the clock edge occurred? Take those values and use them to schedule an assignment to
sr. And when you've finished evaluating
all right-hand sides of all statements in your block,
sr is updated and now has the new value you assigned.
Since our block is sensitive only to the clock and reset, the change in the value of
sr does not trigger the block and all is well.
Really, all of the above is fundamental Verilog and you
must understand it if you are to be successful.
(Also, VHDL works the same way, with the exception that all assignments are non-blocking unless you specifically use variables, and variables don't exist outside of the process in which they are declared.)
Hope this helps.