Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to scale a signal in vhdl

Status
Not open for further replies.

Manolitus7

Newbie level 5
Joined
Mar 9, 2022
Messages
8
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
71
I have a digital signal between 0 and 65535.

I want to get a digital signal between 0 and 500.

In theory it would be necessary to divide by 131, but vhdl does not allow division, and since 131 is not a power of two...
 

VHDL most certainly DOES allow division. Maybe try an internet search of, oh, I don't know, "VHDL division".
VHDL DOES NOT allow division.

you can use little tricks like shifting the binary word a number of places by adding zeros to the left, but it would only be dividing into powers of two, and I don't want to do that.

Another option would be to implement a state machine and perform the division over multiple clock cycles, but I don't want that either.

I don't know if your response was so disappointing because you think I haven't informed myself, or just because you have no idea what you're talking about.
 

I'm sorry your view is so narrow, it must make life so difficult for you.

If you do repeated subtraction, isn't that division? You know, like you do with pencil-and-paper.

Did you know you can also use a cordic to perform division? Do you understand the use of algorithms? Restoring division? Non-restoring division? Do you know that even computers use some kind of algorithm to compute division?

Your initial question was 'how to scale a number'. There was no mention of clock cycles. If you want a single-cycle solution for division, you can use a lookup table.

I'm done with you now; you're ignored.
 

@Manolitus
VHDL certainly does allow division. I have used the division operator many times in code over the years in many FPGA designs.

I think, you are confusing vendor tools support for VHDL with the VHDL language itself.

For example, Quartus will let you use "/" just fine. Vivado will only let you use it if the divisor is a power of 2.

So the following works just fine in both tools:


Code VHDL - [expand]
1
2
3
4
5
signal a : integer;
 
...
 
a <= some_input / 4;



And heres proof - from the ieee.numeric_std package, which is part of the VHDL standard:


Code VHDL - [expand]
1
2
3
4
-- Id: A.21
function "/" (L, R: UNSIGNED) return UNSIGNED;
  -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0)
  -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R.



see https://github.com/ghdl/ghdl/blob/master/libraries/ieee/numeric_std.vhdl
 

VHDL DOES NOT allow division.

you can use little tricks like shifting the binary word a number of places by adding zeros to the left, but it would only be dividing into powers of two, and I don't want to do that.

Another option would be to implement a state machine and perform the division over multiple clock cycles, but I don't want that either.
Maybe next time you should specify your REQUIREMENTS upfront. You didn't specify anything but VHDL doesn't have division.

VHDL does support division, which can be used on real numbers. What it doesn't have is division of arbitrary integer values that can be synthesized into a circuit.

To do division without multiple clocks your choice is either a look up table or a multiplication by 1/131.
 

Hi,
I have a digital signal between 0 and 65535.

I want to get a digital signal between 0 and 500.

In theory it would be necessary to divide by 131, but vhdl does not allow division, and since 131 is not a power of two...
You have a 16 bit value.
Multiply it by the desired value...in your case 500 (9 bit wide)
Now you get a value with range of 16+9= 25 bits.

In a microcontroller you'd shift the result 16 bits to the right to get the deited (0...500) result.
With VHDL you just use bits 16...24 of the multiply_result.

Klaus
 

Als stated above, VHDL supports division for integer datatype, synthesis tools may or may not support divider interference for integer signals, Intel Quartus e.g. does.

In VHDL synthesis practice, you won't use a divider (neither parallel nor sequential) for the division by a constant value. Beyond the scope of this thread, dividers may be still needed for variable scaling.

Constant scaling is typically achieved by a fixed point multiplication, as KlausST stated.
 

@Manolitus7
Your decision to use a div operator in VHDL should be based on the logic synthesis tool you use.

For e.g. Xilinx FPGAs, dividers are supported only when the divisor is a constant and is a power of 2.
 

I have a digital signal between 0 and 65535.

I want to get a digital signal between 0 and 500.

In theory it would be necessary to divide by 131, but vhdl does not allow division, and since 131 is not a power of two...
multiply by 8000 then discard 20 LSBs (with or without rounding)
you will see that such process will badly affect small values.

This is similar to above post saying multiply by 500 then discard 16 bits but resolution is your choice.
 
Last edited:

multiply by 8000 then discard 20 LSBs (with or without rounding)
you will see that such process will badly affect small values.
The result can't be more precise than 1 LSB of range 500 (9 Bit). In so far multiplying by 8000 gives the same result as 500. If you want to apply rounding to nearest integer, multiply by 1000 and add 500, then cut lower bits.
 

The result can't be more precise than 1 LSB of range 500 (9 Bit). In so far multiplying by 8000 gives the same result as 500. If you want to apply rounding to nearest integer, multiply by 1000 and add 500, then cut lower bits.
Yes you are right. I tried multiplying by 500,250,125 with same results.
so 125 seems minimum. I assume at some higher value a difference will occur but may not useful enough. so just multiply by 125 and discard 14 bits.
 

Right, you can choose the lowest integer factor, in this case 125. If you don't care for possible reduction and simply use 500, the synthesis tool will cut the redundant logic cells for you.
--- Updated ---

Code:
    signal num:     unsigned (15 downto 0);
    signal scaled1: unsigned (8 downto 0);
    signal scaled2: unsigned (8 downto 0);
  begin
    scaled1 <= resize(num/to_unsigned(131,8),9); -- 10CL: 215 LE
    scaled2 <= resize(shift_right(to_unsigned(500,9)*num,16),9); -- 10CL: 71 LE
--- Updated ---

Can be simplified to
Code:
    scaled1 <= resize(num/131,9); -- 10CL: 215 LE
    scaled2 <= resize(shift_right(500*num,16),9); -- 10CL: 71 LE
--- Updated ---

Rounding to nearest
Code:
    scaled2 <= resize(shift_right(500*num+250,16),9); -- 10CL: 95 LE
 
Last edited:
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top