Continue to Site

# Arithmetic with big numbers

Status
Not open for further replies.

#### KingMoshe

##### Member level 2
Hello,

I have a design that include counter.
after I finish to count I want to normalize the counter as below:

NUM = 15/(counter*0.000000221)

I want that NUM to be integer.

Example:
counter = 15000
NUM = 15/(15000*0.000000221) = 4524.886878 = 4524(rounded)
at the end I want to save to register the number 4524.

How can I do it?

Thanks,
Moshe

that simplifies to:

(15*10^9/221 )/count
= 67873303/count

Regards, Dana.

NUM = 15/(15000*0.000000221) = 4524.886878 = 4524(rounded)
at the end I want to save to register the number 4524.
4524 isn't the rounded value....

4525 would be the rounded value.

It would be easy to use use non-restoring division on the 67873303/count and adjust the rounded result based on the final remainder being greater than or equal to 1/2 count.

that simplifies to:

(15*10^9/221 )/count
= 67873303/count
Hi
thanks for answer. I tried to do that but now when I try to map my project I got an error:

ERROR - Design doesn't fit into device specified, refer to the Map report for more details.
I guess because the big numbers arithmetic.

This is my code:
Code:
//////////////////////////////////////////////////////////////////////////////////
// Company: SolarEdge
//////////////////////////////////////////////////////////////////////////////////
// Company: SolarEdge
// Engineer: Moshe Novak
//
// Last Update: 20/12/2021
// Module Name: TACHOMETER (RPM DETECTOR)
// Project Name: Jupiter 48 BU
// Revision: 01
//
//////////////////////////////////////////////////////////////////////////////////

//timescale 1ns / 1ps

module TACH(
RST, //input from MNGR to reset
clk, // clock input
IN_TACH, //intput from internal fan
OUT_RPM_NORM //output reister
);

//INPUTS-----------------------------------------------------------------------------------------------------
input wire RST;
input wire clk;
input wire IN_TACH; //intput from internal fan

//OUTPUTS----------------------------------------------------------------------------------------------------
output reg [15:0] OUT_RPM_NORM;

//LOCAL------------------------------------------------------------------------------------------------------
reg [15:0] rpm_counter;
reg [7:0] state;
parameter K = 67720090; // K = 15/TCLK = 15/221.5nano

// OUT_RPM_NORM = 1/(TCLK * OUT_RPM)

integer OUT_RPM;

localparam STATE_IDLE = 0;
localparam STATE_COUNT = 1;
localparam STATE_SAVE = 2;
localparam STATE_NORM = 4;
localparam STATE_STOP = 3;

always @ (posedge clk or posedge RST)
begin
if (RST)
begin
rpm_counter <= 16'b0;
state <= STATE_IDLE;
end
else begin
case (state)
STATE_IDLE: begin
if (~IN_TACH) state <= STATE_COUNT;
else state <= STATE_IDLE;
end

STATE_COUNT: begin
rpm_counter <= rpm_counter + 1'b1;
if (~IN_TACH) state <= STATE_COUNT;
else state <= STATE_SAVE;
end

STATE_SAVE: begin
OUT_RPM <= K/rpm_counter;
state <= STATE_NORM;
end

STATE_NORM: begin
OUT_RPM_NORM <= OUT_RPM;
state <= STATE_STOP;
end

STATE_STOP: begin
state <= STATE_IDLE;
rpm_counter <= 16'b0;
end
endcase
end
end

