Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Output <= registers(to_integer(address)) and intentional meta values

Status
Not open for further replies.

adrianf0

Newbie level 3
Joined
Jun 18, 2019
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
46
Hi,
I have an array of std_logic_vectors. The address selector (unsigned type) may intentionally be unsigned to don't care/unknown state in order to simplify logic in other parts of a design. In such a case, the simulator will generate a warning, however, the output vector will be assigned to registers(0). My intention, in such a case, would be to assign don't care/unknown state also to the output vector. Is there any best practice for this problem?
I know that something like:
Code:
output <= (others => '-') when is_x(address) else registers(to_integer(address));
could work, but according to my knowledge, the is_x function may have a problem with synthesis.

Another option would be to write a process:

Code:
mux: process(all)
begin
  output <= (others => '-');
  for i in registers'range loop
    if address = to_unsgined(i, address'range) then
      output <= registers(i);
    end if;
  end loop;
end process;
However, I am worried that the synthesis tool may have an issue to extract a proper and simple mux from this description.

Is there any more straightforward description? I am using VHDL 2008.

Regards,
Adrian
 

I don’t understand why you would INTENTIONALLY assign ‘don’t care’’, or why it would ‘simplify logic’. I don’t even think that’s syntesizable (I’ve never tried it). Why don’t you just have a default case?
 

I am assigning don't care values in order to give more room for a synthesis tool. As an example, if you have data accompanied by a valid strobe, forcing them eg. to 0 when the strobe is not active, may not be the best from logic utilization point of view. You still need to assign something in order to avoid latches. The synthesis tool may decide that the most efficient is to assign data (when not used) to some pattern which occurs also when there is a valid strobe on the bus.
 

A better way is to do the normal assignments to "output" regardless of the valid bit. That will minimize the logic, and the result is predictable.

A similar approach can be used for processes to minimize the logic when not all signals need to be resetted:

Code:
Async reset:

process(clock, reset)
  if rising_edge(clock) then
    -- Do the normal stuff here, don't care about the reset signal
  end if;

  if reset = '1' then
    -- Set/reset only the signals that really need to be defined after reset
  end if;
end process;


Sync reset:

process(clock, reset)
  if rising_edge(clock) then
    -- Do the normal stuff here, don't care about the reset signal

    if reset = '1' then
      -- Set/reset only the signals that really need to be defined after reset
    end if;
  end if;
end process;

With the standard template, the synthesis tool must implement logic to keep the current value at reset for the signals that are missing in the reset part.
 
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
Sorry, I don't get your point.
What do you mean by normal assignment of the "output" vector?
The code:
Code:
output <= registers(to_integer(address))
will synthesise to a valid implementation.

As you see, I want to have a fully combinatorial logic (multiplexer). The address is a combinatorial output of the Mealy FSM. For some states of this FSM, in order to simplify FSM's logic, this address is assigned to don't care/unknown value. Now, in order to mimic hardware, the output vector of the above description should be assigned with a don't care/unknown value as well for the unknown address. However, to_integer will return 0 for vector containing meta values, which will be a valid choice of some register. It will create mismatch (source of potential, unnoticed bugs) between the behavioural verification and the actual hardware implementation.
 

Ok, I think I understand now.
There are two problems here:

1. How to write code to minimize the synthesized logic, maybe using '-' assignments

2. How to write code so "don't care" ('-') or "unknown" ('X') signals propagate to 'X' on the outputs in simulation

For point 1, I understand that you have paths in the state machine code for which it doesn't matter what value is assigned to an output signal.
You are correct that having no assignment creates logic to keep the current value. By assigning the value '-' (don't care), you tell the synthesis tool that any value is OK.
The tool can use a fixed '0' or '1', but also a value that depends on other signals.
In theory, this should give the synthesis tool more options to minimize the required logic.
The problem is that output signals that depend on such a signal will normally show up as 'X' in the simulation (which you actually want in this case).
I don't assign '-' to minimize logic, since if 'X' outputs are allowed, the risk is much higher that you miss a signal that should not be 'X'. Normally I consider an 'X' output as an error.
I often have a default assignment at the beginning of a process, with the most probable value. I then override that with a new assignment when necessary.
Maybe not the absolute minimum logic, but a very predictable result and no 'X' outputs in simulation.

Now to point 2, where you really want to output 'X' for signals that depend on a "don't care" signal.
In your example, the 'X' disappears in the to_integer function, but an optional "metavalue" warning will be generated by the simulator.
If the mux have a fixed size, it is easy to do your own with a "case" and an "others" that assigns 'X' to the outputs:
Code:
mux: process(all)
  case address is
    when "000" =>
      output <= registers(0);
    when "001" =>
      output <= registers(1);
    when "010" =>
      output <= registers(2);
    when "011" =>
      output <= registers(3);
    when "100" =>
      output <= registers(4);
    when "101" =>
      output <= registers(5);
    when "110" =>
      output <= registers(6);
    when "111" =>
      output <= registers(7);
    when others =>
      output <= (others => 'X');
  end case;
end process;
I know that the code above will work. The synthesis tool will ignore the "others" clause if all combinations of '0' and '1' are covered by the earlier "when" clauses.
It is possible that you can write a more generic loop that does the same thing, but I have not tried that with any synthesis tool.

One more thing about the synthesizeable code:
Only use '-' assignments to make optimizations possible for the synthesis tool. This means that you should probably never use '-' as stimuli in a test bench. Assign 'X' in the test bench if you want to see what depends on a signal.
To indicate an unknown output in simulation, assign 'X'. Only do that when all possible combinations of inputs with only '0' and '1' have been covered with other assignments, then the 'X' assignment will be ignored by the synthesis tool.

'-' is "don't care", used by the synthesis tool and the simulator. IMHO, don't use it in a test bench, only in the synthesizeable code.
'X' is "unknown", used only by the simulator.
 

Yes, you understand correctly the problem.

In the meantime, I solved the issue with my original idea:
Code:
output <= registers(to_integer(address)) when not Is_X(address) else (others => 'U');
I checked results generated by the synthesis tool, and it seems that it properly ignores (set False) Is_X branch and the generated netlist is equivalent to simple
Code:
output <= registers(to_integer(address));
 

and the generated netlist is equivalent to simple
output <= registers(to_integer(address));
Means there's no synthesis advantage?
 

output <= registers(to_integer(address)) when not Is_X(address) else (others => 'U');

You should assign 'X', not 'U'.
'U' is the default value for std_logic, and if you see it in simulation, it means that the signal has never been assigned anything.
You break this convention if you assign 'U'.
 

Means there's no synthesis advantage?

I think the OP already was satisfied with the synthesized logic for creation of the "address" signal.
This thread was started because the simulation would not show which output bits were unknown. registers(0) was used when address contained "unknown" or "don't care" bits.
It is bad if the RTL simulation says '0' when the synthesized circuit says '1'.
 

you always have pragma tricks for this as well.
eg:
Code:
constant kWhatever : std_logic := 
-- synthesis translate_off
'X' when true else
-- synthesis translate_on
'-';

-- other code

output <= registers(to_integer(address)) when condition_where_i_care = '1' else (others => kWhatever);

--edit: also, I'm not sure this is a common use case as Verilog doesn't have a don't care symbol and even in VHDL it isn't common knowledge that '-' is a thing. I suspect synthesis tools convert 'X', 'U', and '-' to either '0' or 'Z' based on tech. I wouldn't expect '-' to be beneficial unless the synthesis tool vendor specifically mentions it somewhere in documentation.

--edit2: fixed syntax. I haven't written VHDL in a while.
 
Last edited:

The synthesis tool will usually ignore is_x and will give it as a warning.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top