OpenCores
URL https://opencores.org/ocsvn/vhld_tb/vhld_tb/trunk

Subversion Repositories vhld_tb

[/] [vhld_tb/] [trunk/] [examples/] [tb_code_snips.vhd] - Blame information for rev 19

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 sckoarn
-------------------------------------------------------------------------------
2
--             Copyright 2011 Ken Campbell
3
--                        All Rights Reserved
4
-------------------------------------------------------------------------------
5
-- $Author: ken $
6
--
7
-- $date:  $
8
--
9
-- $Id:  $
10
--
11
-- $Source:  $
12
--
13
-- Description :
14
--          Code snipets from / for various VHDL Test Bench Facilities.
15
--
16
--   Contents:
17
--     Section 1:  Code from Usage Tips: Interrupts and Waiting.
18
--     Section 2:  Code from CPU emulation: some starter commands
19
--     Section 3:  Code for internal test bench implementation
20
--     Section 4:  Code for Verify commands
21
--            
22
------------------------------------------------------------------------------
23
--
24
-------------------------------------------------------------------------------
25
-------------------------------------------------------------------------------------
26
--###################################################################################
27
--  Section 1:  Interrupts and Waiting.
28
architecture bhv of tb_xxx is
29
--  ...
30
constant MAX_TIME : integer  :=  60000;
31
--  ...
32
 
33
Read_file : process
34
--  ...
35
    define_instruction(inst_list, "WAIT_IRQ", 0);
36
--  ...
37
--------------------------------------------------
38
     elsif (instruction(1 to len) = "WAIT_IRQ") then
39
        temp_int := 0;                               -- initialize counter
40
        while(dut_irq /= '1') then              -- while IRQ not asserted
41
           wait for clk'event and clk = '1';  -- wait for clock cycle
42
            temp_int := temp_int + 1;         --  add one to clock counter
43
            assert (temp_int /= MAX_TIME)  -- if count = max time  quit.
44
              report "Error:  Time out while waiting for IRQ!!"
45
            severity failure;
46
        end loop;
47
 
48
-------------------------------------------------------------------------------------------
49
    define_instruction(inst_list, "MAX_WAIT_SET", 1);
50
--  ...
51
--------------------------------------------------------
52
     elsif (instruction(1 to len) = "MAX_WAIT_SET") then
53
        MAX_TIME  <= par1;                               -- set the max
54
        wait for 0 ps;
55
 
56
architecture bhv of tb_xxx is
57
--  ...
58
  signal irq_expect :  boolean := false;
59
--  ...
60
Read_file : process
61
--  ...
62
    define_instruction(inst_list, "EXPECT_IRQ", 1);
63
--  ...
64
--------------------------------------------------------------------------------
65
     elsif (instruction(1 to len) = "EXPECT_IRQ") then
66
       if(par1 = 0) then
67
         irq_expect <= false;
68
       else
69
         irq_expect <= true;
70
       end if;
71
        wait for 0 ps;
72
--  ...
73
  end process Read_file;
74
 
75
------------------------
76
irq_mon:
77
  process(clk, dut_irq)
78
  begin
79
    -- on the falling edge, assume rising edge assertion, one clock wide
