Altera Avalon-MM Master BFM Tutorial
------------------------------------

6/22/2015 D. W. Hawkins (dwh@caltech.edu)

This tutorial describes how to create a Qsys system containing the Altera
Avalon-MM Master BFM and then how to access that BFM during simulation
using either VHDL or Verilog.

-------------------------------------------------------------------------------
Tutorial Source Code
--------------------

The tutorial zip file altera_avalon_bfm_master.zip contains;

hdl/avalon_bfm_master/              BFM master example
hdl/avalon_bfm_master/readme.txt    The file you are reading
hdl/avalon_bfm_master/scripts       Scripts for Qsys and simulation
hdl/avalon_bfm_master/test          Testbench HDL

===============================================================================
Manual Qsys Creation and Simulation Procedure
===============================================================================

The manual procedure for creating and simulating the Qsys system is first
described. Once a Qsys system has been generated and simulated, the generation
and simulation sequence can be automated using scripts. The scripts are
described after the manual procedure.

-------------------------------------------------------------------------------
Quartus Project Creation
------------------------

1. Start Quartus II

   eg., Quartus II version 15.0 was used for this example

2. Create a new project

   * Select File->New Project Wizard

   * "Introduction"
     Skip this page

   * "Directory, Name, Top-Level Entity"

     Working directory: c:/temp/altera_avalon_bfm_master/hdl/avalon_bfm_master/qwork
     Project name:      avalon_bfm_master

     The qwork, or Quartus work, directory is used to contain the Quartus
     generated files. This makes it easier to determine which files need
     to be saved using source control software.

   * "Project Type"
     Accept the default "Empty Project"

   * "Add Files"
     Skip this step (we will add files later)

   * "Family & Device Settings"

     This example works with any Altera FPGA, so accept the default
     Cyclone V device (5CGXFC7C7F23C8)

   * "EDA Tool Settings"
     Accept the default (Modelsim-Altera VHDL)

   * "Summary"
     Click Finish

3. Save the project

   * Select File->Save Project

-------------------------------------------------------------------------------
Qsys System Creation
--------------------

1. Start Qsys

   * Select Tools->Qsys

2. Default "Clock Source"

   * Rename the default clock from clk_0 to clk
   * The default clock frequency is 50MHz

3. Add an Avalon-MM BFM Master

   * The component is located at

     Basic Functions->
       Simulation; Debug and Verification->
         Simulation->
           Altera Avalon-MM Master BFM

   * Change "Burstcount width" to 4
     - this allows a burst-of-8 = 1000b to be specified
     - the testbench tests burst-of-8 transactions

   * Change "Maximum pending reads" from 0 to 1

     This change ensures that this setting matches the setting
     in the Verification IP Users guide
     "Table 5-3: Parameters for the Avalon-MM Master BFM"

     The simulation notes below indicate that the simulation
     response for 0 and 1 are different.

   * Rename it bfm_master

4. PIO control

   * The component is located at

     Processors and Peripherals->
       Peripherals->
         PIO (Parallel I/O)

   * Change the width to 32-bits
   * Rename it pio_control

5. PIO status

   * The component is located at

     Processors and Peripherals->
       Peripherals->
         PIO (Parallel I/O)

   * Change the direction to Input
   * Change the width to 32-bits
   * Rename it pio_status

6. On-chip RAM

   * The component is located at

     Basic Functions->
       On Chip Memory->
         On-Chip Memory (RAM or ROM)

   * Accept the default size (32-bit width, 4kB total)
   * Uncheck "Initialize memory content"
   * Rename it onchip_ram

7. Connect the Qsys system reset, clock, and Avalon-MM interfaces

   * Connect the "Clock Source" clk and reset ports to the slaves

   * Connect bfm_master to the Avalon-MM slaves;

       Slave                      Address
       -----                      -------
       pio_control                0000_0000 to 0000_000F
       pio_status                 0000_0010 to 0000_001F
       onchip_ram                 0000_1000 to 0000_1FFF

8. Configure the Exported signals

   * Clock source
     - Export clk.clk_in as clk
     - Export clk.clk_in_reset as reset

   * PIO control
     - Export pio_control.external_connection as control

   * PIO status
     - Export pio_status.external_connection as status

