Verilog and ASM implementation - verilog

In the question below,
The ASM chart shows that value of q_next is compared to 0 to proceed to next state but before q_next is compared, the value of q is already updated with q_next, so if we compare the value of q with 0, will the results be same in terms of timing and other parameters?
Also what should be the types of q_next and q ? Should they be reg or wire?
I have attached the screenshots of the ASM chart and the Verilog code. I also don't understand the timing implications of conditional box (in general, can't we put the output of a conditional box in a separate state which doesn't depend on the output of the conditional box)?,
like when in the wait1 state, we check the value of sw and if true, we decrement the counter and then check if counter has reached to zero and then asser db_tick. I want to understand the time flow when we move from wait1 and increment counter and assert db_tick. Are there any clock cycles involved between these stages, that is moving from a state to a conditional box?
Also in the verilog code, we use q_load and q_tick to control the counter. Why these signals are used when we can simply control the counter in the states?
Is it done to make sure that the FSM (control path) controls the counter (data path)? Please explain. Thanks in advance.

In the question below, the ASM chart shows that value of q_next is
compared to 0 to proceed to next state but before q_next is compared,
the value of q is already updated with q_next, so if we compare the
value of q with 0, will the results be same in terms of timing and
other parameters?
No. When q_next has a value of 0, q still contains a value of 1 until it's updated on the next positive clock edge. If you check for q==0, you will spend an extra clock cycle in each wait state.
Also what should be the types of q_next and q? Should they be reg or
wire?
Either. reg types (like q_reg) mean they're assign a value in an always block, while wire types (like q_next) are assigned using the assign statement or as the output of a submodule.
I also don't understand the timing implications of conditional box (in
general, can't we put the output of a conditional box in a separate
state which doesn't depend on the output of the conditional box)?,
like when in the wait1 state, we check the value of sw and if true, we
decrement the counter and then check if counter has reached to zero
and then asser db_tick. I want to understand the time flow when we
move from wait1 and increment counter and assert db_tick.
Here's the flow of operations for a single clock cycle while in the wait1 state:
Is SW==1? If not, do nothing else, and go to state zero. Those operations will be done on the next cycle.
If SW==1, compute q_next, and assign that value to q for the next cycle.
Is q_next==0? If not, remain in wait1 for the next cycle and repeat.
Otherwise, assert db_tick=1 for this clock cycle, and go to state one.
If you split up the two conditionals into two separate states, counting down to 0 will take twice as long.
Are there any clock cycles involved between these stages, that is
moving from a state to a conditional box?
Based on the diagram, all operations (comparing sw, subtracting from q, etc) within a given state - that is, one of the dotted-line boxes - are performed in a single clock cycle.
Also in the verilog code, we use q_load and q_tick to control the
counter. Why these signals are used when we can simply control the
counter in the states? Is it done to make sure that the FSM (control
path) controls the counter (data path)?
You could do it that way too. Just be sure to assign a value to q_next in the default case to prevent latching. Splitting the data path and control path into separate always blocks/assign statements does improve readability though, IMO.

Related

Understanding Verilog Code with two Clocks

I am pretty new to Verilog
and I use it to verify some code from a simulation program.
Right now I am struggeling if a verilog code snippet because the simulation programm uses 2 clocks ( one system clock and a pll of this ) where two hardware componentes work together, thus synchronize each other:
module something (input data)
reg vid;
always #(posegde sys_clk)
vid <= data;
always #(posegde pll_clk)
if (vid)
// do something
When reading about non blocking assignments it says the evaluation of the left-hand side is postponed until other evaluations in the current time step are completed.
Intuitive I thought this means they are evaluated at the end of the time step, thus if data changes from 0 to 1 in sys_clk tick "A", this means at the end of "A" and the beginning of next sys_clk tick this value is in vid and so only after "A" the second always block ( of pll_clk) can read vid = 1
Is this how it works or did i miss something ?
Thank you :)
In this particular case it means that
if posedge sys_clk and pll_clk happen simultaneously then vid will not have a chance to update before it gets used in the pll_clk block. So, if vid was '0' before the clock edges (and is updated to '1' in the first block), it will still be '0' in the if statement of the second block. This sequence is guaranteed by use of the non-blocking assignment in the first block
if the posedges are not happening at the same time, then the value of vid will be updated at posedge sys_clk and picked up later at the following posedge of pll_clk.
In simulation non-blocking assignment guarantees that the assignment itself happens after all the blocks are evaluated in the current clock tick. It has nothing to do with the next clock cycle. However, the latter is often used in tutorials to illustrate a particular single-clock situation, creating confusion.
Also being simultaneous is a simulation abstraction, meaning that both edges happen in the same clock tick (or within a certain small time interval in hardware).

Should case variable be increment atomically?

