Chapter 5
Verilog Test Fixtures

SRAM-based FPGA designers don’t simulate their designs enough. It is easy to burn a part and try it, so that is our tendency. We can argue some advantage to this method; after all, the end result is a part that works, right? Still, any tool that improves the quality of our design must be used. ASIC designers and designers using antifuse technology don’t have the luxury (or crutch, depending on your point of view) of trying a part that is not virtually guaranteed to work. Instead of downloading a configuration file, these designers either program an expensive antifuse device (which is thrown away if it doesn’t work) or go through a full ASIC fabrication turn (which can cost tens and hundreds of thousands of dollars). This is why ASICs (and ASIClike devices) have long simulation processes that drive management nuts. The designers are fooling around with their computers all day instead of delivering product!

Verilog was designed as a simulation and test language. It has excellent features and has been thoroughly thought out and developed. Except for the cost of the simulator software and the danger of falling into the endless ‘paralysis of analysis’ loop, there is no reason the FPGA designer shouldn’t regularly use a simulator. There are some excellent books that cover Verilog simulation in detail (see the bibliography at the end of this book); we’ll just do a quick and dirty overview in this chapter.

Most simulators have a waveform viewer, and a lot of effort is put into making this viewer attractive to the eye. The problem is that a human brain is required to analyze and interpret the waveforms. Waveforms are great and we’ve used them throughout this text to show input and output signals. However, Verilog supports automated testing. This is a great way to test and validate a design and later design changes. You can make a design change and carefully evaluate the effect on the area of interest, but how do you know you didn’t break something in another part of the design that used to work?

This doesn’t mean the automated test fixtures are a panacea. They are often a pain in the rear. You’ll spend a lot of time revising the test fixture to ‘fix’ tests where signals that don’t matter were improperly or too strictly tested.

COMPILER DIRECTIVES

Many powerful compiler directives are available in Verilog. Note the use of the ` (back tick or accent grave) as part of these compiler directives.

`define, `ifdef, `else, `endif, `undef Verilog supports conditional compilation and execution. Code may support simulation and not be synthesizable, or may be conditionally synthesized to support optional features. A macro variable can be defined to control compilation and might have a form like that shown in Listing 5-1

Listing 5-1 `ifdef Example

// Conditional Compilation Example.
// Comment out the next line for synthesis.
define test_mode;      // Define test_mode macro.

‘ifdef test_mode
// Insert test_mode code here. Could be a test module

//  definition or simulation directives, not just inline//  code.

     data_bus      <=     test_points;

‘else 
// Insert non-test_mode code here.
// The ‘else portion is optional.
    data_bus      <=     internal_data;

‘endif
// Continue with unconditional code here.

A macro definition can be ‘undefined’ by an `undef occurring later in the code.

`include filename The directive is similar to the C language #include directive. The file pointed to by filename (which may be a file in the current path or a full path description) will be inserted in the Verilog code during compile time. Includes can be nested; in other words an included file may also have an included file.

`timescale unit/precision The time unit used by the simulator is programmable. For example, in the code of Listing 5-3, there is a line that reads:

#75 reset = 0;

The number 75 represents a delay in units of the timescale unit, in this case 75 nsec. The delay tells the simulator to wait until simulation time has advanced by the delay value before executing the next directive.

There is no magic hardware construct that will create a delay for you. The default, if no timescale directive is executed, is 1 nsec. The precision determines how delay values are rounded off and determine the simulation resolution. The precision must be equal to or less than the timescale unit. The timescale argument units are in s (seconds), ms (milliseconds), us (microseconds), ns (nanoseconds), ps (picoseconds), or fs (femtoseconds). Mostly, you’ll see 1 ns / 1 ns, for delay units of 1 nsec with rounding of delay values to the nearest nsec. There can only be one timescale in a design.

System Tasks

Verilog system tasks start with a $.

$finish; When encountered in the code, $finish ends the simulation. Without some termination point, the simulation will continue forever (or until your PC runs out of memory and crashes). $finish returns control of the computer back to the operating system.

$stop; This system task halts simulation but does not return control to the operating system. Simulation can be continued from the stopping point, or other system commands can be executed at the current simulation time.

$display(list element 1, list element 2); This system task is similar to C’s printf command. Verilog runs just fine in a nonwaveform output mode. If there are no waveforms, how can we tell what our design is doing? Stick some $display commands in your design to view variables and other information (such as simulation time) as illustrated in Listings 5-2 and 5-3.

Listing 5-2 Simple $display Example