9. Save the Qsys system as qsys_system.qsys

    The messages tab should have no warning messages.

    There will be an info message regarding the pio_status input;

      Info: qsys_system.pio_status: PIO inputs are not hardwired in test bench.
      Undefined values will be read from PIO inputs during simulation.

10. Generate the Qsys simulation files

   * Select Generate->Generate HDL

   * Change the "Create HDL design files for synthesis" pull-down to "None"
   * Uncheck "Create block symbol file (.bsf)"
   * Change the "Create simulation model" to VHDL or Verilog

     Select VHDL or Verilog depending on which language you would like
     to test. The tutorial test/ folder contains testbenches written in
     each language.

   * Click the "Generate" button

   The first statement in the Qsys generate GUI is the command used to
   create the Qsys system. This command can be copied and used within
   a Tcl script to automate the generation of the simulation HDL, eg.,
   with the Tcl variable qwork set to

   qwork = c:/temp/altera_avalon_bfm_master/hdl/avalon_bfm_master/qwork

   and VHDL selected as the language, the generate command is

   qsys-generate $qwork\qsys_system.qsys \
   	--simulation=VHDL \
   	--output-directory=$qwork\qsys_system\simulation \
   	--family="Cyclone V" --part=5CGXFC7C7F23C8

   and with Verilog selected the generate command is

   qsys-generate $qwork\qsys_system.qsys \
   	--simulation=VERILOG \
   	--output-directory=$qwork\qsys_system\simulation \
   	--family="Cyclone V" --part=5CGXFC7C7F23C8

   i.e., the only difference is the --simulation argument.

   Note that the --output-directory argument had to be modified to
   --output-directory=$qwork\qsys_system otherwise an extra simulation
   directory would be created (this is probably a bug in the Qsys
   console message that prints the arguments)

-------------------------------------------------------------------------------
Qsys System Simulation
----------------------

1. Start Modelsim

   For example, Quartus II version 15.0 ships with Modelsim-ASE (Altera Starter Edition) 10.3d.
   If you plan on using Modelsim-SE, then make sure to use Modelsim-SE 10.3d, as it is not
   always possible to simulate using a different version of Modelsim from the release shipped
   with Quartus.

2. Change directory to the mentor simulation folder

   ModelSim> cd {c:\temp\altera_avalon_bfm_master\hdl\avalon_bfm_master\qwork\qsys_system\simulation\mentor}

3. Source the Modelsim setup script

   ModelSim> source msim_setup.tcl

4. Compile the simulation source

   a) Modelsim-SE

   ModelSim> dev_com
   ModelSim> com

   a) Modelsim-ASE

   ModelSim> com

   At this point, the Qsys system component is ready for simulation. However,
   a testbench is required to issue Avalon-MM master BFM commands.

5. Compile the testbench

   The tutorial source contains VHDL and Verilog testbenches within the test/ folder.
   Copy the appropriate file(s) into the mentor folder, or use the full path, and
   compile via

   a) VHDL

   ModelSim> vcom -2008 log_pkg.vhd
   ModelSim> vcom -2008 qsys_system_tb.vhd

   or

   ModelSim> vcom -2008 {c:\temp\altera_avalon_bfm_master\hdl\avalon_bfm_master\test\log_pkg.vhd}
   ModelSim> vcom -2008 {c:\temp\altera_avalon_bfm_master\hdl\avalon_bfm_master\test\qsys_system_tb.vhd}

   b) Verilog

   ModelSim> vlog -sv qsys_system_tb.sv -L altera_common_sv_packages

   or

   ModelSim> vlog -sv {c:\temp\altera_avalon_bfm_master\hdl\avalon_bfm_master\test\qsys_system_tb.sv} -L altera_common_sv_packages

6. Set the testbench as the top-level component

   ModelSim> set TOP_LEVEL_NAME qsys_system_tb

7. Elaborate the top-level component

   a) Modelsim-SE

   ModelSim> elab_debug +nowarnTFMPC

   a) Modelsim-ASE

   ModelSim> elab +nowarnTFMPC

   The argument +nowarnTFMPC suppresses warnings within the Avalon-MM interconnect.
   The difference between elab and elab_debug is that optimization is turned off,
   so that Modelsim-SE does not eliminate logic.

