VHDL typecast signed to std_logic_vector

有些话、适合烂在心里 提交于 2020-01-06 04:34:06

问题


I am looking at this example and below answer which is a nice solution to produce two's complement:

library ieee;
use ieee.numeric_std.all;
entity twoscomplement is
  generic
  (
     Nbits : positive := 8 
  );
  port 
  ( 
     A : in  unsigned (Nbits-1 downto 0);
     Y : out signed   (Nbits downto 0)
  );
end entity twoscomplement;

architecture a1 of twoscomplement is
begin
  Y <= -signed(resize(A, Y'length));
end architecture;

I want to use the said example to have two's complement and then make a "16-bit subtractor". The code will look like the following:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity subtractor_16bit is
  Port (    a     : in STD_LOGIC_VECTOR(15 downto 0);
            b     : in STD_LOGIC_VECTOR(15 downto 0);
            cin   : in STD_LOGIC;
            sum   : out STD_LOGIC_VECTOR(15 downto 0);
            cout  : out STD_LOGIC;
            over  : out STD_LOGIC
            );
end subtractor_16bit;

architecture Behavioral of subtractor_16bit is

component fulladder_16bit is
  Port (
          a     : in STD_LOGIC_VECTOR(15 downto 0);
          b     : in STD_LOGIC_VECTOR(15 downto 0);
          cin   : in STD_LOGIC;
          sum   : out STD_LOGIC_VECTOR(15 downto 0);
          cout  : out STD_LOGIC;
          over  : out STD_LOGIC
         );
end component;

component twoscomplement is
  Port (
        A : in  unsigned (15 downto 0);
        C : out signed (15 downto 0) 
        );
end component;

signal n1 : STD_LOGIC_VECTOR(15 downto 0);

begin

    twoscomplement_1: twoscomplement port map (a => a ,c => n1); --ERROR
    fulladder_16bit_1: fulladder_16bit port map (a => a, b => n1, sum => sum , cin => cin, cout => cout, over => over);

end Behavioral;

However, I am receiving an error saying: Error: type error near a; current type std_logic_vector; expected type unsigned.

Kindly help me to solve this problem.


回答1:


As nobody is answering this and nobody is down voting it, I will answer.

Look at the error

Error: type error near a; current type std_logic_vector; expected type unsigned.

Now look at entity subtractor_16bit.

[...]
entity subtractor_16bit is
    Port (    a     : in STD_LOGIC_VECTOR(15 downto 0);
[...]
    component twoscomplement is
        Port (
            A : in  unsigned (15 downto 0);
[...]
    twoscomplement_1: twoscomplement port map (a => a ,c => n1);
[...]

What do you see? twoscomplement expects an unsigned, while a is std_logic_vector! Just like the error says.

std_logic_vector and unsigned are two separate types. As VHDL is a strongly typed language, you cannot just put the data from one type to another. You need to use type conversion.

For unrelated types, you should implement a type conversion function. Or functions, if you want bidirectional conversion. E.g.

function (input : type_a) return type_b;

But in this case, std_logic_vector and unsigned have the same underlying type, std_logic. (std_ulogic actually since VHDL-2008 I believe.) In that case you can convert from one type to another explicitly. E.g.

    signal a_u : unsigned(y downto 0);
    signal a_slv : std_logic_vector(y downto 0);
begin
    a_u <= unsigned(a_slv);

Next, your not instantiating the twoscomplement component properly. The entity has a generic Nbits. By default you set it to 8. But in your architecture Behavioral of subtractor_16bit, you feed it with 16 bits, without changing the generic value. That doesn't work.

Also: twoscomplement has two ports: A and Y. But in subtractor_16bit you start using A and C. That's bad coding practice.


Finally, you can drop the component declarations. Just instantiate the entities from the library. E.g.

twoscomplement_1: entity work.twoscomplement [...]

So, subtractor_16bit should look something like this:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity subtractor_16bit is
    Port (
        a     : in STD_LOGIC_VECTOR(15 downto 0);
        b     : in STD_LOGIC_VECTOR(15 downto 0);
        cin   : in STD_LOGIC;
        sum   : out STD_LOGIC_VECTOR(15 downto 0);
        cout  : out STD_LOGIC;
        over  : out STD_LOGIC
        );
end entity;

architecture structural of subtractor_16bit is
    use IEEE.NUMERIC_STD.ALL;
    signal n1 : signed(a'range);
begin
    twoscomplement_1: entity work.twoscomplement
        generic map(
            NBits => a'length
            )
        port map (
            a => unsigned(a),
            y => n1
            );
    fulladder_16bit_1: entity work.fulladder_16bit
        port map (
            a => a,
            b => std_logic_vector(n1),
            sum => sum,
            cin => cin,
            cout => cout,
            over => over
            );
end architecture;

...

HOWEVER this will still not work.

As you see on your entity twoscomplement, port A has a size of NBits, and port Y has a size of NBits+1. That is because you seem to want to keep 16-bit value precision. So when converting unsigned to signed, you need to add a 17th bit for the sign. As a result, the rest of you code will need to be modified!

.... But this can be fixed a different way. I will learn you something about two's complement: -a = not(a) + 1.

Proof (Take 4 bits signed precision):

  • 0 = b'0000 => -0 is not(b'0000)+1 = b'1111'+1 = b'0000'
  • 7 = b'0111 => -7 is not(b'0111)+1 = b'1000'+1 = b'1001'
  • -6 = b'1010' => 6 is not(b'1010)+1 = b'0101'+1 = b'0110'

See?

So now I will solve your puzzle for you:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity subtractor_16bit is
    Port (
        a     : in STD_LOGIC_VECTOR(15 downto 0);
        b     : in STD_LOGIC_VECTOR(15 downto 0);
        sum   : out STD_LOGIC_VECTOR(15 downto 0);
        cout  : out STD_LOGIC;
        over  : out STD_LOGIC
        );
end entity;

architecture structural of subtractor_16bit is
begin
    fulladder_16bit_1: entity work.fulladder_16bit
        port map (
            a => a,
            b => not(b),
            sum => sum,
            cin => '1',
            cout => cout,
            over => over
            );
end architecture;

You will still need to change/fix the cout and over behavior...



来源:https://stackoverflow.com/questions/46375014/vhdl-typecast-signed-to-std-logic-vector

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!