Mixing blocking and non-blocking assign in Verilog (or not!) - verilog

I'm implementing a simple serializer in Verilog, but I do not understand the nuances of when blocking assigns can cause problems. I'm specifically having trouble understanding part of this answer. "However, you should never use blocking assignments for synchronous communication, as this is nondeterministic."
I'm building a block that takes, as an input:
A bit clock
A 5-bit parallel data input (the value to be serialized)
A "Data valid" signal that indicates valid 5-bit data is present
As an output, I have:
Serial data out
A "Complete" signal that indicates it's time for a new 5-bit value
A "Transmitting" signal that's high whenever there's valid serial data going out on the bus
Whenever data valid goes high, the block starts outputting the 5-bit value, one bit a time, starting at the next rising edge of the bit clock. When the last bit is out on the wire, the block signals "complete" so a new 5-bit value can be made available.
Omitting some of the reset logic, the code to do this looks like this:
always # (posedge clk) begin
if(shiftIndex == 0) begin
if(dataValid == 1) transmitting = 1; //Blocking assign
else transmitting = 0; //Blocking assign
end
//Need the blocking assign up above to get this part to run
//for the 1st bit
if(transmitting == 1) begin
shiftIndex <= shiftIndex + 1;
dataOut <= data5b[shiftIndex];
if(shiftIndex == 4) begin
complete <= 1;
shiftIndex <= 0;
end
else begin
complete <= 0;
end
end
end
Now, I can write the block with all non-blocking assigns, but I feel that it hurts readability. That would look something like this:
always # (posedge clk) begin
if(shiftIndex == 0) begin
if(dataValid == 1) begin
transmitting <= 1; //Non-blocking now
shiftIndex <= shiftIndex + 1; //Duplicated code
dataOut <= data5b[shiftIndex]; //Duplicated code
complete <= 0; //Duplicated code
end
else transmitting <= 0;
end
//Now, this only runs for the 2nd, 3rd, 4th, and 5th bit.
else if(transmitting == 1) begin
shiftIndex <= shiftIndex + 1;
dataOut <= data5b[shiftIndex];
if(shiftIndex == 4) begin
complete <= 1;
shiftIndex <= 0;
end
else begin
complete <= 0;
end
end
end
Both appear to do what I want in simulation, and I favor the 1st one because it's easier for me to read but since I don't understand why using blocking assignments for synchronous communication is nondeterministic, I'm worried that I've coded up a ticking time bomb
The Question: Am I doing something wrong in the 1st code that's going to blow up when I try to synthesize this? Is the 2nd code preferable despite being a bit harder (for me anyway) to read? Is there some 3rd thing I should be doing?

When using the blocking (=) assignment the value is available to use in the next line of code. This implies it is combinatorial and not driven from a flip-flop.
In simulation it looks like it is driven from a flip-flop because the block is only evaluated on positive clock edge, in reality it is not which might break the interface.
I am of the faction which says never mix styles, as it can be a problem in code reviews and refactoring. The refactor, if a module needs to output a new signal and it is seen that it already exists they just change to be an output. At first glance looked like it was a flip-flop because it was in a always #(posedge clk block.
Therefore I would recommend to NOT mix styles, but pull out the section that is combinatorial and put it in its own block. Does this still meet your requirements? if not then you would have had problem.
I do not see how data valid is controlled but it can change the output transmitting, potentially transmitting could also glitch as it is from a combinatorial decode, not driven cleanly from a flip-flop. The receiving interface might be async, glitches could cause lock up etc.
always #* begin
if(shiftIndex == 0) begin
if(dataValid == 1) transmitting = 1; //Blocking assign
else transmitting = 0; //Blocking assign
end
end
always # (posedge clk) begin
if(transmitting == 1) begin
shiftIndex <= shiftIndex + 1;
dataOut <= data5b[shiftIndex];
if(shiftIndex == 4) begin
complete <= 1;
shiftIndex <= 0;
end
else begin
complete <= 0;
end
end
end