I'm writing Verilog code which iterate through the states of an FSM in order to perform a calculation in steps. The application is done and running as desired, but for efficiency requirements I'm wondering the following.
I'm updating the case variable, "i", atomically as shown in excerpt 1 below, is this at all necessary to ensure it does not skip a step in my FSM?
Or is the method in excerpt 2 equally safe to run without a step being missed?
As excerpt two is twice as fast as excerpt one.
Before it is asked. Everything runs, everything is initialised prior to use, counters reset to 0 when finished and encased in a module.
Code for atomic update of "i"
always #(posedge clk) begin
if( ITERATE ) i = i + 1; //Atomic increment of variable
else begin
case( i )
0: ....
.: ....
n: The case internals are not pertinent
endcase
end
ITERATE = !ITERATE; //Trigger for atomic update of i
end
Code for non-atomic update of "i"
always #(posedge clk) begin
case( i )
0: ....
.: ....
n: The case internals are not pertinent
endcase
i = i + 1; //Non-atomic increment of variable
end
In both cases your always blocks are executed only once per rising edge of clk. They will not be re-evaluated in the same delta cycle (unless you have glitches in clk itself).
The code inside any always block is executed sequentially as in other programming languages.
So, according to your samples, the first one will increment 'i' every second clock edge, while the second one will increment it every clock edge.
I'm updating the case variable, "i", atomically as shown in excerpt 1 below, is this at all necessary to ensure it does not skip a step in my FSM?
I am not sure what you mean here, but i will be incremented one by one without skipping and the case statement in your fsm will have a chance to react to every value of 'i' in both cases. There will be a difference in timing due to your use of ITERATE in the first sample. Also, in the first example i will be incremented before the case statement and in the second sample, after. This is the other difference.
BTW, word atomic does not apply to any of the cases. What did you mean there?
Also note that you did not write your state machine according to general recommendations, splitting state and transition logic, also you most-likely misused blocking assignments in your samples. These probably are acceptable code samples for test bench, but they might not be good for RTL.

Frank Vahid - Digital design - High level state machine write to storage example

I am self-teaching myself VHDL, and took this answer's advice by starting with Frank Vahid's Digital Design (2nd edition).
On page 254 (link) he explains that updates to storage items occur on the next rising clock edge, therefore, at the end of a state's clock cycle. This is explained in figure 5.14 using the "Jreg" storage item, the behavior of which I understand.
What I don't understand, is why the storage item "P" behaves differently:
1) Its value is already known upon entering state S0 (whereas "Jreg" is not)
2) Upon transitioning to state S1, "P" immediately updates to the value given by state S1, whereas "Jreg" is not updated until the end of that clock cycle
Is there a difference between "Jreg" and "P" I'm not aware of? Is it an error in the example?
It appears that P is a combinational signal (not dependent on a clock) and that Jreg is sequential register (is dependent on a clock). Jreg appears to behave as a counter (which requires a clock or drive signal of some sort). The example says that the machine waits for an input signal B to go high and once it does, it sets output P high. Then, using Jreg to count the number of clock cycles passed since B went high, it holds P high until Jreg counts to a certain number of clock cycles (2) at which point both Jreg and P are reset to 0.
1) Jreg is unknown at the start and most likely so is P, however P does not have to wait for a clock tick because its a combinational signal.
2) Again Jreg is sequential so it must wait for a clock tick to change its state.

Non-blocking and blocking assignments don't work as expected