8. Populate the wave window

   The tutorial source file scripts/qsys_system_tb.do populates the Modelsim wave
   window. Copy the file to the mentor directory and load the script via
   (or use the full path to the script)

   VSIM> do qsys_system_tb.do

   or

   VSIM> do {c:\temp\altera_avalon_bfm_master\hdl\avalon_bfm_master\scripts\qsys_system_tb.do}

9. Run the simulation

   VSIM> run -a

   See the contents of the following text files for the simulation output;

   qsys_system_tb_vhd_output.txt = VHDL simulation
   qsys_system_tb_sv_output.txt  = SystemVerilog simulation

**********************
*** IMPORTANT NOTE ***
**********************

Under Modelsim-ASE, the SystemVerilog simulation runs *significantly* faster
than the VHDL simulation (seconds versus minutes!). The difference is not
quite as bad using Modelsim-SE, however, there is still a difference.
The slow VHDL simulation time implies that the overhead of the VHDL to
SystemVerilog wrapper is quite high.

The following simulation run times were logged by the simulation script
(scripts/sim.tcl) described below.

   ---------------------------------------------
  | Modelsim version   | Language | Run time    |
  |--------------------|----------|-------------|
  |                    |          |             |
  | Modelsim-ASE 10.3d | Verilog  |     1 sec   |
  |                    | VHDL     |  4.87 mins  |
  |                    |          |             |
  | Modelsim-SE 10.3d  | Verilog  |     1 sec   |
  |                    | VHDL     |    19 sec   |
  |                    |          |             |
   ---------------------------------------------

The run time is the time taken for the 'run -a' command to run. The measured
run time does not include the time taken to build the source code.

Modelsim-ASE was run natively on a Windows 7 laptop (Lenovo Y40).

Modelsim-SE was run from within a VirtualBox virtual machine running on
that same laptop. The Modelsim-SE simulation script takes a while to build
the device libraries the first time it is run.

-------------------------------------------------------------------------------
Single-language vs Mixed-language Modelsim simulation
-----------------------------------------------------

The two simulation examples presented by this tutorial use a single language
for the Qsys system and the testbench to allow the use of Modelsim-ASE.
Modelsim-SE can also run these single-language simulations. Modelsim-SE also
supports the option of generaing the Qsys system in a mixture of languages.
Under mixed language mode, you would typically generate the Qsys system
nominally in Verilog, so that the BFM used SystemVerilog. You would then
write the testbench in SystemVerilog to avoid the overhead of the VHDL
wrapper.

===============================================================================
Automated Qsys Creation and Simulation Procedure
===============================================================================

The Qsys simulation can be automated as follows;

1. Generate Qsys system simulation HDL files

   The Qsys system is described by the XML file qsys_system.qsys

   The Quartus II Qsys tool needs to be used to convert this XML description
   into simulation HDL files.

   The Quartus II synthesis script, scripts/synth.tcl, creates a Quartus II
   project, and then generates the Qsys simulation files.

   The choice of VHDL or Verilog is determined by a Tcl variable, eg.,

   a) Start Quartus II

   b) Select the Quartus II Tcl console

   c) Change to the project directory

      tcl> cd {c:\temp\altera_avalon_bfm_master\hdl\avalon_bfm_master}

   d) Set the language (option: it defaults to verilog)

      tcl> set language vhdl

      or

      tcl> set language verilog

   e) Source the synthesis script

      tcl> source scripts/synth.tcl

      Quartus II console output (for verilog)

      Synthesizing the Avalon-MM Master BFM Qsys example
      --------------------------------------------------
       - Simulation language is 'verilog'
       - Quartus Version 15.0.0 Build 145 04/22/2015 SJ Full Version
       - Creating the Quartus work directory
         * c:/temp/altera_avalon_bfm_master/hdl/avalon_bfm_master/qwork
       - Create the project 'avalon_bfm_master'
         * create a new 'avalon_bfm_master' project
       - Applying constraints
       - Generate the Qsys system
         * copy the Qsys file to the work directory
         * generating the Qsys system (please wait)
       - Qsys simulation HDL generation completed

   The synthesis script could be modified to create a language specific
   build area, eg., qwork/verilog and qwork/vhdl.

