Question

How can I implement a VHDL function which has "don't care" inputs and have the "don't cares" be directly represented?

Exercise 4.8-2a of Free Range VHDL asks me to:

...write VHDL models that implement these functions using...selected signal assignment.

a) F (A, B, C, D) = A'CD' + B'C + BCD'

This code works:

library ieee;
use ieee.std_logic_1164.all;

entity funca_selected is
  port (
    a: in std_ulogic;
    b: in std_ulogic;
    c: in std_ulogic;
    d: in std_ulogic;
    x: out std_ulogic);
end entity;

architecture rtl of funca_selected is
  signal s: std_ulogic_vector(3 downto 0);
begin
  s <= a & b & c & d;
  with s select x <=
    '1' when "0010" | "0110" | "0011" | "1010" | "1011" | "1110",
    '0' when others;
end architecture;

It is, however, a poor representation of the function definition. I want to code it using "don't care" inputs so that the code more closely matches the definition. This would be less work, and easier to get right. I tried this:

  with s select x <=
    '1' when "0-10" | "-01-" | "-110",
    '0' when others;

This does not work: When my test bed exercises this function, the result is always '0'.

I am using GHDL version 0.29+gcc4.3.i386.

How can a VHDL function represent "don't care" inputs?

Was it helpful?

Solution

With overbar notation (like A̅) the function from exercise 4.8-2a is:

F(A, B, C, D) = A̅CD̅ + B̅C + BCD̅

GHDL does only support up to at most VHDL-2000 (according to GHDL features), so none of the VHDL-2008 compare operations with don't care ('-') check are available. An alternative expression for GHDL is the expression:

x <= ((not a) and c and (not d)) or
     ((not b) and c) or
     (b and c and (not d));

However, if VHDL-2008 is available in the tools, then the ?= operator, which checks for don't care, can be used as:

x <= (s ?= "0-10") or (s ?= "-01-") or (s ?= "-110");

Note that this expression also applies VHDL-2008 implicit boolean to std_logic conversion.

Or a case?, which also checks for don't care, can be used as:

process (s) is
begin
  case? s is
    when "0010" | "0110" | "0011" | "1010" | "1011" | "1110" => x <= '1';
    when others => x <= '0';
  end case?;
end process;

There is no with? operator in VHDL-2008 for concurrent case-like assign.

For more information about VHDL-2008 features, there is a nice paper here VHDL-2008: Why It Matters.

OTHER TIPS

I tried both versions of the logic in Xilinx ISE 14.6 and both versions work, but there are some caveats. First of all, when I compare the RTL Schematic of the "don't care" version with the explicit version the "don't care" version is much simpler and more optimized. "Don't care" version has four logic gates and maximum input lines per gate are three lines. The explicit version has seven logic gates and maximum input lines per gate are six lines.

When I test bench the two version I have four different simulation options: Behavioral, Post-Translate, Post-Map, and Post-Route. In the Behavioral model the "don't care" version output is a flat line like you stated and it appears that the "don't care" version does not work, however, in all three other simulation options both versions work perfectly and output is identical. So it looks like the behavioral model does not know how to handle the "don't care" parts of the VHDL code, but the code is synthesizable and using "don't care" in the VHDL code is very valuable.

Comparisons in VHDL are a very pure element by element exact match. This was one of VHDLs daftnesses which got an extension to fix it in VHDL-2008, with the case? statement and =? operator

http://www.doulos.com/knowhow/vhdl_designers_guide/vhdl_2008/vhdl_200x_small/#matchcase

Unfortunately, VHDL-2008 isn't supported in GHDL, so you'll have to use the std_match function, which I think also precludes the use of with..select.

Yes, ghdl can only be counted on to be IEEE Std 1076-1993 compliant, and there's a hole or two at that.

The function could be simpler when we realize the first term (A̅CD̅) isn't needed, no where is the result dependent on it. The first product term is never uncovered in the output.

Regardless the evaluation target of a selected signal assignment is an expression. You could use the expression from MortenZdk's concurrent signal assignment statement:

library ieee;
use ieee.std_logic_1164.all;

entity f_test is
end;
architecture test of f_test is

    subtype vector is  std_logic_vector (3 downto 0);
    type    vectorstream is array (0 to 15) of vector;

    constant stimulous: vectorstream  :=(
    x"0",x"1",x"2",x"3",x"4",X"5",x"6",x"7",
    x"8",x"9",x"A",x"B",x"C",x"D",x"E",X"F"
    );

    signal index: integer range 0 to 15;

    signal a,b,c,d: std_logic;

    signal x:   std_logic;

begin
Test_Vectors:
    process
        variable TV: std_logic_vector(3 downto 0);
    begin
        -- first term is valid
        for i in vectorstream'range loop

                index <= (i);   -- make vector index  visible in waveform
                TV  := vector(stimulous(i));
                a <= TV(3); b <= TV(2); c <= TV(1); d <= TV(0);  
                wait for 10 ns;                      
            end loop;

            wait;  -- ends simulation

    end process;
EVALUATE:  -- "the code more closely matches the definition"

    with TO_X01(
                ( not a           and c and not d) or  -- b is don't care
                (           not b and c          ) or  -- a, d are don't care
                (               b and c and not d)     -- a is don't care
               ) select x <= '1' when '1',
                             '0' when '0',
                             'X' when 'X';  -- equivalent of 'else 'X' in 
                                            -- concurrent signal assignment

end;

TO_X01 is called a strength stripper, is from the package std_logic_1164 and evaluates to either an 'X' a '0' or a '1'.

The selected signal assignment has a conditional signal assignment equivalent and both can be expressed as processes, which is how they are simulated.

ghdl -a f_test.vhdl
ghdl -r f_test --wave=f_test.ghw
open f_test.ghw

gtkwave simulation result

You could add to stimulous allowing the demonstration of propagating other element values as specified in the stdlogic_table for "and" and for "or" in the std_Logic_1164 package mapped to type X01 to reduce the number of choices in the selected signal assignment statement.

Also note in select x <= '1' when '1', the first '1' refers to a std_logic value while the second '1' refers to a value of type X01.

You can comment out the first product term line for A̅CD̅ to demonstrate it has no affect on the result x.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top