fault_injection_controller_tb.vhd 9.21 KB
Newer Older
1
--------------------------------------------------------------------------------
2
3
4
-- Fault InJection Instrumenter (FIJI)
-- https://embsys.technikum-wien.at/projects/vecs/fiji
--
5
6
7
8
-- The creation of this file has been supported by the publicly funded
-- R&D project Josef Ressel Center for Verification of Embedded Computing
-- Systems (VECS) managed by the Christian Doppler Gesellschaft (CDG).
--
9
10
11
-- Authors:
-- Christian Fibich <fibich@technikum-wien.at>
-- Stefan Tauner <tauner@technikum-wien.at>
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-0.51. Unless required by applicable
-- law or agreed to in writing, software, hardware and materials
-- distributed under this License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or
-- implied. See the License for the specific language governing
-- permissions and limitations under the License.
--
-- See the LICENSE file for more details.
--
-- Description:
--  Fault injection controller testbench file
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

library work;
use work.public_config_pkg.all;
use work.private_config_pkg.all;
use work.fault_injection_controller_pkg.all;

library std;
use std.textio.all;

-------------------------------------------------------------------------------

entity fault_injection_controller_tb is
  generic (
44
45
    g_data_file_name : string;          -- test vectors
    g_lfsr_file_name : string);
46
47
48
49
50
51
52

end entity fault_injection_controller_tb;

-------------------------------------------------------------------------------

architecture sim of fault_injection_controller_tb is

53
54
  constant c_bit_time        : time := (1000 ms) / c_baudrate;
  constant c_inter_byte_time : time := (5000 ms) / c_baudrate;
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

  -- component ports
  signal s_clk_i               : std_logic := '1';
  signal s_reset_n_i           : std_logic;
  signal s_data_i              : std_logic;
  signal s_data_valid_i        : std_logic;
  signal s_uart_error_i        : std_logic;
  signal s_shift_data_o        : std_logic;
  signal s_shift_enable_data_o : std_logic;
  signal s_injection_start_o   : std_logic;
  signal s_dut_reset_o         : std_logic;
  signal s_update_fius_o       : std_logic;
  signal s_msg_data_o          : std_logic_vector(6 downto 0);
  signal s_send_msg_o          : std_logic;
  signal s_byte_start_i        : std_logic;

  signal s_trigger_ext_i : std_logic;
  signal s_trigger_dut_i : std_logic;

  signal s_lfsr_o : std_logic_vector(c_lfsr_width-1 downto 0);