2. Modelsim simulation

   The Quartus generated Mentor/Modelsim simulation script msim_setup.tcl
   contains the majority of the simulation setup. The simulation script
   scripts/sim.tcl sets up the variables used by the Mentor script, and
   then runs the simulation.

   a) Start Modelsim

   b) Change to the project directory

      ModelSim> cd {c:\temp\altera_avalon_bfm_master\hdl\avalon_bfm_master}

   c) Set the language (option: it defaults to verilog)

      tcl> set language vhdl

      or

      tcl> set language verilog

   d) Source the simulation script

      tcl> source scripts/sim.tcl

The Qsys system testbench then runs and generates the console output as
shown in;

   qsys_system_tb_vhd_output.txt = VHDL simulation
   qsys_system_tb_sv_output.txt  = SystemVerilog simulation

Note that if you first run the Verilog simulation and then decide to run
the VHDL simulation, before using Quartus II Qsys to generate the simulation
files in a different language, delete the ./qwork/simulation and ./libraries
folders, so that the new files are generated in a new directory (not mixed
up with the previous language files).

===============================================================================
Miscellaneous Notes
===============================================================================

-------------------------------------------------------------------------------
Altera Avalon-MM Master BFM "Maximum pending reads" parameter
-------------------------------------------------------------

The BFM parameter "Maximum pending reads" determines the number of read transactions
that the BFM will issue to a slave. The default value when the BFM is added to a
Qsys system is 0. That number seems incorrect, since it would seem logical that that
number be at least 1. Should this be modified?

The Verification IP Suite states that the default value of "Maximum pending reads"
is 1, not 0. Is the functionality of the BFM identical is the setting is 0 or 1,
i.e., does a setting of 0 get interpreted as 1? Modelsim tests indicate no, they
are not the same. The BFM setting should be changed to 1 (or more) when the BFM
is instantiated.

Modelsim waveform observation:

a) Maximum pending reads = 0

   The single read transactions are not affected by this setting, since each read is
   blocked, i.e., each read transaction is issued and then the testbench blocks waiting
   for the read response (the assertion of readdatavalid). Given this blocking operation,
   the testbench will never issue a second read transaction.

   The same argument applies to burst read transactions. A burst read transaction is
   issued and then the testbench blocks waiting for all read burst response data to
   be returned.

   During single and burst reads, the waitrequest signal asserts after the read transaction
   is accepted. During single read transactions, waitrequest asserts for three clock
   periods, deasserting at the end of the clock period that readdatavalid asserts.
   During burst read transactions, waitrequest deasserts two data phases before the end of
   the burst transaction.

b) Maximum pending reads = 1

   During the testbench single read transactions waitrequest does not assert.

   During the testbench burst read transactions waitrequest asserts right after the
   transaction is accepted, remains asserted for 7 clock periods, and deasserts
   two data phases before the end of the burst transaction.

   The fact that "Maximum pending reads" is not the same for settings of 0 or 1
   means that the BFM setting should be changed to 1 to match the Verification IP Suite.

c) Maximum pending reads = 2 or 4

   The simulation waveforms look the same as with Maximum pending reads = 1.
   This is to be expected, since the testbench does not issue more than
   one read transaction before waiting for the response.

Altera Knowledgebase: Search for "maximum pending reads"
 -> there are no entries related to the BFM setting

-------------------------------------------------------------------------------
Qsys XML or Tcl?
----------------

The Qsys system is described by the XML file qsys_system.qsys. The contents
of the XML file vary slightly with different Quartus II versions and with the
components added to the Qsys system. The Qsys XML description can be converted
to a Tcl description using a script from the AlteraWiki, i.e.,

http://www.alterawiki.com/wiki/Qsys_Scripts

The advantage of using a Tcl file is that it allows the use of conditional logic.
This allows a qsys_system.tcl file to support multiple versions of Quartus II
(which is nice when a project is used across multiple versions, eg., due to
device support restrictions). The qsys_system.tcl file is constructed by
converting the .qsys file from multiple versions of Quartus II and factoring
out the common and difference code.