80
    if(clk'event and clk = '0') then
81
      if(dut_irq = '1') then
82
        if(irq_expect = true) then
83
            assert (false)
84
              report "NOTE:  An expected IRQ occurred."
85
            severity note;
86
        else
87
            assert (false)
88
              report "ERROR:  An unexpected IRQ occurred."
89
            severity failure;
90
        end if;
91
      end if;
92
    end if;
93
end process irq_mon;
94
--  END  Section 1:
95
--###################################################################################
96
 
97
 
98
-------------------------------------------------------------------------------------
99
--###################################################################################
100
--  Section 2:  CPU Emulation Commands
101
-- starting from the top of the bhv architecture
102
architecture bhv of xxx_tb is
103
  -- create type for cpu array of registers
104
  --  Type needed for CPU registers, it can be resized if needed
105
  type cpu_reg_array is array(0 to 7) of std_logic_vector(31 downto 0);
106
  -- optional constant to help test for zero
107
  constant zeros   : std_logic_vector(31 downto 0) := (others => '0');
108
--  ...
109
--  ...
110
  --------------------------------------------------------------------------
111
  Read_file: process
112
--  ...  variable definitions
113
  -------------------
114
  --  CCR def
115
  --   bit 0   zero, will be set when results are zero
116
  --   bit 1   equal, will be set when compared values are equal
117
  --   bit 2   greater than, will be set when source1 is > source2
118
  --   bit 3   less than, will be set when source1 is < source2
119
  --   others undefined
120
    variable v_reg_ccr    : std_logic_vector(7 downto 0);  -- condition code register
121
    variable v_regs       : cpu_reg_array;                 -- Create variable of cpu regs
122
    variable v_tmp_bit    : std_logic;                     -- nice place to store a bit temp
123
    variable v_read_data  : std_logic_vector(31 downto 0);
124
--  ...
125
  begin  -- process Read_file
126
--  ...
127
    define_instruction(inst_list, "READ_TO_REG", 2);
128
    define_instruction(inst_list, "REG_TO_VAR", 2);
129
    define_instruction(inst_list, "MOV", 2);
130
    define_instruction(inst_list, "MOVI", 2);
131
    define_instruction(inst_list, "AND", 3);
132
    define_instruction(inst_list, "ANDI", 3);
133
    define_instruction(inst_list, "OR", 3);
134
    define_instruction(inst_list, "NOT", 2);
135
    define_instruction(inst_list, "XOR", 3);
136
    define_instruction(inst_list, "SLL", 2);
137
    define_instruction(inst_list, "SLR", 2);
138
    define_instruction(inst_list, "CMP", 2);
139
    define_instruction(inst_list, "BE", 1);
140
    define_instruction(inst_list, "BZ", 1);
141
    define_instruction(inst_list, "BB", 4);
142
 
143
    ------------------------------------------------------------------------
144
    -- Read, test, and load the stimulus file
145
    read_instruction_file(stimulus_file, inst_list, defined_vars, inst_sequ,
146
                          file_list);
147
    -- initialize last info
148
    last_sequ_num  := 0;
149
    last_sequ_ptr  := inst_sequ;
150
    -- initialize  registers  -- this is the zering of the registers and CCR
151
    v_regs           := (others => (others => '0'));
152
    v_reg_ccr        := (others => '0');
153
--  ...
154
--------------------------------------------------------------------------
155
-- READ_TO_REG
156
--   Read a addressed location to the local register array
157
--     par1   address
158
--     par2   target reg (index)
159
    elsif(instruction(1 to len) = "READ_TO_REG") then
160
      v_temp_vec1     :=  std_logic_vector(conv_unsigned(par1, 32));
161
      STM_ADD   <=  v_temp_vec1;
162
      STM_DAT   <=  (others => 'Z');
163
      STM_RWN   <=  '1';
164
      wait for 1 ps;
165
      STM_REQ_N  <=  '0';
166
      wait until STM_ACK_N'event and STM_ACK_N = '0';
167
      STM_REQ_N  <=  '1';
168
      STM_ADD   <=  (others => 'Z');
169
      v_read_data  :=  STM_DAT;
170
      v_regs(par2)   :=  STM_DAT;
171
      STM_RWN   <=  '1';
172
      wait for 1 ps;
173
 
174
--------------------------------------------------------------------------
175
-- REG_TO_VAR
176
--  Write a register array value to a Variable.
177
--     par1   target reg (index)
178
--     par2   Variable to update with value from target reg
179
    elsif(instruction(1 to len) = "REG_TO_VAR") then
180
      temp_int  :=  to_uninteger(v_regs(par1));            --<< NEW to_uninteger conversion function
181
      update_variable(defined_vars, par2, temp_int, valid);
182
-- the to_uninteger function was added because to add the function through
183
--   std_developerskit overflowed my PE student simulator.  I am tired of
184
--   conversion and created my own function, tb_pkg contained.  see additional
185
--   code at the bottom of this section.  You can replace this with functions
186
--   you usually use, or use std_developerskit if you are on real tools.
187
--------------------------------------------------------------------------
188
-- MOV
189
--   Move one register contents to another register.  Source contents maintained
190
--     par1   reg1 index
191
--     par2   reg2 index
192
    elsif(instruction(1 to len) = "MOV") then
193
      v_regs(par2)  :=  v_regs(par1);
194
 
195
--------------------------------------------------------------------------
196
-- MOVI
197
--   Move value passed to destination register
198
--     par1   value
199
--     par2   reg index
200
    elsif(instruction(1 to len) = "MOVI") then
201
      v_regs(par2)  :=  std_logic_vector(conv_unsigned(par1, 32));
202
 
203
--------------------------------------------------------------------------
204
-- AND
205
--   AND two registers and write results to target register
206
--     par1   reg1 index
207
--     par2   reg2 index
208
--     par3   target results reg index
209
    elsif(instruction(1 to len) = "AND") then
210
      v_regs(par3)  :=  v_regs(par1) and v_regs(par2);
211
      if(v_regs(par3) = zeros) then
212
        v_reg_ccr(0) := '1';
213
      else
214
        v_reg_ccr(0) := '0';
215
      end if;
216
 
217
--------------------------------------------------------------------------
218
-- ANDI
219
--   AND the passed value with the indexed register and store in register index
220
--     par1   value
221
--     par2   reg index
222
--     par3   target results reg index
223
    elsif(instruction(1 to len) = "ANDI") then
224
      v_regs(par3)  :=  std_logic_vector(conv_unsigned(par1, 32)) and v_regs(par2);
225
      if(v_regs(par3) = zeros) then
226
        v_reg_ccr(0) := '1';
227
      else
228
        v_reg_ccr(0) := '0';
229
      end if;
230
 
231
--------------------------------------------------------------------------
232
-- OR
233
--   OR two registers and write results to target register
234
--     par1   reg1 index
235
--     par2   reg2 index
236
--     par3   target results reg index
237
    elsif(instruction(1 to len) = "OR") then
238
      v_regs(par3)  :=  v_regs(par1) or v_regs(par2);
239
      if(v_regs(par3) = zeros) then
240
        v_reg_ccr(0) := '1';
241
      else
242
        v_reg_ccr(0) := '0';
243
      end if;
244
 
245
--------------------------------------------------------------------------
246
-- XOR
247
--   XOR two registers and write results to target register
248
--     par1   reg1 index
249
--     par2   reg2 index
250
--     par3   target results reg index
251
    elsif(instruction(1 to len) = "XOR") then
252
      v_regs(par3)  :=  v_regs(par1) xor v_regs(par2);
253
      if(v_regs(par3) = zeros) then
254
        v_reg_ccr(0) := '1';
255
      else
256
        v_reg_ccr(0) := '0';
257
      end if;
258
 
259
--------------------------------------------------------------------------
260
-- NOT
261
--   NOT a register and write results to target register
262
--     par1   reg1 index
263
--     par2   target results reg index
264
    elsif(instruction(1 to len) = "NOT") then
265
      v_regs(par2)  :=  not v_regs(par1);
266
      if(v_regs(par2) = zeros) then
267
        v_reg_ccr(0) := '1';
268
      else
269
        v_reg_ccr(0) := '0';
270
      end if;
271
 
272
--------------------------------------------------------------------------
273
-- SLL
274
--   Shift the register left rotate the upper bits into the lower bits
275
--     par1   reg1 index
276
--     par2   bit positions to Left
277
    elsif(instruction(1 to len) = "SLL") then
278
      v_temp_vec1  :=  v_regs(par1);
279
      temp_int  := par2 - 1;
280
      v_regs(par1) :=  v_temp_vec1(31-par2 downto 0) & v_temp_vec1(31 downto 31 - temp_int);
281
 
282
--------------------------------------------------------------------------
283
-- SLR
284
--   Shift the register right rotate the lower bits into the upper bits
285
--     par1   reg1 index
286
--     par2   bit positions to Right
287
    elsif(instruction(1 to len) = "SLR") then
288
      v_temp_vec1  :=  v_regs(par1);
289
      temp_int  := par2 - 1;
290
      v_regs(par1) :=  v_temp_vec1(temp_int downto 0) & v_temp_vec1(31 downto par2);
291
 
292
--------------------------------------------------------------------------
293
-- CMP
294
--   Compare one register against another and set CCR bits, no effect on registers
295
--     par1   reg1 index source1
296
--     par2   reg2 index source2
297
    elsif(instruction(1 to len) = "CMP") then
298
      v_reg_ccr  :=  (others => '0');
299
      if(v_regs(par1) = v_regs(par2)) then
300
        v_reg_ccr(1)  :=  '1';
301
      elsif(v_regs(par1) > v_regs(par2)) then
302
        v_reg_ccr(2)  :=  '1';
303
      elsif(v_regs(par1) < v_regs(par2)) then
304
        v_reg_ccr(3)  :=  '1';
305
      end if;
306
 
307
      if(v_regs(par1) = zeros) then
308
        v_reg_ccr(1)  :=  '0';
309
      end if;
310
 
311
--------------------------------------------------------------------------
312
-- BE
313
--   Branch if equal
314
--     par1   jump location
315
    elsif(instruction(1 to len) = "BE") then
316
      if(v_reg_ccr(1) = '1') then
317
        v_line    :=  par1 - 1;
318
        wh_state  :=  false;
319
        wh_stack  := (others => 0);
320
        wh_dpth   := 0;
321
        wh_ptr    := 0;
322
        --stack     := (others => 0);
323
        --stack_ptr := 0;
324
      end if;
325
 
326
--------------------------------------------------------------------------
327
-- BZ
328
--   Branch if Zero
329
--     par1   jump location
330
    elsif(instruction(1 to len) = "BZ") then
331
      if(v_reg_ccr(0) = '1') then
332
        v_line    :=  par1 - 1;
333
        wh_state  :=  false;
334
        wh_stack  := (others => 0);
335
        wh_dpth   := 0;
336
        wh_ptr    := 0;
337
        --stack     := (others => 0);
338
        --stack_ptr := 0;
339
      end if;
340
 
341
--------------------------------------------------------------------------
342
-- BB
343
--   Branch if bit in register is set/clear
344
--     par1   register
345
--     par2   register bit index
346
--     par3   compare value : 0/1
347
--     par4   jump location
348
    elsif(instruction(1 to len) = "BB") then
349
      v_temp_vec1  :=  v_regs(par1);
350
      if(par3 = 0) then
351
        v_tmp_bit  := '0';
352
      else
353
        v_tmp_bit  := '1';
354
      end if;
355
      if(v_temp_vec1(par2) = v_tmp_bit) then
356
        v_line    :=  par4 - 1;
357
        wh_state  :=  false;
358
        wh_stack  := (others => 0);
359
        wh_dpth   := 0;
360
        wh_ptr    := 0;
361
        --stack     := (others => 0);
362
        --stack_ptr := 0;
363
      end if;
364
--  ...
365
  end process Read_file;
366
end bhv;
367
--  Stimulus_file commands used for testing.  I used no VERIFY command
368
--    as I watched the functionality in single stepping through code.
369
DEFINE_VAR dat x01
370
EQU_VAR dat x12345678
371
MASTR_WRITE 3 $dat
372
READ_TO_REG 3 0
373
OR 0 1 2
374
AND 0 2 1
375
MOV 1 3
376
XOR 0 1 4
377
NOT 4 5
378
SLL 0 1
379
SLL 1 2
380
SLL 2 3
381
SLL 3 4
382
SLR 0 1
383
SLR 1 2
384
SLR 2 3
385
SLR 3 4
386
MOVI x87654321 7
387
 
388
ANDI 0 0 0
389
BZ $B1
390
MOVI x1234678 0
391
 
392
B1:
393
CMP 1 2
394
BE $B2
395
MOVI 0 1
396
 
397
B2:
398
BB 0 0 1 $B3
399
BB 0 0 0 $B3  "Didnt jup as expected
400
MOVI 0 1
401
 
402
B3:
403
 
404
FINISH
405
 
406
--------------------------------------------------------------------------------
407
-- tb_pkg function
408
---   header section
409
-------------------------------------------------------------------------
410
--  convert a std_logic_vector to an unsigned integer
411
    function to_uninteger  ( constant vect     : in std_logic_vector
412
                         ) return integer;
413
--  body section
414
---------------------------------------------------------------------------------------
415
  function to_uninteger ( constant vect     : in std_logic_vector
416
                        ) return integer is
417
    variable result   : integer := 0;
418
    variable len      : integer := vect'length;
419
    variable idx      : integer;
420
    variable tmp_str  : text_field;
421
    variable file_name: text_line;
422
  begin
423
    -- point to start of string
424
    idx  :=  1;
425
    -- convert std_logic_vector to text_field
426
    for i in len - 1 downto 0 loop
427
      if(vect(i) = '1') then
428
        tmp_str(idx) := '1';
429
      elsif(vect(i) = '0') then
430
        tmp_str(idx) := '0';
431
      else
432
        assert(false)
433
          report LF & "ERROR:  Non 0/1 value found in std_logic_vector passed to to_uninteger function!!" & LF &
434
                "Returning 0."
435
        severity note;
436
        return result;
437
      end if;
438
      idx := idx + 1;
439
    end loop;
440
    -- call bin txt to int fuction with dummy fn and sequ idx
441
    result := bin2integer(tmp_str, file_name, idx);
442
    return result;
443
 
444
  end to_uninteger;
445
 
446
 
447
 
448
--  Section 2:  END
449
--###################################################################################
450
 
451
--
452
--###################################################################################
453
-- Section 3: Begin
454
--   This section presents the code needed to make an internal test bench
455
--     an optional compile item through the use of VHDL generics and generate
456
--     statements.
457
 
458
-- this is the top enity or at the level where you can assign the
459
--    en_bfm generic and it makes sense
460
entity my_top_dut is
461
  generic (
462
           g_en_bfm  :  integer :=  0
463
          );
464
  port (
465
     --  top port definitions
466
       );
467
end enity my_top_dut;
468
 
469
 
470
architecture struct of my_top_dut is
471
-- this is the component of an internal block of my_top_dut
472
component rtl_block
473
  port (
474
        reset_n  : in      std_logic;
475
        clk_in   : in      std_logic;
476
        -- ...
477
       );
478
end component;
479
-- bhv_block has the same pin out as rtl_block, except for the generic
480
component bhv_block
481
  generic (
482
           stimulus_file: in string
483
          );
484
  port (
485
        reset_n  : in      std_logic;
486
        clk_in   : in      std_logic;
487
        -- ...
488
       );
489
end component;
490
--....
491
begin
492
  -- if generic is default value, include rtl
493
  if(g_en_bfm = 0) generate
494
  begin
495
    rtl_b1: rtl_block
496
      port map(
497
            reset_n  =>  reset_n,
498
            clk_in   =>  clk,
499
            -- ...
500
           );
501
  end generate;
502
  -- if generic is set for bhv, include it
503
  if(g_en_bfm = 1) generate
504
  begin
505
    bfm: bhv_block
506
      generic map(
507
                  stimulus_file => "stm/stimulus_file.stm"
508
                 )
509
      port map(
510
            reset_n  =>  reset_n,
511
            clk_in   =>  clk,
512
            -- ...
513
           );
514
  end generate;
515
-- ...
516
end struct;
517
 
518
--  Section 3 End:
519
--###################################################################
520
 
521
--####################################################################
522
--  Section 4 Start:
523
--    This section provides some example VERIFY commands.
524
  --------------------------------------------------------------------------
525
  Read_file: process
526
  --  ...
527
    variable v_tmp_bit    : std_logic;
528
    variable v_upb        : integer := 31;  -- upper bounds
529
    variable v_lob        : integer := 0;  -- lower bounds
530
    variable v_temp_read  : std_logic_vector(31 downto 0);
531
  --  ...
532
    define_instruction(inst_list, "SLICE_SET", 2);
533
    define_instruction(inst_list, "VERIFY", 1);
534
    define_instruction(inst_list, "VERIFY_BIT", 2);
535
    define_instruction(inst_list, "VERIFY_SLICE", 1);
536
  --  ...
537
 
538
 
539
-----------------------------------------------------------------------------
540
--  SLICE_SET     set the slice of the data for testing
541
--     par1       upper bound value  -  must be larger than par2 and less than 32
542
--     par2       lower bound value
543
   elsif (instruction(1 to len) = "SLICE_SET") then
544
     -- test user input.
545
     assert (par1 < 32 and par1 >= 1)
546
       report LF & "ERROR:  Par1 in SLICE_SET command input range is out of bounds" & LF &
547
        "Found on line " & (integer'image(file_line)) & " in file " & file_name
548
     severity failure;
549
     assert (par2 < 31 and par2 >= 0)
550
       report LF & "ERROR:  Par2 in SLICE_SET command input range is out of bounds" & LF &
551
        "Found on line " & (integer'image(file_line)) & " in file " & file_name
552
     severity failure;
553
     assert (par1 > par2)
554
       report LF & "ERROR: SLICE_SET command bounds incorrectly defined. Par1 must be greater than Par2." & LF &
555
        "Found on line " & (integer'image(file_line)) & " in file " & file_name
556
     severity failure;
557
     -- update variables
558
     v_upb  :=  par1;
559
     v_lob  :=  par2;
560
 
561
-----------------------------------------------------------------------------
562
--  VERIFY    test that the data in temp_read is the passed value.
563
--      par1  value to test against.
564
   elsif (instruction(1 to len) = "VERIFY") then
565
     v_temp_vec1     :=  std_logic_vector(conv_unsigned(par1, 32));
566
 
567
     assert (v_temp_vec1 = v_temp_read)
568
       report LF & "ERROR: VERIFY command compare value was not as expected!!" &
569
         LF & "Got " & (to_hstring(v_temp_read)) &
570
         LF & "Expected " & (to_hstring(v_temp_vec1)) & LF &
571
        "Found on line " & (integer'image(file_line)) & " in file " & file_name
572
      severity failure;
573
 
574
-----------------------------------------------------------------------------
575
--  VERIFY_BIT    test that the data bit in temp_read is the passed value.
576
--      par1  index into 32 bit temp_read
577
--      par2  bit value
578
   elsif (instruction(1 to len) = "VERIFY_BIT") then
579
     assert (par1 >= 0 and par1 < 32)
580
       report LF & "ERROR: VERIFY_BIT command bit index is out of range. Valid is 0 - 31." & LF &
581
        "Found on line " & (integer'image(file_line)) & " in file " & file_name
582
     severity failure;
583
     if(par2 = 0) then
584
         v_tmp_bit := '0';
585
     else
586
         v_tmp_bit := '1';
587
     end if;
588
     assert (v_temp_read(par1) = v_tmp_bit)
589
       report LF & "ERROR: VERIFY_BIT command miss-compare!" & LF &
590
        "We tested for " & (integer'image(par2)) & LF &
591
        "Found on line " & (integer'image(file_line)) & " in file " & file_name
592
     severity failure;
593
 
594
-----------------------------------------------------------------------------
595
--  VERIFY_SLICE    test that the data in temp_read is the passed value.
596
--      par1   value
597
   elsif (instruction(1 to len) = "VERIFY_SLICE") then
598
     v_temp_vec1  :=  (others => '0');
599
     temp_int   :=  v_upb - v_lob + 1;
600
     v_temp_vec1(v_upb downto v_lob)     :=  std_logic_vector(conv_unsigned(par1, temp_int));
601
     -- no need to test ranges here
602
     assert (v_temp_vec1(v_upb downto v_lob) = v_temp_read(v_upb downto v_lob))
603
       report LF & "ERROR: VERIFY_SLICE Compare Value was not as expected!!" &
604
         LF & "Got " & (to_hstring(v_temp_read(v_upb downto v_lob))) &
605
         LF & "Expected " & (to_hstring(v_temp_vec1(v_upb downto v_lob))) & LF &
606
        "Found on line " & (integer'image(file_line)) & " in file " & file_name
607
      severity failure;
608
 
609
--  END Section 4
610
--#######################################################################################

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.