As far as correctness is concerned, there is no problem with mixing blocking and non-blocking assignments, but you need to have a clear understanding of which signal is sequential and which signal is combinational block (note that the inputs of this combinational block come either from other sequential blocks or primary inputs). Also, you need to decide if you want any latches in your design or not.
If you use blocking assignments for a variable that you don't mean to be sequential, make sure to always assign to it, otherwise, it might be interpreted as a sequential element.
In your first code, you don't assign to transmitting when (shiftIndex != 0). This implies the previous value of transmitting should be used when (shiftIndex != 0), hence it would be a sequential element. But you need its value in the current clock, hence you used a blocking assignment.
Below is another version of your code, where firstBit_comb for the first bit is used and is always assigned to.
always # (posedge clk) begin
//Default value to avoid sequentials. Will be overwritten later if necessary
firstBit_comb = 0;
if(shiftIndex == 0) begin
if(dataValid == 1) begin
transmitting_seq <= 1;
firstBit_comb = 1;
end
else begin
transmitting_seq <= 0;
firstBit_comb = 1;
end
end
//Need the blocking assign up above to get this part to run
//for the 1st bit
if(firstBit_comb || transmitting_seq) begin
shiftIndex <= shiftIndex + 1;
dataOut <= data5b[shiftIndex];
if(shiftIndex == 4) begin
complete <= 1;
shiftIndex <= 0;
end
else begin
complete <= 0;
end
end
end
It is however more clear if you separate sequential and combinational blocks. Note that the next state of your sequential elements is often an output of a combinational block.
//combinational block
always_comb
begin
//The default value of next state is the previous state
transmitting_next = transmitting_seq;
//The default value of firstBit_comb=0. It would be overwritten if necessary
firstBit_comb = 0;
if(shiftIndex == 0 && dataValid == 1) begin
firstBit_comb = 1;
transmitting_next = 1;
end
else begin
firstBit_comb = 0;
transmitting_next = 0;
end
end
//Sequential block
always # (posedge clk) begin
//update transmitting_seq with its next state
transmitting_seq <= transmitting_next;
if(firstBit_comb || transmitting_seq) begin
shiftIndex <= shiftIndex + 1;
dataOut <= data5b[shiftIndex];
if(shiftIndex == 4) begin
complete <= 1;
shiftIndex <= 0;
end
else begin
complete <= 0;
end
end
end

Related

Find Maximum Number present in Verilog array

I have tried writing a small verilog module that will find the maximum of 10 numbers in an array. At the moment I am just trying to verify the correctness of the module without going into specific RTL methods that will to do such a task.
I am just seeing a a couple of registers when I am synthesizing this module. Nothing more that that. Ideally the output should be 7 which is at index 4 but I am seeing nothing neither on FPGA board or in the test bench. What I am doing wrong with this ?
module findmaximum(input clk,rst,output reg[3:0]max, output reg[3:0]index);
reg [3:0]corr_Output[0:9];
always#(posedge clk or posedge rst)
if(rst)
begin
corr_Output[0]=0;
corr_Output[1]=0;
corr_Output[2]=0;
corr_Output[3]=0;
corr_Output[4]=0;
corr_Output[5]=0;
corr_Output[6]=0;
corr_Output[7]=0;
corr_Output[8]=0;
corr_Output[9]=0;
end
else
begin
corr_Output[0]=0;
corr_Output[1]=0;
corr_Output[2]=0;
corr_Output[3]=0;
corr_Output[4]=7;
corr_Output[5]=0;
corr_Output[6]=0;
corr_Output[7]=0;
corr_Output[8]=0;
corr_Output[9]=0;
end
integer i;
always#(posedge clk or posedge rst)
if(rst)
begin
max=0;
index=0;
end
else
begin
max = corr_Output[0];
for (i = 0; i <= 9; i=i+1)
begin
if (corr_Output[i] > max)
begin
max = corr_Output[i];
index = i;
end
end
end
endmodule
Looking are your code, the only possible outputs are max=0,index=0 and a clock or two after reset max=7,index=4. Therefore, your synthesizer is likely optimizing the code with equivalent behavior with simpler logic.
For your find max logic to be meaningful, you need to change the values of corr_Output periodically. This can be done via input writes, LFSR (aka pseudo random number generator), and or other logic.
Other issues:
Synchronous logic (updated on a clock edge) should be assigned by with non-blocking (<=). Combinational logic should be assigned with blocking (=). When this guideline is not followed there is a risk of behavior differences between simulation and synthesis. In the event you need to compare with intermediate values (like your original max and index), then you need to separate the logic into two always blocks like bellow. See code bellow.
Also, FPGAs tend to have limited asynchronous reset support. Use synchronous reset instead by removing the reset from the sensitivity list.
always#(posedge clk) begin
if (rst) begin
max <= 4'h0;
index <= 4'h0;
end
else begin
max <= next_max;
index <= next_index;
end
always #* begin
next_max = corr_Output[0];
next_index = 4'h0;
for (i = 1; i <= 9; i=i+1) begin // <-- start at 1, not 0 (0 is same a default)
if (corr_Output[i] > next_max) begin
next_max = corr_Output[i];
next_index = i;
end
end
end