module display1 (clock, reset); 
input              clock, reset; 
reg         [7:0]  count_val; 
always @ (posedge clock or posedge reset)
     if (reset) 
     count_val     <=     0; 
     else    begin 
     count_val     <=     count_val + 1; 
     $display (count_val); 
     end 
endmodule 

Listing 5-3 Simple $display Example Test Fixture

// Dis    play Test.
module dis    p1_tf;
`timescale      1ns / 1ns
reg clock, reset;
parameter      clk_period     =       20;
display1 u1 (clock, reset);
always         begin
     #(clk_period / 2) clock = ~clock;
     end
initial begin
     clock          =       0;
     reset           =       1; // Assert the system reset.
     #75 reset        =      0;

    #1000 $finish;
end
endmodule

Listing 5-4 shows the result of a Silos III simulation run. The first few zeros are the count_val register content during the reset period. The $display defaults to a decimal number format and includes a carriage return (newline) after each execution. If the newline is not desired, the $write system task can be used instead.

Listing 5-4 Simple $display Example Output Listing

                   S I L O S  I I I    Version 99.100       
               DEMO COPY LIMITED TO 100 to 200 DEVICES 
           Copyright (c) 1999 by SIMUCAD Inc. All rights reserved. 
           No part of this program may be reproduced, transmitted, 
       transcribed, or stored in a retrieval system, in any 
       form or by any means without the prior written consent of
         SIMUCAD Inc., 32970 Alvarado-Niles Road, Union City,
                     California, 94587, U.S.A.                   
                (510)-487-9700  Fax: (510)-487-9721              
          Electronic Mail Address:   Ü[email protected]Ü    
 
!file .sav=Üdisplay1Ü 
!control .sav=3 
!control .savcell=0 
!control .disk=1000M 
 
Reading Üc:verilogsourcecodedisp1_tf.vÜ 
Reading Üc:verilogsourcecodedisplay1.vÜ 
sim to 0 
     Highest level modules (that have been auto-instantiated): 
            (disp1_tf disp1_tf 
     3 total devices. 
     Linking … 
 
     3 nets total: 11 saved and 0 monitored. 
     74 registers total: 74 saved. 
     Done.                  
 
     0 State changes on observable nets. 
 
     Simulation stopped at the end of time 0.000000000s. 
Ready: sim  
  0 
  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 
   313 State changes on observable nets in 0.33 seconds. 
   948 Events/second. 

   Simulation stopped at the end of time 0.000001075s.
Ready:  

Text and numbers can be formatted with escape string. An escape string is a string following a backslash () or %. Here are a few examples:

%h

Display numbers in hex format

%d

Display numbers in decimal (the default) format

%o

Display numbers in octal format

%b

Display numbers in binary format

%c

Display numbers as ASCII characters

%t

Display in current time format

“string”

Display text string

newline

tab

literal

Literal could be another (to print a ‘’), a “(quote), or % (print %).

To get some experience with this formatting, take a look at Listings 5-5, 5-6, and 5-7.

Listing 5-5 Simple $display Example Output Listing with Formatting

// Display Test with formatting. 
module time_setup; 
initial 
      begin 
// This timeformat is nsec (-9), 2 digits after decimal 
//  place (2), ns text, and a minimum of 3 spaces for 
//  time to be displayed in. 
      $timeformat (-9, 2, Ü nsÜ, 3); 
      end 
endmodule 
 
module disp2_tf; 
timescale 1ns / 1ns 
reg           clock, reset; 
parameter  clk_period      =          20; 
 
display2 u1 (clock, reset); 
always begin 
      #(clk_period / 2) clock = ~clock; 
      end 
 
initial 
begin 
      clock                   =       0; 
      reset                   =       1; // Assert the system reset.
      #75 reset               =       0; 
      #1000 $finish; 
end 
endmodule 

Listing 5-6 Simple $display Example Output Listing with Formatting

module display2 (clock, reset); 
input                 clock, reset; 
reg           [7:0]  count_val; 
// Comment out the next line for terse printout. 
‘define verbose 
always @ (posedge clock or posedge          reset) 
begin 
      if (reset)      count_val        <=     0; 
      else    begin 
                      count_val        <=     count_val + 1;
      ‘ifdef verbose 
      $write        (Ücount_val = %hÜ, count_val); 
      $display (Ü Current time = %tÜ, $time); 
      ‘else 
      $write (Ü:Ü, count_val); 
      ‘endif 
      end 
end 
endmodule 

Listing 5-7 Simple $display Example Output Listing with Formatting

                  S I L O S  I I I    Version 99.100       
               DEMO COPY LIMITED TO 100 to 200 DEVICES 
           Copyright (c) 1999 by SIMUCAD Inc. All rights reserved. 
           No part of this program may be reproduced, transmitted, 
       transcribed,       or stored in a retrieval system, in any 
       form or by any means without the prior written consent of
         SIMUCAD Inc., 32970 Alvarado-Niles Road, Union City,    
                     California, 94587, U.S.A.                   
                (510)-487-9700  Fax: (510)-487-9721              
          Electronic Mail Address:   Ü[email protected]Ü    
 
!file .sav=Üdisplay2Ü 
!control .sav=3 
!control .savcell=0 
!control .disk=1000M 
 
Reading Üc:verilogsourcecode ime_setup.vÜ 
Reading Üc:verilogsourcecodedisplay2.vÜ 
sim to 0 
        Highest level modules (that have been auto-instantiated): 
            (time_setup time_setup 
            (disp2_tf disp2_tf 

    4 total devices. 
    Linking … 
    3 nets total: 11 saved and 0 monitored. 
    74 registers total: 74 saved. 
    Done.                  
 
    0 State changes on observable nets. 
    Simulation stopped at the end of time 0.000000000s.
Ready: sim  
count_val = 00 Current time = 90.00 ns 
count_val = 01 Current time = 110.00 ns 
count_val = 02 Current time = 130.00 ns 
count_val = 03 Current time = 150.00 ns 
count_val = 04 Current time = 170.00 ns 
count_val = 05 Current time = 190.00 ns 
count_val = 06 Current time = 210.00 ns 
count_val = 07 Current time = 230.00 ns 
count_val = 08 Current time = 250.00 ns 
count_val = 09 Current time = 270.00 ns 
count_val = 0a Current time = 290.00 ns 
count_val = 0b Current time = 310.00 ns 
count_val = 0c Current time = 330.00 ns 
count_val = 0d Current time = 350.00 ns 
count_val = 0e Current time = 370.00 ns 
count_val = 0f Current time = 390.00 ns 
count_val = 10 Current time = 410.00 ns 
count_val = 11 Current time = 430.00 ns 
count_val = 12 Current time = 450.00 ns 
count_val = 13 Current time = 470.00 ns 
count_val = 14 Current time = 490.00 ns 
count_val = 15 Current time = 510.00 ns 
count_val = 16 Current time = 530.00 ns 
count_val = 17 Current time = 550.00 ns 
count_val = 18 Current time = 570.00 ns 
count_val = 19 Current time = 590.00 ns 
count_val = 1a Current time = 610.00 ns 
count_val = 1b Current time = 630.00 ns 
count_val = 1c Current time = 650.00 ns 
count_val = 1d Current time = 670.00 ns 
count_val = 1e Current time = 690.00 ns 
count_val = 1f Current time = 710.00 ns 
count_val = 20 Current time = 730.00 ns 
count_val = 21 Current time = 750.00 ns 
count_val = 22 Current time = 770.00 ns 
count_val = 23 Current time = 790.00 ns 
count_val = 24 Current time = 810.00 ns 
count_val = 25 Current time = 830.00 ns 
count_val = 26 Current time = 850.00 ns 
count_val = 27 Current time = 870.00 ns 
count_val = 28 Current time = 890.00 ns 
count_val = 29 Current time = 910.00 ns 
count_val = 2a Current time = 930.00 ns 

count_val = 2b Current time = 950.00 ns 
count_val = 2c Current time = 970.00 ns 
count_val = 2d Current time = 990.00 ns 
count_val = 2e Current time = 1010.00 ns 
count_val = 2f Current time = 1030.00 ns 
count_val = 30 Current time = 1050.00 ns 
count_val = 31 Current time = 1070.00 ns 
 
    313 State changes on observable nets in 0.76 seconds.
    411 Events/second. 
 
    Simulation stopped at the end of time 0.000001075s. 
Ready:  

Simulation stopped at the end of time 0.000001075s.

Ready:

A list of variables can be displayed when they change by using the $monitor directive. The syntax of the $monitor signal list and formatting controls is very similar to those used for the $display directive. Some examples of the using the $monitor directive are presented in Listing 5-8 and Listing 5-9 with the corresponding output shown in Listing 5-10.

$monitor (signal list and formatting);

$monitoron/$monitoroff;

Listing 5-8 $monitor Example display3.v

  module display3 (clock, reset); 
  input             clock, reset; 
  reg        [7:0]  count_val; 
  always @ (posedge clock or posedge reset) 
  begin 
      if (reset)    count_val    <=     0; 
      else 
      begin         count_val    <=     count_val + 1; 
  end 
  end 
  endmodule

Listing 5-9 $monitor Example Test Fixture disp3_tf.v

  //  $monitor used in a test fixture. 

   module time_setup2; 
   initial 
       begin 
       ‘timescale 1ns / 1ns  
       $timeformat (-9, 2, “ ns”, 3); 
       end 
   endmodule 

   module disp3_tf; 

       reg                 clock, reset; 
       wire         [7:0]  count_val; 
       parameter clk_period       =     20; 

   display3 u1 (clock, reset); 

   always 
       begin 
       #(clk_period / 2) clock = ~clock; 
       end 

   initial 
   begin 
       $monitor ($time, “ Counter value: %h”, u1.count_val); 
      clock         =      0; 
       reset        =      1;     // Assert the system reset. 
       #75 reset    =      0; 
       #1000 $finish 
   end 
   endmodule

Listing 5-10 $monitor Example Output Listing

 90000000000.00 ns Counter value: 01 
 110000000000.00 ns Counter value: 02 
 130000000000.00 ns Counter value: 03 
 150000000000.00 ns Counter value: 04 
 170000000000.00 ns Counter value: 05
 190000000000.00 ns Counter value: 06 
 210000000000.00 ns Counter value: 07 
 230000000000.00 ns Counter value: 08
 250000000000.00 ns Counter value: 09 
 270000000000.00 ns Counter value: 0a 
 290000000000.00 ns Counter value: 0b
 310000000000.00 ns Counter value: 0c 
 330000000000.00 ns Counter value: 0d
 350000000000.00 ns Counter value: 0e
 370000000000.00 ns Counter value: 0f 
 390000000000.00 ns Counter value: 10
 410000000000.00 ns Counter value: 11
 430000000000.00 ns Counter value: 12 
 450000000000.00 ns Counter value: 13 
 470000000000.00 ns Counter value: 14
 490000000000.00 ns Counter value: 15 
 510000000000.00 ns Counter value: 16
 530000000000.00 ns Counter value: 17
 550000000000.00 ns Counter value: 18 
 570000000000.00 ns Counter value: 19
 590000000000.00 ns Counter value: 1a
 610000000000.00 ns Counter value: 1b 
 630000000000.00 ns Counter value: 1c
 650000000000.00 ns Counter value: 1d 
 670000000000.00 ns Counter value: 1e 
 690000000000.00 ns Counter value: 1f
 710000000000.00 ns Counter value: 20 
 730000000000.00 ns Counter value: 21 
 750000000000.00 ns Counter value: 22
 770000000000.00 ns Counter value: 23 
 790000000000.00 ns Counter value: 24 
 810000000000.00 ns Counter value: 25
 830000000000.00 ns Counter value: 26 
 850000000000.00 ns Counter value: 27 
 870000000000.00 ns Counter value: 28
 890000000000.00 ns Counter value: 29 
 910000000000.00 ns Counter value: 2a 
 930000000000.00 ns Counter value: 2b
 950000000000.00 ns Counter value: 2c 
 970000000000.00 ns Counter value: 2d 
 990000000000.00 ns Counter value: 2e
 1010000000000.00 ns Counter value: 2f 
 1030000000000.00 ns Counter value: 30
 1050000000000.00 ns Counter value: 31
 1070000000000.00 ns Counter value: 32 

There are many file commands, we’ll touch on the highlights.

$dumpfile (“filename”);

$dumpvars(levels of hierarchy, module variables extracted from);

$dumpvars(0, module the variables extracted from);

$dumpvars

$dumpon;

$dumpoff;

$dumpall;

$dumplimit(filesize in bytes);

Verilog can save simulation results in an ASCII file. The format of this file is called Value Change Dump or VCD. An entry in the file occurs only when a variable value changes. The $dumpvars directive without an argument list will dump all the variables in the design. The $dumpvars (0, module name) directive will dump variables from the listed module and all modules instantiated by the listed module. Variables can be identified hierarchically in the file list (module1.module2.variable_name).

The VCD file can get very large. Setting a $dumplimit will stop the dump when the VCD file reaches the specified limit. Some examples of the $dump directive is shown in Listing 5-11 and Listing 5-12, with a partial output listing shown in Listing 5-13.

Listing 5-11 $dump Options

 #100 $dumpon;   // Dump all variables after 100 time units. 
 #100 $dumpoff;  // Stop dump after 100 time units. 
 #100 $dumpall;  // Dump a snapshot of all variables.

Listing 5-12 $dumpvars Example Listing

 // Value Change Dump Example. 
 module time_setup3; 
 initial begin  
     ‘timescale 10ns / 1ns 
     $timeformat (-9, 2, “ ns”, 3); 
     $dumpfile (“bigdump.dmp”); // Open file. 
     end 
 endmodule 

 module disp4_tf; 
     reg          clock, reset; 
     wire   [7:0] count_val; 
     parameter    clk_period    =     20; 

 display4 u1 (clock, reset); 
 always begin 
     #(clk_period / 2) clock = ~clock; 
     end 
 initial begin 
            $timeformat (-9, 2, “ ns”, 3); 
            $dumpvars; 
            clock        =      0; 
            reset        =      1;     // Assert the system reset. 
     #75 reset           =      0; 
     #1000 $finish; 
 end 
 endmodule  

 module display4 (clock, reset); 
 input clock, reset; 

 reg [7:0] count_val; 

 always @ (posedge clock or posedge reset) 
 begin 
     if (reset) 
     count_val     <=    0; 
     else 
     begin 
     count_val     <=    count_val + 1; 
 end 
 end endmodule

Listing 5-13 $dumpvars Output Listing Extract

 $scope module disp4_tf $end 
 $var reg   1 !    reset $end 
 $var reg   1 “    clock $end 
  
 $scope module u1 $end 
 $var wire  1 #     clock $end 
 $var wire  1 $      reset $end 
 $var reg   8 %      count_val [7:0] $end 
 $upscope $end 
  
 $upscope $end 
  
 $enddefinitions $end 
 #0 
 $dumpvars 
 1! 
 0“ 
 0# 
 1$ 
 b00000000 % 
 $end

Listing 5-13 is a small part of the bigdump.dmp. Note that each signal in the scope of $dumpvars (because $dumpvars was not limited in scope, all signals in the design are dumped) is assigned a key character (! = reset, for example) and this shorthand is used in the dumpfile. The VCD is not human-friendly, but is a format that can be read by other tools.

$readmemh (“filename”, memory_name); Read hex values from a file.

$readmemb (“filename”, memory_name); Read binary values from a file.

Optional starting and ending addresses can be added to place limits on the data pulled from the file. The address is an index into the array, the nth data element. It is acceptable to have a start address, but no end address, in which case the file is read to the end of the memory array.

$readmemh (“filename”, memory_name, start_addr, end_address);

AUTOMATED TESTING

The only way to assure thorough testing of a design is to automate the task. A check-off list can be created. When a new revision of code is being released, all the automated tests should be run again. The process is maddening, because most of the effort to resolve problems will be in test-fixture errors, not design errors. Still, there is no better way to test a design.

As an example, let’s design and test a simple digital filter as shown in Listing 5-14. The source code for this design is shown in Listing 5-15. The output values are shown in Figure 5-1. This design implements a one-dimensional low-pass pyramidal filter that uses five samples with coefficients of 0.0625, 0.125, 0.625, 0.125, and 0.0625 (note the sum of these coefficients is 1). This filter is crude and suffers from truncation errors but will serve as an example of automated testing.

Listing 5-14 Pyramidal Filter Test Fixture

 // Pyramidal Filter Example. 

 module time_setup4; 
 initial 
      begin 
      ‘timescale 1ns / 1ns 
      $timeformat (-9, 2, “ ns”, 3); 
      end 
 endmodule 

 module pf1_tf; 

      reg           clock, reset; 
      reg    [7:0]  tap_unfilt; 
       
 // Define array where test values will come from. 
      reg   [7:0] test_pattern[0:31]; 

 // Define array for testing filter output. 
     reg   [7:0] verify_pattern[0:31]; 
     reg   [4:0] mem_index; 
     wire  [7:0]  tap_filt; 
     reg   [7:0]  tap_test, filt_test; 
     reg          flag; 
       
     parameter clk_period      =       20; 

 pfilt1 u1 (clock, reset, tap_unfilt, tap_filt); 

 always begin 
     #(clk_period / 2) 
     clock               =      ~clock; 
     tap_unfilt          =      test_pattern [mem_index]; 
 //  filt_test           =      tap_filt [mem_index]; 
     tap_test            =      verify_pattern [mem_index]; 
     mem_index           =      mem_index + 1; 
     if (mem_index == 0) $finish; 
     end 
 
 always begin 
     #(clk_period) 
     if (!reset & (tap_filt != tap_test)) 
            begin 
 $display ($time, ImageImage ERROR! tap_filt = %h tap_test = %h′′, tap_filt, tap_test); 
            flag  <=     1; 
            end 
 //  else $display (“All is okay.”); 
     end 
 
 initial 
 begin 
 clock            =      0; 
 mem_index        =      0; 
 tap_test         =      0; 
 filt_test        =      0; 
 tap_unfilt       =      0; 
 flag             =      0; 
 reset            =      1;      // Assert the system reset. 

 // Read test pattern data from file into 
 //  test_pattern array. 
 $readmemh (“pfilt1.tst”, test_pattern); 
 $readmemh (“verify1.tst”, verify_pattern); 

 #(clk_period * 2)        reset        =       0; 
 end 
 endmodule

Listing 5-15 Pyramidal Filter Verilog Code

 // Pyramidal Filter Example. 
 // This implements a low-pass filter with coefficients: 
 //  .0625   .125  .625   .125  .0625 
 // Gain = 1. 
 module pfilt1 (clock, reset, tap4, tap_out[8:1]); 
 input             clock, reset; 
 input      [7:0]  tap4; 
 output            tap_out; 
 reg        [8:0]  tap_out; 
 reg        [7:0]  tap0, tap1, tap2, tap3; 

 // Intermediate summation (pipeline) registers. 
 reg [4:0] sum1; 
 reg [5:0] sum2; 
 reg [7:0] sum3; 
  
 always @ (posedge clock or posedge reset) 
 begin 
     if (reset) 
     begin 
     tap0          <=     0; 
     tap1          <=     0; 
     tap2          <=     0; 
     tap3          <=     0; 
     tap_out       <=     0; 
     sum1          <=     0; 
     sum2          <=     0; 
     sum3          <=     0; 
     end 
     else    begin 
     tap0          <=     tap1; 
     tap1          <=     tap2; 
     tap2          <=     tap3; 
     tap3          <=     tap4; 
      
 // To multiply by 0.0625 (same as division by 16): 
 //  shift left 2 places. 
 // Result register must be 1 larger than input 
 //  registers to hold carry. 
      sum1  <=     tap0[7:4] + tap4[7:4]; 
       
 // To multiply by 0.125 (same as division by 8): 
      sum2  <=     tap1[7:3] + tap3[7:3]; 
  
 // To multiply by 0.625 (5/8) is the same as: 
 // (division by 2) + (division by 8). 
      sum3  <=     tap2[7:1] + {2′b0, tap2[7:3]}; 
 // Final sum adds sum1 + sum2 + sum3. 
 // If the design needs to be faster, it can be 
 //  further pipelined to spread out the summing logic. 
 // The LSB is truncated to give an 8-bit result. Logic 
 //  can be added, if necessary, to round-off to 8 bits 
 //  instead. 
      tap_out[8:0] <=    {3′b0, sum1} + {2′b0, sum2} + sum3; 
      end 
 end 
 endmodule

Figure 5-1 Pyramidal Filter Waveforms

Img

The pyramidal filter design reads data from two external files. Data used to stimulate the filter is extracted from pfilt1.tst (shown in Listing 5-16) and identical data (except for an intentional error put in for test) used to test the filter output extracted from the file verify1.tst shown in Listing 5-17. The error is displayed as so:

140000000000.00 ns ERROR! tap_filt = 04 tap_test = 03

Three types of entries are allowed in files read by Verilog: numbers (either hex or binary), white space, and comments.

Listing 5-16 Pyramidal Filter Input Data List (pfilt1.tst)

 0 // Each data value is entered twice because the 
 0 //  value is loaded on each clock edge; two values 
 5 //  are required to sustain a value through 
 
 5 //  a complete clock period. 
 9 
 9 
 b 
 b 
 f 
 f 
 5 
 5 
 c 
 c 
 5 
 5 
 c 
 c 
 5 
 5 
 c 
 c 
 5 
 5 
 c 
 c 
 5 
 5 
 c 
 c 
 5 
 5

Listing 5-17 Pyramidal Filter Test Data List (verify1.tst)

 0 
 0 
 0 
 0 
 0 
 0 
 0 
 0 
 0 
 0 
 3 
 3 
 3 // Error added. Should be 4.
 3 // Error added. Should be 4.
 4 
 4 
 2 
 2
 3
 3
 2
 2
 3
 3
 2
 2
 3
 3
 2
 2

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.186.201