I'm having problems with understanding such a simply looking thing: blocking and non-blocking assignments.
I created a small test bench just to simulate the behavior of this code:
module ATest(clk, out);
input wire clk;
output reg [7:0] out;
reg [7:0] A;
initial begin
A <= 8'b0;
end
always #(posedge clk) begin
A = A + 1;
out = A;
end
endmodule
After simulation, I got this wave:
I expected the same value under both A and out, as I assigned values to them sequentially. Why is out "don't care" during the first clock?
Then I tried to use non-blocking assignment. I changed a part of my code into:
always #(posedge clk) begin
A <= A + 1;
out <= A;
end
And I got this wave:
I didn't expect anything here, because non-blocking statements are kind of mystery to me. Why is both A and out set to "don't care"?
Also, I found different names on every page I got to, so please help me out:
Are blocking and non-blocking interchangeable with sequential and concurrent as terms? Which one is right: non-blocking statement or concurrent statement?
Without diving too deep into the simulation cycles used by Verilog Simulators, you can think of non-blocking vs blocking assignment simply as this:
Blocking assignment happens inline at the time the given assignment is executed, so that means if I have a line like A = A + 1, that means we take the present value of A, add 1 and assign A that new value. So, the assignment "blocks" execution until it is done.
Non-blocking assignment (NBA) happens at a time slightly later than while the line is executed. You can think of non-blocking assignments as lines telling the simulator to schedule this assignment for a little bit later (note, later is still with the same simulation time step, so all of this is still happening in simtime t). So, if you have something like A <= A + 1, this means take the value of A at the time of executing this line, add 1 and schedule A to be updated to that value in a little bit, but keep moving on with the lines following that one. So, if the next line after is out = (A == 1) ? 1 : 0, this line will execute using the old value of A, not the incremented one. Once the simulator finished with the active code, it can move on to perform all the non-blocking assignments. Now, A will get the incremented value and all other non-blocking assignments will take effect.
So, to your examples. In case one, we see the delayed effect of NBA. In the initial block, A is assigned to 0, which means A will take on the value of 0 a little bit later (still within sim time 0 remember); ie the assignment is scheduled to take place after all blocking assignments have run (Not strictly true but it works in this case). Also, you have the clock's posedge happen so the always block runs. Here, A takes on the value A + 1, but remember, the assignment of A to 0 hasnt happened, so A still has its initial value of 8'bx. so, A + 1 is also 8'bx. And since this is a blocking assignment, it happens right away. So, A doesnt change from don't care. Continuing on, out gets the current value of A, which is 8'bx. So, we get the don't cares on out. After these and other blocking assignments are done, now we finish up the NBAs, in this case, A to become 0. So, still within sim time 0, A becomes 0 and we are done. At the next posedge of the clock, A is 0, out is don't care and your always block runs as expected, incrementing A and assignment out to the same value.
If you change the always block to use NBA (which it should if it is suppose to be a register), things change slightly. The initial block still results in a NBA scheduled for A to become 0. But now, the always block does something different. Now, A <= A + 1 instead of assigning A to don't cares right away, it schedules A to become 8'bx (remember, the right-hand side expression for what value to assign is evaluated inline, so A + 1 still uses A as don't care just as before; whats changed is when A takes on this new value) and this is scheduled after A to become 0. So, both the NBAs of A are set up, but the one telling A to be 0 happens first and is wiped out by the later assignment of A to 8'bx. out is similarly scheduled to take on 8'bx but now, A never becomes 0. As such, both A and out get stuck at 8'bx.
You can look through the Verilog or SystemVerilog LRM's to get a better understanding of sim cycles and what really goes on, but I hope this helps you better understand the difference!
Your issue come from using a non-blocking assignment in your initial block. Use initial A = 8'b0; instead.
The casue for this is likely how the two assignments are processed. = assignments are done incrementally, with any new values being available to subsequent assignments. Changes made via <= assignments are only available once all assignments have been processed.
Because your first edge is at t = 0 (when intial blocks are processed), in the first example A is assigned 0, but that 0 isn't available to out until after it is processed. That's while the first cycle looks weird, but everything else is OK. In the second, A is assigned both 0 and A+1, so the simulator uses the always block instead of the initial, going with A+1, when A is still an unknown value. As such, the values for A and out are never known.
The terms are equivalent. "Blocking" is the same as "sequential" because "blocking" means that the assignment must be done before the simulator moves to the next line (in sequence). "Non-Blocking" means that all the lines may be done at once. As everything with Verilog, it helps to imagine the hardware intended, so you may think of it as "parallel" vs. "serial" sometimes.
Is there a positive clock edge at time 0 in your simulation?

Always block not behaving as expected

I am making a state machine in verilog to implement certain arithmetic functions based on user input. I've run into a snag, however; my first always block, the one that handles my reset and maintains the correct state, is not behaving as expected; it is not updating the state correctly. The code is as follows:
always # (posedge CLOCK_50 or negedge RESET) begin
if(RESET == 1'b0)
STATE <= BASE;
else
STATE <= NEXT_STATE; // this always block, and specifically this line, is //not executing correctly.
end
Here is the general output of the file when reset and then following three button presses (KEY[1]) with SW = 0000:
EDIT: waveform with actual CLOCK_50 and RESET signals added
http://imgur.com/0DUka21
As for my question, I just want to know what I am doing incorrectly with this section of code. I can think of no reason for it to behave this way. Thanks for any help you can provide.
EDIT2: FFS, I changed the block to negedge CLOCK_50 and now it's working. I'd really like to know why if you can tell.
Ah, I see what you did now. You're assigning STATE in both of your two always blocks (STATE <= STATE in the default of the case block). This is bad, as it's a race condition between the two blocks as to which gets actually assigned. In your case, the second block is overriding the first, such that STATE <= STATE gets executed every clock. You should not assign the same variable in more than one always block.
Also you should pay attention to those warnings, but they are referring to the always #(ENABLE) block. This is complaining because you are inferring weird latched behavior, because the output is depending on STATE and SW, but they are not in the sensitivity list. You should probably just make this a combinational block, and use the auto-sensitivity list always #*.
Every always block, as well as every statement outside of an always block, effectively runs in parallel.
Since you have "state" being driven by two always blocks, you're effectively having two wires feed into a single wire. In digital logic design, you just can't do that. (Excluding pull-up resistors and such, but that's another topic.)
In simulation, if the multiple wires driving that single wire have the same logical value, you can get the output you desire; but if they have different values, you'll get invalid or unpredictable output.
In synthesis, this will simply fail with a "multiple drivers" error.
Also, the sensitivity list for an always block should have one of three things in it:
A clock
A clock and an asynchronous reset
Every wire/reg that is used as an input to that always block (*)
Anything else can result in an unintentional latch, which will cause problems.
In case 3, you need to make sure that every wire driven in the always block has a default value. Anything else can result in an unintentional latch.
Lastly, you can't have circular assignments or you risk a logic loop. You have one by assigning next_state to itself. Anything "circular" requires a flip-flop, aka an always block of type 1 or 2 outlined above.

Resources