coding style for arithmetic operations

F

Frank Buss

I have a generic entity with a signals like this:

writeAddress: out unsigned(ADDRESS_WIDTH-1 downto 0);
dstStart: in unsigned(ADDRESS_WIDTH-1 downto 0);
dstPitch: in unsigned(15 downto 0);

Then I have a procedure:

procedure setPixel(x: unsigned(15 downto 0); y: unsigned(15 downto 0)) is
begin
writeAddress <= dstStart + dstPitch * y + x;
writeEnable <= '1';
data <= color;
end;

Xilinx ISE compiles it, but generates a warning:

Width mismatch. <writeAddress> has a width of 14 bits but assigned
expression is 32-bit wide

IIRC in Quartus this would be an error. So to avoid the warning, I have
written this function:

function adjustLength(value: unsigned; length: natural) return unsigned is
variable result: unsigned(length-1 downto 0);
begin
if value'length > length then
result := value(length-1 downto 0);
else
result := to_unsigned(0, length - value'length) & value;
end if;
return result;
end;

Now I can write it like this:

writeAddress <= adjustLength(
dstStart + dstPitch * y + x,
writeAddress'length);

and there is no warning anymore, but I wonder if this is good VHDL coding
style, or if there is already library function which does this. I want to
avoid using integer variables with ranges, because then I don't need too
many conversions for other operations for the block RAM interface and
parameter passing from external devices, which are all unsigned vectors.

I'm using this use-statements:

use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
F

Frank Buss

Frank said:
function adjustLength(value: unsigned; length: natural) return unsigned is
variable result: unsigned(length-1 downto 0);
begin
if value'length > length then
result := value(length-1 downto 0);
else
result := to_unsigned(0, length - value'length) & value;
end if;
return result;
end;

There was a small bug in the function if the length was already at the
right size, this is the corrected version:

function adjustLength(value: unsigned; length: natural) return unsigned is
variable result: unsigned(length-1 downto 0);
begin
if value'length >= length then
result := value(length-1 downto 0);
else
result := to_unsigned(0, length - value'length) & value;
end if;
return result;
end;

This is very useful for other problems, too, like converting hex input from
RS232, entered in some terminal program, and sending it to an SPI port:

if rs232DataIn >= x"30" and rs232DataIn <= x"39" then
spiNibble <= adjustLength(rs232DataIn - x"30", 4);
startSpiTransfer;
elsif rs232DataIn >= x"61" and rs232DataIn <= x"66" then
spiNibble <= adjustLength(rs232DataIn - x"57", 4);
startSpiTransfer;
end if;
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,233
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top