endmodule`

and this is the map summary:

Last edited by a moderator:

Hi,
Always when I tried to calculate and save big numbers I got an error:

ERROR - Design doesn't fit into device specified, refer to the Map report for more details.
and this is the Map report:

that is happen just after I add this lines to my design:

reg [15:0] rpm_counter;
parameter K = 67720090; // K = 15/TCLK = 15/221.5nano
integer OUT_RPM;

OUT_RPM <= K/rpm_counter;

What is the problem?

Thanks,
Moshe

Obviously you have exceeded # LUTS, SLICES in design. Without
knowing more about total design, one can only guess. What was
resource map before the addition ? What did usage look like then ?

Considerations (LUT minimization) - https://zipcpu.com/blog/2017/06/12/minimizing-luts.html

Regards, Dana.

Hi,

I´m not very experienced in this field.
What comes into my mind:
Maybe there are no ALUs inside, so the divider has to be built with LUTs and gates.
and maybe constrainted to do all this within one clock cycle.

If so, mabe a pipelined divider (using mutliple clock cycles) is a way to go.

Klaus

that is happen just after I add this lines to my design:

reg [15:0] rpm_counter;
parameter K = 67720090; // K = 15/TCLK = 15/221.5nano
integer OUT_RPM;

OUT_RPM <= K/rpm_counter;

What is the problem?
The problem is the division operation 27bit_constant/16bit_variable. Instead of a parallel divider you should implement a serial divider like https://opencores.org/projects/serial_div_uu

Back in post #4 I said to use non-restoring division, which is a serial division algorithm.

The link in post #9, at a glance, looks like a non-restoring divider.

Back in post #4 I said to use non-restoring division, which is a serial division algorithm.

The link in post #9, at a glance, looks like a non-restoring divider.
Right, I answered the question (now post #6) before I realized that it was a duplicate of a previous post. Both threads have been merged later.

Checkout book by Wakerly "Logic design projects using standard integrated circuits"
Experiment C7 Digital Tachometer pg.no. 101

You need to change the design architecture as shown.
Hope this helps!

A tachometer operates by measuring the frequency of firing of the​
engine's points. There are two approaches for doing this. The first
is to simply count the number of firings in a fixed period of time,
as was done in Project C2. Although this is by far the simplest of
the methods, it will be shown that this approach is not satisfactory.

The other method is to measure the period between successive firings
of the points and then to find the inverse of this, that is, the
frequency. This approach can be implemented with a reasonable amount
of circuitry by keeping in mind that the time required to find the
inverse is not critical.

In comparing the different approaches, it is important to note that
the reaction time of the human being is critical, as well as how fast
the engine can change RPM (revolutions per minute). The eye can
detect very short changes and interpret them in about 0.1 to 0.2
seconds. For this reason, the tachometer's RPM display should be
updated within this period of time. The engine can change about
3000 RPM/sec. For the driver to get useful information on the engine
seconds or better. The operating range of the display should be about
600 to 7000 RPM with accuracy of about ±50 RPM throughout the range.
The points of a typical 4-cylinder or 8-cylinder engine fire four
times per revolution. Hence the RPM can be related to the number of
point firing pulses per second by the formula:
1 revolution 1 minute 4 pulses 1 pulse
1 RPM = ------------ x ----------- x ----------- = -----------
minute 60 seconds revolution 15 seconds

RPM = 15 x (pulses/second)
If we take the first alternative of counting the number of pulses
within a fixed period of time, it would be most convenient to use the
relationship:
RPM = 100 x (pulses/0.15 second)
That is, we could count the number of pulses in a .15 second period
and append two zeroes to get RPM; the display could be updated every
.15 seconds. However, in addition to the fact that the display is
not updated quite as fast as we would like it to be, this method has
a primary disadvantage of poor accuracy. A difference of only one
pulse per .15 second period makes a difference of 100 RPM in the
display. If we counted pulses over an even shorter period for
faster updating, the accuracy would be correspondingly poorer.
The second alternative is much more accurate: measure the period
of the pulses and divide to find the RPM. At 600 RPM the time between
pulses is .025 seconds, and at 7000 RPM the period is .0021 seconds.
At the low end the period is still short enough that updating the
display once per period gives the driver his information quickly
enough, and at the high end the period is not so short that the
division cannot be carried out in one period by standard TTL or CMOS
circuits. The RPM can be given by the relationship:
15
RPM = 15 x pulses/second = ---------------
seconds/pulse

Choosing then the second alternative as the method for designing the tachometer, the first problem
we are faced with is how to measure the period between pulses. The simplest method is to count the
number of pulses of a high frequency (in relation to 7000 rpm) freerunning clock between engine
point pulses. The period of the point pulses is then simply the number of clock pulses times the
period of the free-running clock. In order to achieve accuracy of ±50 RPM throughout the range of
the tachometer, it can be shown that the frequency of the free-running clock should be about 80 KHz
or higher (show this as part of the assignment). A choice of 109.2 KHz for the free-running clock
15 X 109.2 KHz 1
RPM (in hundreds)= ------------------------------- x ----
clock pulses/engine pulses 100

2^14
= --------------------------------
clock pulses/engine pulses​

The only problem rema1n1ng, then, is how to carry out the division called for above. Shift and
subtract algorithms are certainly fast enough to carry out the division within .0021 seconds, but​
they re quire too much circuitry and their higher speed is not necessary. A brute force method
using counters requires less circuitry. As shown in the block diagram of Figure C7-l, the engine
point pulses are fed to the control unit to produce a gating signal for the period counter, which
counts the period between pulses in units of the 109.2 KHz clock period. After the period has been
counted, a 14-bit counter and a two-digit display counter are cleared, and the contents of the
period counter are transferred to a down counter. The down counter counts down and the up counter
counts up until the down counter reaches zero. When this happens the display counter is incremented
and the down counter is reloaded from the period counter. The process is repeated
until the up counter overflows. At this point the display counter
contains the (truncated) quotient of 2^14 divided by the contents of
the period counter. The display counter contains the RPM in hundreds.

Notice that the posted "Experiment C7 Digital Tachometer" is dedicated to standard IC rather than PLD/FPGA. In FPGA the serial divider solution suggested in post #4 and #9 is straight forward, I think.

The required 27/16 = 16 bit divider including overflow handling can be implemented in 118 logic elements (4-input LUT with register) which seems fair.

Status
Not open for further replies.