Kooss
Kooss

Reputation: 71

std_logic_vector to integer conversion vhdl

I faced with conversion problem/I read a lot of similar topics but my code still not working.Could you pls give me some hints. Quartus give me error:

Error (10476): VHDL error at true_dual_port_ram_single_clock.vhd(44): type of identifier "random_num_i" does not agree with its usage as "std_logic_vector" type

LIBRARY ieee;
USE ieee.std_logic_1164.all;
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;

entity write_ram is
  generic(width : integer := 32);
  port(clock_i  : IN  STD_LOGIC;
       we_w     : IN  STD_LOGIC;
       wr_addr  : IN  INTEGER RANGE 0 to 31;
       read_add : IN  INTEGER RANGE 0 to 31;
       q_out    : out STD_LOGIC_VECTOR(2 DOWNTO 0)
  );
end write_ram;

architecture rtl of write_ram is
  --- Component decalarartion
  component random is
    port(clk        : in  std_logic;
         random_num : out std_logic_vector(width - 1 downto 0) --output vector 
    );
  end component;

  component single_clock_ram is
    port(clock         : IN  STD_LOGIC;
         data          : IN  INTEGER RANGE 0 to 31;
         write_address : IN  INTEGER RANGE 0 to 31;
         read_address  : IN  INTEGER RANGE 0 to 31;
         we            : IN  STD_LOGIC;
         q             : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
    );
  end component;
  for all : random use entity work.random(rtl);
  for all : single_clock_ram use entity work.single_clock_ram(rtl);
  Signal random_num_i : INTEGER RANGE 0 to 31; --interanal signals
begin
  -- Component Instantiation

  C1 : random Port map(
      clk        => clock_i,
      --random_num <=to_integer(to_signed(random_num_i))
      random_num => random_num_i
    );
  random_num <= to_integer(to_signed(random_num_i)); -- error

  C2 : single_clock_ram
    Port map(
      clock         => clock_i,
      we            => we_w,
      read_address  => read_add,
      write_address => wr_addr,
      data          => random_num_i,
      q             => q_out
    );

end rtl;

Upvotes: 4

Views: 23398

Answers (2)

user1155120
user1155120

Reputation:

Your question isn't an MCVE with the configuration specifications for random and single_clock_ram present. You didn't supply the entity declarations and architecture bodies (rtl) for them.

With them commented out this analyzes:

library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_signed.all;  -- NOT USED
-- use ieee.std_logic_unsigned.all;  -- NOT USED
use ieee.numeric_std.all;
-- use ieee.std_logic_arith.all;  -- NOT USED

entity write_ram is
  generic (width:  integer := 32);
  port (clock_i:   in  std_logic;
        we_w:      in  std_logic;
        wr_addr:   in  integer range 0 to 31;
        read_add:  in  integer range 0 to 31;
        q_out:     out std_logic_vector(2 downto 0)
  );
end entity write_ram;

architecture rtl of write_ram is
  --- component declaration
  component random is
    port (clk:         in  std_logic;
         random_num:   out std_logic_vector(width - 1 downto 0) --output vector 
    );
  end component;

  component single_clock_ram is
    port (clock:          in  std_logic;
          data:           in  integer range 0 to 31;
          write_address:  in  integer range 0 to 31;
          read_address:   in  integer range 0 to 31;
          we:             in  std_logic;
          q:              out std_logic_vector(2 downto 0)
    );
  end component;
  -- for all:  random use entity work.random(rtl);
  -- for all:  single_clock_ram use entity work.single_clock_ram(rtl);
  signal random_num_i:  integer range 0 to 31; -- internal signals 
  signal random_num:   std_logic_vector(width - 1 downto 0); -- added
begin
  -- component instantiation

  c1:  random port map (
      clk        => clock_i,
      -- random_num <=to_integer(to_signed(random_num_i))
      -- random_num => random_num_i  -- DELETED
      random_num => random_num   -- ADDED
    );
  -- random_num <= to_integer(to_signed(random_num_i)); -- error DELETED
  random_num_i <= to_integer(signed(random_num));   -- ADDED

  c2:  single_clock_ram
    port map (
      clock         => clock_i,
      we            => we_w,
      read_address  => read_add,
      write_address => wr_addr,
      data          => random_num_i,
      q             => q_out
    );

