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

Maths Error

DBarn22
Novice
842 Views

I have a block that is occasionally giving an error.  I'm fairly sure it is due to timing, but I do not understand the problem.

The following are relevant snippets.

 

 

reg enc_reg;
reg [31:0] enc_real_fast_time;
reg [31:0] enc_real_fast_time_prev;
reg [31:0] enc_pulse_period;

always @ (posedge clk) begin
	enc_reg <= enc;
end

always @ (negedge enc_reg) begin
	enc_pulse_period <= (fast_now - enc_real_fast_time_prev) / (divider*2);
	enc_real_fast_time_prev <= enc_real_fast_time;
	enc_real_fast_time <= fast_now;
end

 

 

 
clk: A 50MHz output of a PLL block.
enc: The input from an encoder.  A synchronous approximately 20kHz.
fast_now: A 32-bit count of clk, incremented on negative edges.
divider: constant = 5.

This usually works and results in enc_pulse_period of 496 (give or take one or two).

Every few seconds, the result is wrong, either in the order of 400 or very large.  It always (usually) occurs when fast_now is XXXX0000 at the time of the negedge enc_reg block.

My assumption is that the subtraction and division is occurring as the other values are changing and therefore gets incorrect bits in its calculation.  I have tried using blocking assignments but that makes no difference.

What am I doing wrong?
What is best practice for making the enc_pulse_period reliably correct?

This is an example of an error occurring.
enc_pulse_period.png
n.b. 8E800000h - 8E7F3C98h = 4968(d) -> 496 expected.  [divider = 5]

0 Kudos
1 Solution
ak6dn
Valued Contributor III
828 Views

Why not do a fully synchronous design with all the registers clocked on posedge clk ?

Create an enable signal for the data processing block and include all the logic inside that block within it:

always @ (posedge clk) begin
    if (enable_enc) begin
     ... do stuff ...
    end
end

 

View solution in original post

4 Replies
DBarn22
Novice
837 Views

I tried a different solution...

always @ (negedge enc_reg) begin
	enc_real_fast_time_prev <= enc_real_fast_time;
	enc_real_fast_time <= fast_now;
end

wire [31:0] enc_pulse_period;
assign enc_pulse_period = (enc_real_fast_time - enc_real_fast_time_prev) / divider;

(Currently not quite the same functionality as it divides over one rather than two periods, but that is just detail).

What this has shown is that the division takes many clock cycles to perform.  Therein lies my problem.
enc_pulse_period2.png

This may be a sufficient solution for what I need.  I would still be interested to know if it is possible to do what I was initially trying to do.

0 Kudos
ak6dn
Valued Contributor III
829 Views

Why not do a fully synchronous design with all the registers clocked on posedge clk ?

Create an enable signal for the data processing block and include all the logic inside that block within it:

always @ (posedge clk) begin
    if (enable_enc) begin
     ... do stuff ...
    end
end

 

DBarn22
Novice
824 Views

Two questions.

 

Why would that work when my solution does not?

What is best practice for implementing enable_enc?

0 Kudos
ak6dn
Valued Contributor III
820 Views

Using a single synchronous clock with optional register enable(s) is simpler for Quartus to meet timing than deriving a bunch of signals that will be used as clocks. FPGAs only have a limited number of low skew, high drive clock layout resources.

As to implementing the enable signal, that is just some simple logic driving a register to create a one clock width pulse at the posedge clk when you want the logic to trigger. No special techniques needed.

Reply