Maths Error
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.
n.b. 8E800000h - 8E7F3C98h = 4968(d) -> 496 expected. [divider = 5]
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