end architecture rtl;

Note there's been a random_num std_logic_vector declared to hook up to the output of random, which is converted an integer random_num_i used as an input to single_clock_ram data. The output q from the single_clock_ram looks a bit suspicious, should that be an integer or a wider std_logic_vector?

Upvotes: 2

user1818839
user1818839

Reputation:

First, delete the non-standard libraries.

use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.STD_LOGIC_ARITH.ALL;

leaving only std_logic_1164 and numeric_std.

The others introduce a bunch of overlapping declarations which make it difficult to determine what is going on - and if there are several declarations for the same operator with the same argument and result types, the compiler makes them all invisible rather than picking an arbitrary one.


Then, decide what you are trying to do. This is currently ambiguous and contradictory.

(1)You have a generic (width : integer :=32); and a port declaration

random_num : out std_logic_vector (width-1 downto 0)

which suggest you are dealing with 32 bit words.

(2) You have a ranged integer : Signal random_num_i: INTEGER RANGE 0 to 31; which (a) should be a ranged NATURAL to make it even clearer that negative values are errors, and (b) suggests you are dealing with 5 bit words.

Which is it? What exactly are you trying to do?

And here, you are apparently trying to connect them together in a port map...

 C1: random Port map ( 
     clk => clock_i,
     --random_num <=to_integer(to_signed(random_num_i))
     random_num =>random_num_i
 );
 random_num <=to_integer(to_signed(random_num_i)); -- error

There are a number of things wrong here.

1) A simple port mapping like random_num =>random_num_i requires that both sides have the same type. This would work if both sides actually WERE the same type : for example, if you added a signal declaration

random_num_slv : std_logic_vector (width-1 downto 0);

then the port mapping random_num =>random_num_slv would work. Now you can convert to the required type random_num_i in a signal assignment.

random_num_i <= to_integer (unsigned(random_num_slv));

There are still problems with this : a 32-bit output is likely to overflow a 5-bit integer.

While adding an intermediate signal random_num_slv may look inefficient and redundant, it keeps the design clean and simple, which matters when dealing with tools that don't understand type conversions in ports.

Make sure you know how to use intermediate signals even if there's a cleaner approach. It can save you when all else fails.

(2) The commented out port mapping

 random_num <=to_integer(to_signed(random_num_i))

would be the way to do it, except for three things ... (a) <= is a signal assignment, you need => a n association operator (b) you're converting an integer to an integer, and driving a std_logic_vector with it. That really won't work... (c) the component port is an OUTPUT so you shouldn't be driving it in the first place.

What you probably meant was

   to_integer(unsigned(random_num)) => random_num_i

and this would be the cleanest way to do it if your tools support conversions in port maps properly. Notes:

  • again it has the overflow problem, a 32-bit vector won't fit a 5 bit integer.
  • You can convert from std_logic_vector to either signed or unsigned by casting unsigned rather than a conversion function to_signed as they are closely related types. Integers are not "closely related" to these, so need a conversion function to_integer.
  • As negative numbers aren't permitted by the declaration of random_num_i, use unsigned rather than signed.

(3) The existing signal assignment

random_num <=to_integer(to_signed(random_num_i)); -- error

again contains several errors. The biggest is that there is no random_num port visible outside the component declaration. Simply delete this line, you need to use one of the port mappings.


Further considerations:

(1) Some type conversions are inevitable. But if you are doing too many, that generally points to a design error, like the use of std_logic_vector everywhere, even for thengs like addresses which are inevitably unsigned integers so either unsigned ornatural would be a better choice. Keep the design as simple and readable as possible. I think your use of integer here is generally good but natural would be better (unless you need negative addresses!)

(2) If you're adding the flexibility of a generic like width, use it correctly and consistently - OR - check it's valid.

Here, as described above, your design ONLY works correctly without surprises IF this entity is instantiated with width => 5.

So, check the value and abort if this precondition is not met.

assert Width = 5 report "Width of " & natural'image(width) & " not supported!" 
   severity FAILURE;

OR make the design work for all reasonable values of the generic, for example by making other quantities dependent on it in valid ways. For example:

   constant DEPTH : natural := 2**WIDTH - 1;
   signal random_num_i : natural range 0 to DEPTH;

and so on...

Upvotes: 1

Related Questions