0
\$\begingroup\$

I'm facing a error when I tried to simulate a circuit. It's a parallel-to-serial converter. With the first word, the circuit works well, i.e, the conversions occur. But with the second word the simulation stop, and throws an error without information.

Here my VHDL code:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY ParalelSequencial is
  port (
    clk: in std_logic;
    data_in: in std_logic_vector(0 to 7);
    start: in std_logic;
    data_out: out std_Logic
  );
end ParalelSequencial;

architecture behave of ParalelSequencial is
  signal start_bit: std_logic;
  signal stop_bit: std_logic;
  signal buff: std_logic_vector(0 to 9);
  signal control: integer range 0 to 9;
begin
  start_bit <= '0';
  stop_bit <='1';

  buff(0) <= start_bit;
  buff(9) <= stop_bit;

  buff(1 to 8) <= data_in;

  process (clk)
  begin
    if (rising_edge(clk)) then
      data_out <= '1';
      if (start = '1') then
        data_out <= buff(control);
        control <= control + 1;
        if (control = 9) then
          control <= 0;
        end if;
      end if;
    end if;
  end process;
end behave;
\$\endgroup\$
  • \$\begingroup\$ Show us your test bench, and show us your results. We can't help you unless you provide ALL of the details. \$\endgroup\$ – Dave Tweed Jan 4 at 23:45
  • 1
    \$\begingroup\$ I don't see how this could run for the first time as 'control' is never reset or initialised so stays 'U'. That would crash/fail buff(control). \$\endgroup\$ – Oldfart Jan 4 at 23:59
  • \$\begingroup\$ Incorrect Oldfart. control (signal control: integer range 0 to 9;) is a constrained integer whose 'LEFT bound 0 is used as the default value. There is no 'U' associated with an integer which is a numeric type (IEEE 1076-2008 5.2 Scalar types, 5.2.1 General, first paragraph). 'U' would be an enumeration value from a character enumerated type (5.2.2 Enumeration types, 5.2.2.1 General), here declared in package std_logic_1164. \$\endgroup\$ – user8352 Jan 5 at 0:15
  • \$\begingroup\$ For some reason, if i sets the control range to 0 to 10, it works, but I can't explain why, it's like before a length overflow occurred in buff signal. \$\endgroup\$ – Bruno Otavio Jan 5 at 1:45
3
\$\begingroup\$

For some reason, if i sets the control range to 0 to 10, it works, but I can't explain why, it's like before a length overflow occurred in buff signal.

It can be demonstrated with a a simple testbench:

library ieee;
use ieee.std_logic_1164.all;

entity paralelsequencial_tb is
end entity;

architecture foo of paralelsequencial_tb is
    signal clk:         std_logic := '0';
    signal data_in:     std_logic_vector(7 downto 0) := (others => '0');
    signal start:       std_logic := '0';
    signal data_out:    std_logic;
begin
DUT:
    entity work.paralelsequencial
        port map (
            clk => clk,
            data_in => data_in,
            start => start,
            data_out => data_out
        );
CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if now > 200 ns then
            report " now = " & time'image(now);
            wait;
        end if;
    end process;
STIMULI:
    process
    begin
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        start <= '1';
        wait until rising_edge(clk);  -- 10 clocks
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        start <= '0';
        wait until rising_edge(clk);
        wait;
    end process;

end architecture;
ghdl -a paralelsequencial.vhdl
ghdl -e paralelsequencial_tb
ghdl -r paralelsequencial_tb --wave=paralelsequencial_tb.ghw
./paralelsequencial_tb:error: bound check failure at paralelsequencial.vhdl:33
./paralelsequencial_tb:error: simulation failed

The explanation can be seen in the IEEE Std 1076-2008 VHDL standard, 10.5.2.2 Executing a simple assignment statement:

