2
votes

Is there a data type in VHDL that is an array like a "std_logic_vector", but instead of having all having 9 possible states:

'U': uninitialized. This signal hasn't been set yet. 
'X': unknown. Impossible to determine this value/result. 
'0': logic 0 
'1': logic 1 
'Z': High Impedance 
'W': Weak signal, can't tell if it should be 0 or 1. 
'L': Weak signal that should probably go to 0 
'H': Weak signal that should probably go to 1 
'-': Don't care. 

has only two possible states:

'0': logic 0 
'1': logic 1 

The reason why I ask this is because i'm looking for the VHDL equivalent of the verilog case statement. Verilog Example:

module m1(input a, input b, output reg[7:0] q);
wire [1:0] sel = {a, b};
always @* begin
    case(sel)
    2'b00: q = 8'd1;
    2'b01: q = 8'd2;
    2'b10: q = 8'd3;
    2'b11: q = 8'd4;
    endcase
end 
endmodule

In VHDL, I can do this with no problems:

entity m1 is
    port(
        a :in std_logic;
        b :in std_logic;
        q :out std_logic_vector(7 downto 0)
    );
end entity;
architecture rtl of m1 is
    signal sel :std_logic_vector(1 downto 0);
begin
    sel <= a & b;

    process(sel)
    begin
        case sel is
        when "00" => q <= 1;
        when "01" => q <= 2;
        when "10" => q <= 3;
        when "11" => q <= 4;
        end case;
   end process;

end architecture;

The problem with this is that both Xilinx ISE and Modelsim refuse to compile this code saying that I didn't cover the states for 'X', 'U', 'L', 'H', etc... so i need to add a "when others => q <= 'X';" statement to my VHDL....

Then, when I compile the code with Vivado, it says, "WARNING: you have a default case eventhough your full case was covered." so then I delete the "when others=>" clause of the case...

Well, this is just annoying... is there a way to get it to work in every tool without generating either an ERROR message or a bogus warning message?

My idea was to just use an array type that can be only "0" or "1" like an integer... but instead more like std_logic_vector without supporting all the other logic states that mess up the case select and require the "when others =>" clause....

possible? its there a VHDL data type like this already built in? an array of only '0' or '1' and nothing else specifically for catatentating together and being used as a case selection? integer types don't have 'U' or 'X', but are perfectly ok to use in a VHDL case... i'm wondering if the same holds for an array type of ('0', '1')?

2
The others case can be useful in simulation if you've got some odd signals coming in, you'll then put XXs on Q - which is useful to see on a waveform. A lot of people often omit the when "11" case, and just put the final case in when others, but this covers errors states also - possibly masking an error. This is the same if you convert the slv to a bitvector. - Tricky

2 Answers

1
votes

You should stick with std_logic and std_logic_vector, an other post is presenting the differences: When to use STD_LOGIC over BIT in VHDL

I think your problem comes (also) from the fact that you are putting an integer into a std_logic_vector. You should use the conversion functions:

  • to_unsigned(arg: natural, size: natural) return unsigned
  • std_logic_vector(arg: signed or unsigned) return std_logic_vector

Which leads you to:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all; --DO NOT FORGET THIS LIBRARY TO USE THE CONVERSION FUNCTION

entity m1 is
    port(
        a :in std_logic;
        b :in std_logic;
        q :out std_logic_vector(7 downto 0)
    );
end entity;

architecture rtl of m1 is
    signal sel :std_logic_vector(1 downto 0);
begin
    sel <= a & b;

    process(sel)
    begin
        case sel is
        when "00" => q <= std_logic_vector(to_unsigned(1,q'length));
        when "01" => q <= std_logic_vector(to_unsigned(2,q'length));
        when "10" => q <= std_logic_vector(to_unsigned(3,q'length));
        when "11" => q <= std_logic_vector(to_unsigned(4,q'length));
        when others => q <= std_logic_vector(to_unsigned(1,q'length));
        end case;
   end process;

end architecture;
0
votes

Try VHDL Predefined Types from the package standard:

type bit is ('0', '1');
type bit_vector is array (natural range <>) of bit;

funciton to_stdlogicvector (b :bit_vector)  return std_logic_vector;
function to_bitvector      (s :std_ulogic_vector) return bit_vector;
architecture rtl of m1 is
    signal sel :std_logic_vector(1 downto 0);
    signal bv  :bit_vector(1 downto 0);
begin
    sel <= a & b;
    bv  <= to_bitvector(sel);

    process(bv)
    begin
        case bv is
        when "00" => q <= 1;
        when "01" => q <= 2;
        when "10" => q <= 3;
        when "11" => q <= 4;
        end case;
   end process;

end architecture;