begin  -- architecture sim

  -- component instantiation
  DUT : fault_injection_controller
    port map (
      s_clk_i               => s_clk_i,
      s_reset_n_i           => s_reset_n_i,
      s_dut_reset_o         => s_dut_reset_o,
      s_data_i              => s_data_i,
      s_data_valid_i        => s_data_valid_i,
      s_uart_error_i        => s_uart_error_i,
      s_byte_start_i        => s_byte_start_i,
      s_trigger_ext_i       => s_trigger_ext_i,
      s_trigger_dut_i       => s_trigger_dut_i,
      s_shift_data_o        => s_shift_data_o,
      s_shift_enable_data_o => s_shift_enable_data_o,
      s_update_fius_o       => s_update_fius_o,
      s_injection_start_o   => s_injection_start_o,
      s_msg_data_o          => s_msg_data_o,
      s_send_msg_o          => s_send_msg_o,
      s_lfsr_o              => s_lfsr_o);

  -- clock generation
  s_clk_i     <= not s_clk_i after (1.0 / real(c_frequency)/2.0) * (1 sec);
  s_reset_n_i <= '0', '1'    after (1.0 / real(c_frequency)/2.0) * (1 sec);

  -- waveform generation
  WaveGen_Proc : process
    file f_data_in    : text open read_mode is g_data_file_name;
    variable L        : line;
    variable byte     : std_logic_vector(8 downto 0);
    variable cmd      : character;
    variable duration : time;
    variable bits     : integer;
    variable good     : boolean;
  begin
    s_data_i        <= '0';
    s_byte_start_i  <= '0';
    s_data_valid_i  <= '0';
    s_uart_error_i  <= '0';
    s_trigger_ext_i <= c_trigger_ext_active;
    s_trigger_dut_i <= c_trigger_dut_active;
    wait for c_inter_byte_time;
    l_readfile : while not endfile(f_data_in) loop
      readline(f_data_in, L);
      read(L, byte, GOOD => good);
      if not good then
        read(L, cmd, GOOD => good);
        if not good then
          next;
        end if;
        case cmd is
          when '#' =>
            report "[TB:Wavegen_Proc] "&L.all;
          when 'W' =>
            read(L, duration, good);
            if not good then
              report "[TB:Wavegen_Proc] Invalid time 'W' command";
            else
              wait for duration;
            end if;
          -- report cmd&": Waiting done";
          when 'M' =>
            wait until s_send_msg_o = '1';
          when 'N' =>
            read(L, bits, good);
            if not good then
              report "[TB:Wavegen_Proc] Invalid #bits after 'N' command" severity error;
            else
              wait for bits*c_bit_time;
            end if;
          when 'C' =>
            read(L, bits, good);
            if not good then
              report "[TB:Wavegen_Proc] Invalid #cycles after 'C' command" severity error;
            else
              l_wait_clock : for j in 1 to bits loop
                wait until s_clk_i = '1';
              end loop;
            -- report cmd&": Waiting done";
            end if;
          when 'T' =>
            s_trigger_ext_i <= not(c_trigger_ext_active);
            report cmd&": Triggering";
            read(L, bits, good);
            if not good then
              bits := 1;
              report "[TB:Wavegen_Proc] Invalid #cycles after 'T' command" severity error;
            end if;
            l_wait_ext_trigger : for j in 1 to bits loop
              wait until s_clk_i = '1';
            end loop;
            report cmd&": Triggering done";
            s_trigger_ext_i <= c_trigger_ext_active;
          when 'I' =>
            s_trigger_dut_i <= not(c_trigger_dut_active);
            -- report cmd&": Triggering";
            read(L, bits, good);
            if not good then
              bits := 1;
              report "[TB:Wavegen_Proc] Invalid #cycles after 'I' command" severity error;
            end if;
            l_wait_int_trigger : for j in 1 to bits loop
              wait until s_clk_i = '1';
            end loop;
            -- report cmd&": Triggering done";
            s_trigger_dut_i <= c_trigger_dut_active;
          when others =>
            null;
        end case;
        next;
      end if;
      wait for c_inter_byte_time;
      s_uart_error_i <= '0';
      l_write_byte : for i in 0 to 7 loop
        wait for c_bit_time;
        s_data_i       <= byte(i);
        s_data_valid_i <= '1';
        if i = 0 then
          s_byte_start_i <= '1';
        end if;
        wait until s_clk_i = '1';
        s_data_valid_i <= '0';
        s_byte_start_i <= '0';
        wait until s_clk_i = '1';
      end loop;
      s_data_i       <= '0';
      s_uart_error_i <= byte(8);
    end loop;
    wait;
  end process WaveGen_Proc;

  Message_Proc : process
    variable v_msg_type : string (1 to 10);
  begin
    wait until s_clk_i'event and s_clk_i = '1' and s_send_msg_o = '1';
    case s_msg_data_o(c_msg_bit_type1 downto c_msg_bit_type0) is
      when c_msg_type_conf_done =>
        v_msg_type := "CONF_DONE ";
      when c_msg_type_underrun =>
        v_msg_type := "UNDERRUN  ";
      when c_msg_type_ready =>
        v_msg_type := "READY     ";
      when others =>
        report "[TB:Message_Proc] Illegal message type received" severity failure;
        v_msg_type := "**ILLEGAL*";
    end case;
    report "[TB:Message_Proc] "&v_msg_type&" message received " & lf &
      "                  UART ERROR : "&std_logic'image(s_msg_data_o(c_msg_bit_uart))& lf &
      "                  ID   ERROR : "&std_logic'image(s_msg_data_o(c_msg_bit_id))& lf &
      "                  CRC  ERROR : "&std_logic'image(s_msg_data_o(c_msg_bit_crc));
  end process Message_Proc;



-- waveform generation
  p_check_lfsr : process
    file f_data_in : text open read_mode is g_lfsr_file_name;
    variable L     : line;
    variable data  : std_logic_vector(c_lfsr_width-1 downto 0);
    variable good  : boolean;
  begin
    wait until s_lfsr_o = c_lfsr_seed;
    wait until rising_edge(s_clk_i);
    -- insert signal assignments here
    l_read_lfsr_file : while not endfile(f_data_in) loop
      readline(f_data_in, L);
      read(L, data, GOOD => good);
      if not good then
        next;
      end if;
      assert (data = s_lfsr_o) report "LFSR mismatch" severity failure;
      wait until rising_edge(s_clk_i);
    end loop;
    assert (s_lfsr_o = c_lfsr_seed) report "LFSR cycle did not wrap" severity failure;
    wait;
  end process p_check_lfsr;


end architecture sim;

-------------------------------------------------------------------------------

configuration fault_injection_controller_tb_sim_cfg of fault_injection_controller_tb is
  for sim
  end for;
end fault_injection_controller_tb_sim_cfg;

-------------------------------------------------------------------------------