Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17249 Discussions

Unsafe Latch behavior and inferred latches

Altera_Forum
Honored Contributor II
5,041 Views

Hey Everyone, 

 

I am a little confused on how Quartus decides if something is an actual latch or an inferred latch. For example in the following code, latch_counter and control_word_register are treated as inferred latches, but counter seems to be treated as a register.  

 

module prog_counter (reset, ceb, write, data_in, clk, load, data_out,trigger); input trigger; input reset; input ceb, write, load; input data_in; input clk; output data_out; //declare the control word reg control_word_register; reg disable_CWR; //Used to disable the CWR //declare the counter with 8 bits reg counter; reg latch_counter; //flag for first clk pulse after loading in value of counter reg flag_counter; //flag for half count cycle reg flag_half_counter; //to write control word into counter //for control_word, bit 2 reprsents enable, //bits 1 and 0 represent counter mode //this also latches in the counter value. always @(ceb or write or reset or load or data_in or disable_CWR) begin //Load control word //Pin Config: ceb:low, write:high, load:low, reset:low if (~ceb & write & ~load & ~reset) control_word_register = data_in ; //Load Counter Value //Pin Config: ceb:low, write:low, load:high: reset:low else if (~ceb & ~write & load & ~reset) latch_counter = data_in; //Timer Enable - Prepare timer for loading control word and latch //Pin Config: ceb:high, reset:low else if (ceb & ~reset) begin //reset the control word counter control_word_register = 3'd0; //reset the latch latch_counter = 8'd0; end else if (disable_CWR) control_word_register = 1'd0; end //to counter for counter always @(posedge clk or posedge reset) begin if(reset) begin disable_CWR <= 0; flag_counter <= 0; counter <= 0; flag_half_counter<=0; end else begin if(control_word_register) //counter is enabled begin if(control_word_register == 2'b00) //this if for one shot mode begin if(~flag_counter) begin counter <= latch_counter; flag_counter <=1; end else begin if(counter == 8'hff) begin //to stop counter for one shot mode disable_CWR <= 1; flag_counter <=0; end else counter <= counter + 1; end end else if (control_word_register == 2'b01) //waveform generator mode begin if(~flag_counter) begin counter <= latch_counter; flag_counter <= 1; end else begin if(counter == 8'hff) flag_counter <= 0; counter <= counter + 1; end end else if(control_word_register == 2'b10) //this if for the 50% duty cycle waveform generator begin if(~flag_counter) begin counter <= latch_counter; flag_counter <= 1; end else begin if (counter == {1'b0,latch_counter}) begin flag_half_counter <= ~flag_half_counter; counter <= counter - 1; end else if (counter == 0) flag_counter <= 0; else counter <= counter - 1; end end else if(control_word_register == 2'b11)//this is for triggered pulse generator mode begin if(~flag_counter) begin //If we aren't currently sending out a pulse, then keep the counter loaded and ready //this also resets the counter after a successful pulse is generated so that we will be ready for the next trigger counter <= latch_counter; if(trigger) flag_counter <= 1; else flag_counter <= 0; end else if(counter == 8'hff) begin //stop counter for triggered pulse mode flag_counter <= 0; end else counter <= counter + 1; end end end end assign data_out = ( ((counter == 8'hff) & (control_word_register == 2'b00) & flag_counter) | ((counter == 8'hff) & (control_word_register == 2'b01)) | (flag_half_counter & (control_word_register == 2'b10))| ((counter != 8'hff) & (control_word_register == 2'b11) & flag_counter) ); endmodule  

 

 

I get warnings about the former two being inferred, and then get warnings like: 

 

Warning: Latch prog_counter:inst|control_word_register has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|control_word_register has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|latch_counter has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|latch_counter has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|latch_counter has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|latch_counter has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|latch_counter has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|latch_counter has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|latch_counter has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|control_word_register has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst Warning: Latch prog_counter:inst|latch_counter has unsafe behavior Warning: Ports D and ENA on the latch are fed by the same signal rst 

 

the thing is I want to treat latch_counter and control_word_register as storage anyway, so why are they being inferred? is there way a way to force quartus to treat them as registers? 

 

If I run a simulation of the circuit, after the latch_counter is loaded correctly and the load pin is pulled low, the latch resets to 0, but I haven't a clue why. 

 

Any input is greatly appreciated. Thanks
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
3,296 Views

Look at what is in your process sensitivity list. If you write a function that responds to reset and posedge clk then it will most likely be a register. If it responds to other stuff and has incomplete in/then statements it may fold it into a latch.

0 Kudos
Altera_Forum
Honored Contributor II
3,296 Views

 

--- Quote Start ---  

Look at what is in your process sensitivity list. 

--- Quote End ---  

 

In synthesized code, it's almost meaningless what's in the sensitívity list of a combinational process, although the compiler issues warnings about missing signals to keep compatibilty with simulation results. 

 

It's the pure logic equations that actually matter. control_word_register and latch_counter are assigned in a combinational (or "level sensitive") process, so latches are created. The behaviour is unsafe, because logical combinations of the same signals are generating different latch states. Unavoidable glitches in the generated logic make the latch state possibly unpredictable. 

 

flag_counter and counter are in contrast assigned in a synchronous (edge-sensitive) process and thus synthesized as clockes DFFs.
0 Kudos
Altera_Forum
Honored Contributor II
3,296 Views

Thank you both for the replies, I can see now why the latches are created. 

 

FvM: 

 

 

--- Quote Start ---  

It's the pure logic equations that actually matter. control_word_register and latch_counter are assigned in a combinational (or "level sensitive") process, so latches are created. The behaviour is unsafe, because logical combinations of the same signals are generating different latch states. Unavoidable glitches in the generated logic make the latch state possibly unpredictable. 

--- Quote End ---  

 

 

is there a way fix the unsafe behavior in the above code?
0 Kudos
Altera_Forum
Honored Contributor II
3,296 Views

 

--- Quote Start ---  

is there a way fix the unsafe behavior in the above code? 

--- Quote End ---  

 

You should find an alternative way to achieve the intended behaviour. Actually I don't undertstand the meaning of the present code, e.g. three different cases of reset. Finding a synchronous solution would be preferable, of course.
0 Kudos
Altera_Forum
Honored Contributor II
3,296 Views

As always, I should probably just wait for FvM to answer questions. You are correct, but I do find that sensitivity lists do shed light into what the original coder was trying to accomplish. If they have just edges of reset and clocks in the list is shows they intended to write a ff, if they have other stuff in there it shows they are trying to write combinational logic. Although now I am just writing stuff to cover up my incorrect first post...

0 Kudos
Altera_Forum
Honored Contributor II
3,296 Views

I didn't suggest to ignore sensitivity lists, I'm mostly filling them up as required by the VHDL standard. I just wanted to prevent jumping into conclusion about the present problem.

0 Kudos
Altera_Forum
Honored Contributor II
3,296 Views

Hello. 

 

I forgot to assign all the cases in a case control in a always @(*), so latches are inferred. 

OK, I understand that, no problem. 

But, with the inferred latches present I get both LE count and fmax 10% better than with the inferred latches eliminated. 

 

Is the TimeQuest timing analyzer to believe in this case?
0 Kudos
Altera_Forum
Honored Contributor II
3,296 Views

Yes and no. Timequest is only able to analyse registers, not latches. So latches could present all sorts of problems.

0 Kudos
Reply