Verilog Design Problems

How to fix multiple driver , default value and combinational loop problems in the code below?
always #(posedge clk)
myregister <= #1 myregisterNxt;
always #* begin
if(reset)
myregisterNxt = myregisterNxt +1;
else if(flag == 1)
myregister = myregister +2;
end
right there are at least 3 issues in your code:
you are driving myregister within 2 different always blocks. Synthesis will find multiple drivers there. Simulation results will be unpredictable. The rule: you must drive a signal within a single always block.
you ave a zero-delay loop over myregisterNxt = myregisterNxt +1. Since you are using a no-flop there, it is a real loop in simulation and in hardware. You need to break such loops with flops
#1 delay is not synthesizable and it is not needed here at all.
You have not described what you were trying to build and it is difficult to figure it out from our code sample. In general, reset is used to set up initial values. So, something like the following could be a template for you.
always #(posedge clk) begin
if (reset)
myregister <= 0;
else
myregister <= myregister + increment;
end
always #* begin
if (flag == 1)
increment = 1;
else
increment = 2;
end
the flop with posedge clk and nonblocking assignments will not be in a loop.

Can't use else in verilog always block

I am receiving this error from Quartus when trying to compile:
Error (10200): Verilog HDL Conditional Statement error at
time_of_day_FSM.v(166): cannot match operand(s) in the condition to
the corresponding edges in the enclosing event control of the always
construct
Here is some background. I am making a clock, and for this always block, I want to increment and set certain values to resemble the behavior of a clock in the format of hh:mm:ss. I have a clock source that goes high every millisecond, and am using a counter to set the secondPassed reg.
I want the code in the block to update every time a second passes, like a clock, or KEY[2] is pressed on my board (down = 0), as this is what the user uses to increment the hours, minutes, or seconds when setting the clock time. Here is the always block in question (sorry for the nested if statements, I can't think of a better way to do it):
// every second. Used just to keep time going. Independent of states.
always #(posedge secondPassed, negedge KEY[2], negedge KEY[0]) begin
if(KEY[0] == 0) begin
hr1 <= 1;
hr0 <= 2;
min1 <= 0;
min0 <= 0;
sec1 <= 0;
sec0 <= 0;
end
else if(secondPassed == 1 || KEY[2] == 0) begin // I don't care about explicitly stating the conditions, as the sensitivity list covers that right?
if(sec0 == 9) begin
sec0 <= 0;
if(sec1 == 5) begin
sec1 <= 0;
if(min0 == 9) begin
min0 <= 0;
if(min1 == 5) begin
min1 <= 0;
if(hr1 == 1) begin
if(hr0 == 2) begin
hr0 <= 1; // go to 1 o'clock
hr1 <= 0;
end
else hr0 <= hr0 + 1;
end
else hr0 <= hr0 + 1;
end
else min1 <= min1 + 1;
end
else min0 <= min0 + 1;
end
else sec1 <= sec1 + 1;
end
else begin
sec0 <= sec0 + 1;
end
just_flashed <= ~just_flashed;
end // end big else
end // end always
My question is: Why does the Quartus compiler complain if I try to make the non-reset scenario JUST AND ELSE, like this:
// every second. Used just to keep time going. Independent of states.
always #(posedge secondPassed, negedge KEY[2], negedge KEY[0]) begin
if(KEY[0] == 0) begin
hr1 <= 1;
hr0 <= 2;
min1 <= 0;
min0 <= 0;
sec1 <= 0;
sec0 <= 0;
end
else begin // this is causing the issue. compiler complains .
// same logic to drive clock as above
just_flashed <= ~just_flashed;
end // end big else
end // end always
I feel I have seen many examples where people simply use and else begin end for their code. My code seems to want my to EXPLICITLY restate the conditions of the sensitivity list for the else if. Any explanation? I am new to large verilog projects.
You are mixing combinational logic and synchronous logic in the always block and this is bad habit of coding. Generally, there are 2 main always blocks in most designs.
A combinational:
always#(*) // * adds anything under this always block to sensitivity list.
begin // Which makes this always block combinational.
count_reg_d <= somelogic;
end
Then these combinational logic is assigned to proper registers in the sequental
always block:
always#(posedge clk, negedge rst)
begin
if(~rst)
count_reg_q <= 0;
else
begin
count_reg_q <= count_reg_d;
end
end
By coding this way you avoid mixed always blocks, and the code is much more readable and closer to hardware that is being synthesized. So if you update the always blocks' sensitivity list properly the problems has to be solved.

Verilog assignments in a sequential always

I know that I should be using a non-blocking assignments in sequential always assignments. However, I accidentally happen to use a blocking assignment in part of my code, here it is:
reg tb_strobe = 0;
reg [9:0] tb_strobe_cnt = 0;
reg tb_sync = 0;
always#(posedge tb_clkh)
begin
if (~tb_resetl) begin
tb_strobe <= 0;
tb_strobe_cnt <= 0;
tb_sync <= 0;
end
else begin
if (tb_strobe_cnt == 1022) begin
tb_strobe <= 1;
tb_strobe_cnt <= tb_strobe_cnt + 1;
end else if (tb_strobe_cnt == 1023) begin
tb_strobe <= 0;
tb_strobe_cnt <= 0;
end else begin
tb_strobe <= 0;
tb_strobe_cnt <= tb_strobe_cnt + 1;
end
if (tb_strobe == 1) begin
tb_sync = 1; // <-- this is the mistakenly used blocking assignment
end else begin
end
end
end
And then my simulator behaves unpredictably, and once I fixed that assignment to be a non-blocking one, it started working fine !!!!
I am curious as to what was wrong with the above (in my specific code)?
In the way that I used it, since I am only calling tb_sync once in my code, I wasn't expecting any unpredictable behavior...
And tb_sync is not being assigned anywhere else in the code. Any idea what is wrong?
Non-blocking assignments are used to prevent race conditions between multiple processes that write and read the same variable on the same clock edge. It just takes one process that writes, and another process that reads the same variable on the same clock edge to create that race. Your example does not show the process that reads tb_sync, but I'm assuming that's where the race is.

Verilog Event control statements

I currently have this code(below) for a debouncer for a button on an fpga, however I am getting an error that says "Multiple event control statements in one always/initial process block are not supported in this case." whenever I try to synthesize the desgin. The line that causes the problem is the #(posedge clk) but I'm wondering how exactly to replace this logic. What I essentially require is always # (quarter & posedge clk)as the sensitivity list for the first always block but this does not work either. I am fairly new to the language so I'm still working out a few syntax kinks.Snippet of Code is below:
always #(quarter)
begin
#(posedge clk)
begin
if (quarter != new) begin new <= quarter; count <= 0; end
else if (count == DELAY) cleanq <= new;
else count <= count+1;
end
end
instead of always
#(posedge event1)
#(posedge event2)
create aflag (1bit reg) event2done : reg event2done; initial event2done=0;
always#(posedge event1)
begin if (!event2done & event 2)
// event2done=1; + type ur code
else if(event2done & !event 2)
event2done =0; end
pseudo code:
always#(something1)
#(something2)
do something
Look in the comments to see explanation as to why this isn't synthesizable
always #(posedge clk)
/* over here you'll have to set the default values
for everything that's being changed in this always block,
you'll otherwise generate latches. Which is likely
not what you want */
begin
if (quarter != new) begin new <= quarter; count <= 0; end
else if (count == DELAY) cleanq <= new;
else count <= count+1;
end
I don't have access to my verilog rig at the moment so I can't confirm the syntax correctness

Resources