For the execution of a simple waveform assignment statement whose target is of a scalar type, the waveform on its right-hand side is first evaluated. Evaluation of a waveform consists of the evaluation of each waveform element in the waveform. Thus, the evaluation of a waveform results in a sequence of transactions, where each transaction corresponds to one waveform element in the waveform. These transactions are called new transactions. It is an error if the sequence of new transactions is not in ascending order with respect to time. It is also an error if the value of any value expression in the waveform does not belong to the subtype of the target.

The value expression here is the control + 1 on the line:

        control <= control + 1;

control is evaluated to determine if the current value is 9 in the following line while the incremented value 10 doesn't belong to the subtype of control.

You can reorder the evaluation of control in the process in the architecture of paralelsequencial to prevent assigning a waveform outside the subtype:

    process (clk)
    begin
        if rising_edge(clk) then
            data_out <= '1';
            if start = '1' then
                data_out <= buff(control);
                if control = 9 then
                    control <= 0;
                else
                    control <= control + 1;
                end if;
            end if;
        end if;
    end process;

And that would allow your VHDL code to simulate:

paralelsequencial.jpg

You'd expect a testbench used for validating a design unit might be more complex. This one simply demonstrates the error and the fix.

History

The behavior described in 10.5.2.2 quoted above is specific to -2008. If we look in -1993 or -2002 8.4.1 Updating a projected output waveform, Notes:

5—No subtype check is performed on the value component of a new transaction when it is added to a driver. Instead, a subtype check that the value component of a transaction belongs to the subtype of the signal driven by the driver is made when the driver takes on that value (see 12.6.1).

Nor is the quoted semantic rule "It is also an error if the value of any value expression in the waveform does not belong to the subtype of the target." present.

However Notes are advisory and in -2008 1.3.4 Front matter, examples, notes, references, and annexes:

Notes are meant to emphasize consequences of the rules described in the clause or elsewhere. In order to distinguish notes from the other narrative portions of this standard, notes are set as enumerated paragraphs in a font smaller than the rest of the text.

There is no other supporting text for the note which has no semantic weight by itself.

You'd find there are earlier revision implementations that also perform the subtype check when evaluating waveform transactions.

The -2008 change with the added sentence "It is also an error if the value of any value expression in the waveform does not belong to the subtype of the target." and eliminating Note 5 is found in Language Change Specification LCS-2006-006 resulting from Issue Report 2013 which resolves other subtype checking issues.

It was possible to implement VHDL relying solely on the subtype check semantically required in (-2008) 14.7.3.4 Signal update (12.6.2 Propagation of signal values in -1993, -2002) prior to -2008.

So why does it matter where the subtype test is performed?

Resumption, execution and subsequent suspension of any process sensitive to a signal event occurs after any signal updates. Signal updates use projected output waveform values from scheduled updates. (14.7.5.3 Simulation cycle, 14.7.3.4 Signal update)

Signal assignment controls the contents of projected output waveform queues. (10.5.2.2 Executing a simple assignment statement)

If you don't perform the subtype check on new transaction values the original statement order would not be erroneous. A new transaction scheduled for the same simulation time replaces any existing transaction for the same simulation time.

The preceding control <= control + 1; would schedule a new transaction value for the current simulation time. The following if statement with the condition control = 9 would result in a new transaction value of 0 being scheduled for he current simulation time supplanting the previous new transaction.

Without the added rule in -2008 requiring a value in a waveform be of the subtype of assignment target the subtype check during signal update wouldn't see the transaction with a value of 10.

This represents a portability issue between different implementations that are otherwise compliant to standard revisions prior to -2008 (Annex D):

A description is considered portable if it

a) Compiles, elaborates, initializes, and simulates to termination of the simulation cycle on all conformant implementations, and
b) The time-variant state of all signals and variables in the description are the same at all times during the simulation,

under the condition that the same stimuli are applied at the same times to the description. The stimuli applied to a model include the values supplied to generics and ports at the root of the design hierarchy of the model, if any.

Eliminating 'holes' in the standard is a good thing.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.