Aller au contenu

Non-synthesizable VHDL examples

There are instructions in VHDL that are not synthesizable, they are not intended to be used to describe an electronic circuit. The usefulness of these instructions is that they facilitate simulations and the rapid creation of golden models (functional reference model for comparison with the circuit that we want to design).

Test bench file

A test bench is a VHDL file that will only be used to test one or more components. Its VHDL description is not necessarily synthesizable, it is even rarely synthesizable. Indeed we often use non-synthesizable features such as wait and after

A test bench is a module that has no inputs/outputs, it only includes one or more components, drives their inputs and possibly monitors their outputs.

Test bench

Test bench
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-- exemple de test bench

entity tb_Module is
end tb_Module;

architecture archi_tb_Module of tb_Module is

component Module is     -- module que l'on souhaite tester
    generic(
        G_GenericA  : integer;
        G_GenericB  : integer
    );
    port(
        I_Clock         : in  std_logic;
        I_Reset         : in  std_logic;
        I_Enable        : in  std_logic;
        I_Data          : in  std_logic_vector(G_GenericA-1 downto 0);
        I_Address       : in  std_logic_vector(G_GenericB-1 downto 0);
        O_Ready         : out std_logic;
        O_ResultValid   : out std_logic;
        O_Result        : out std_logic_vector(G_GenericA+G_GenericB-1 downto 0)
    );
end component;

constant CST_GENERIC_A  : integer := 12;
constant CST_GENERIC_B  : integer := 5;

signal SR_Clock         : std_logic := '0';
signal SR_Reset         : std_logic;
signal SR_Enable        : std_logic;
signal SR_Data          : std_logic_vector(CST_GENERIC_A-1 downto 0);
signal SR_Address       : std_logic_vector(CST_GENERIC_B-1 downto 0);
signal SC_Ready         : std_logic;
signal SC_ResultValid   : std_logic;
signal SC_Result        : std_logic_vector(CST_GENERIC_A+CST_GENERIC_B-1 downto 0);

begin

    SR_Clock <= not SR_Clock after 7 ns;

    SR_Reset <= '1' , '0' after 59 ns , '1' after 2313 ns , '0' after 2350 ns;

    instance1_Module : Module
        generic map(
            G_GenericA  => CST_GENERIC_A    ,
            G_GenericB  => CST_GENERIC_B
        )
        port map(
            I_Clock         => SR_Clock         ,
            I_Reset         => SR_Reset         ,
            I_Enable        => SR_Enable        ,
            I_Data          => SR_Data          ,
            I_Address       => SR_Address       ,
            O_Ready         => SC_Ready         ,
            O_ResultValid   => SC_ResultValid   ,
            O_Result        => SC_Result
        );

    process     -- process de pilotage des entrees du composant a tester
    begin
        SR_Enable   <= '0';
        SR_Data     <= (others => '0');
        SR_Address  <= (others => '0');
        wait for 61 ns;                     -- wait : instruction non synthetisable
        wait until rising_edge(SR_Clock);
        SR_Enable   <= '1';
        SR_Data     <= std_logic_vector(to_unsigned (111 , CST_GENERIC_A));
        SR_Address  <= std_logic_vector(to_unsigned (15 , CST_GENERIC_B));
        wait until rising_edge(SR_Clock);
        SR_Enable   <= '1';
        SR_Data     <= std_logic_vector(to_unsigned (1 , CST_GENERIC_A));
        SR_Address  <= std_logic_vector(to_unsigned (7 , CST_GENERIC_B));

        -- ... --

    end process;

end archi_tb_Module;

Text file manipulation

To simulate a circuit it is sometimes very useful to be able to manipulate text files in a test bench or even in a circuit (before synthesis). We can use a text file to :

  • store values to be applied to inputs
  • store expected internal or output values and compare them to the values present at the output of the circuit
  • initialize RAM content of a circuit on FPGA

Input text file content:

1
2
3
4
5
6
7
8
12 13
15 14
11 2
1234 678
345 234
12 987
-12   -87
  -3124 9786
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use STD.textio.all;

entity testStdLogicTextio is
end entity testStdLogicTextio;

architecture arch of testStdLogicTextio is
  file F_input      : text open read_mode is "../input.txt";
  file F_output     : text open write_mode is "../output.txt";
  signal SR_Clock   : std_logic := '0';
  signal SR_reset   : std_logic;
  signal SR_Value1  : integer;
  signal SR_Value2  : integer;
  signal SR_Value3  : integer;
  signal SR_Value4  : integer;
  signal SR_reading : std_logic;

begin

  SR_reset <= '1', '0'     after 3 ns;
  SR_Clock <= not SR_Clock after 10 ns;

  process (SR_Clock, SR_reset) is
    variable theline  : line;
    variable V_Value1 : integer;
    variable V_Value2 : integer;
  begin
    if(SR_reset = '1')then
      SR_Value1  <= 0;
      SR_Value2  <= 0;
      SR_reading <= '0';
    elsif rising_edge(SR_Clock) then
      if(not endfile(F_input))then
        readline(F_input, theline);
        read(theline, V_Value1);
        SR_Value1  <= V_Value1;
        read(theline, V_Value2);
        SR_Value2  <= V_Value2;
        SR_reading <= '1';
      else
        SR_reading <= '0';
      end if;
    end if;
  end process;

  SR_Value3 <= SR_Value1*SR_Value2;
  SR_Value4 <= SR_Value2+SR_Value1;

  process (SR_Clock, SR_reset) is
    variable theline : line;
  begin
    if SR_reset = '1' then
    elsif rising_edge(SR_Clock) then
      if(SR_reading = '1')then
        write(theline, string'("Op1 = "));
        write(theline, SR_Value1, left, 8); --alignement a gauche, taille minimum de 8 caracteres
        write(theline, string'("Op2 = "));
        write(theline, SR_Value2, left, 8); --alignement a gauche, taille minimum de 8 caracteres
        write(theline, string'("ResMult = "));
        write(theline, SR_Value3, right, 4); --alignement a droite, taille minimum de 4 caracteres
        write(theline, string'("   ResAdd = "));
        write(theline, SR_Value4, left, 9); --alignement a gauche, taille minimum de 9 caracteres
        writeline(F_output, theline);
        -- les deux lignes ci-dessous sont expliquees dans la section suivante
        assert SR_Value1 > SR_Value2 report "SR_Value1 = " &integer'image(SR_Value1) severity warning;
        assert SR_Value1 > SR_Value2 report "SR_Value2 = " &integer'image(SR_Value2) severity warning;
      end if;
    end if;
  end process;

end architecture arch;

Output text file:

1
2
3
4
5
6
7
8
Op1 = 12      Op2 = 13      ResMult =  156   ResAdd = 25
Op1 = 15      Op2 = 14      ResMult =  210   ResAdd = 29
Op1 = 11      Op2 = 2       ResMult =   22   ResAdd = 13
Op1 = 1234    Op2 = 678     ResMult = 836652   ResAdd = 1912
Op1 = 345     Op2 = 234     ResMult = 80730   ResAdd = 579
Op1 = 12      Op2 = 987     ResMult = 11844   ResAdd = 999
Op1 = -12     Op2 = -87     ResMult = 1044   ResAdd = -99
Op1 = -3124   Op2 = 9786    ResMult = -30571464   ResAdd = 6662

assert instruction

There is an instruction that displays messages in the simulator's dialog window. It is called assert This instruction allows several levels of criticality:

  • note
  • warning
  • error
  • failure (arrêt de la simulation)
1
2
assert SR_Value1 > SR_Value2 report "SR_Value1 = " &integer'image(SR_Value1) severity warning;
assert SR_Value1 > SR_Value2 report "SR_Value2 = " &integer'image(SR_Value2) severity warning;

The message is displayed if the Boolean condition is false.


Dernière mise à jour: March 19, 2024