Basic FPGA Tutorial |
|
|
All rights strictly reserved. Reproduction or issue to third parties, in any form whatsoever, is not permitted without written authority from the proprietors. |
Modulation Lab |
||||
|
Project Name / Projektname |
Page / Seite |
|||||
|
|
|
|||||
|
Prepared by / Erstellt |
Subject Responsible / Verantwortlich |
Date / Datum |
Rev. |
File / Datei OpenOffice.org Writer |
||
|
Maja Gordić |
Peter Thorwartl |
|
1.0 |
|
||
Basic FPGA Tutorial
using VHDL, ISE and Spartan-3e
and a simple
two frequencies PWM modulator lab

Table of Contents
-
3. COUNTER 22
7. PWM 41
8. MODULATOR 46
8.7 Implementation/Translation 53
8.9 Implementation/Place&Route 61
8.10 Generate Programming File 73
8.11 Configure Target Device 74
1. INTRODUCTION
1.1 Motivation
Basic FPGA Tutorial is a document made for beginners who are entering the FPGA world. This tutorial explains, step by step, procedure of designing simple digital system using VHDL language and Xilinx design tools.
1.2 Purpose of this lab
This lab is made to introduce you how to create, simulate and test an project.
After completing this lab, you will be able to:
Launch and navigate the Project Navigator
Locate and insert snippets from the Language Templates
Demonstrate the capabilities of the text editor
Simulate a design using integrated Simulator ISim or external ModelSim
Debug a design in hardware using ChipScope Pro Tool and Oscilloscope
The following project is designed for:
Designing Surface: ISE 11.1
HD Language: VHDL
Simulator: ISIM / ModelSim SE 6.2a
Device: Xilinx Spartan-3E 500 FG320 Demo Board
1.3 Description of this lab
In this lab a PWM signal modulated using the sine wave with two different frequencies (1 Hz and 3.5 Hz) will be created. Frequency that will be chosen depends on the position of the two-state on-board switch (sw0).
PWM Signal
Pulse-width modulation (PWM) uses a rectangular pulse wave whose pulse width is modulated by some other signal (in our case we will use a sine wave) resulting in the variation of the average value of the waveform. Typically, PWM signals are used to either convey information over a communications channel or control the amount of power sent to a load. To learn more about PWM signals, please visit http://en.wikipedia.org/wiki/Pulse-width_modulation.
Drawing 1.1. illustrates the principle of pulse-width modulation. In this picture an arbitrary signal is used to modulate the PWM signal, but in our case sine wave signal will be used.

Drawing
1.1:
Example of the PWM signal
1.4 One possible solution of this lab
Considering that we are working with digital systems and signals, our task will be to generate an digital representation of an analog (sine) signal with two frequencies: 1 Hz and 3.5 Hz.
Drawing 1.2 is showing the sine wave that will be used to modulate the PWM signal.

Drawing
1.2:
Sine wave with 256 samples
One period of the sine wave is represented with 256 (28) samples, where each sample can take one of 4096 (212) possible values. Since the sine wave is a periodic signal, we only need to store samples of one period of the signal.
Note: Pay attention that all of sine signals with the same amplitude, regardless their frequency, look the same during the one period of a signal. The only thing that is different between those sine signals is duration of a signal period. This means that the sample rate of those signals is different.
Considering that the whole system will be clocked with the 50 MHz input signal, which is typically available on the development boards, to get 1 Hz and 3.5 Hz frequencies (which is much smaller than 50 MHz) we should divide input clock frequency with integer value N.
In the Tables 1.1 and 1.2 are shown parameters that are necessary for generating sine signals with 1 Hz and 3.5 Hz frequencies.
Table 1.1: Sine signal with the frequency of 1 Hz
|
T=1 s |
|
T is the period of the signal |
|
f1=256 Hz |
|
f1 is the frequency of reading whole period (T) with 256 samples |
|
N1=195313 |
|
N1 is the number which divide frequency of the input clock signal (50 MHz) to the required frequency for the digital sine module |
|
N2=48 |
N2=195313/4096=47.684 |
N2 is the number which divide frequency of the input clock signal (50 MHz) to the required frequency for the PWM's FSM module |
|
N1=196608 |
N1=48*4096=196608 |
This is new calculation, because N1 must be divisible with 4096 |
Table 1.2: Sine signal with the frequency of 3.5 Hz
|
T=0.286 s |
|
T is the period of the signal |
|
f2=896 Hz |
|
f2 is the frequency of reading whole period (T) |
|
N1=55804 |
|
N1 is the number which divide frequency of the input clock signal (50 MHz) to the required frequency |
|
N2=14 |
N2=55804/4096=13.624 |
N2 is the number which divide frequency of the input clock signal (50 MHz) to the required frequency for the PWM's FSM module |
|
N1=57344 |
N1=14*4096=57344 |
This is new calculation, because N1 must be divisible with 4096 |
Now, it is obvious that the sine wave can be generated by reading sample values of one period, that are stored in one table, with appropriate speed. In our case the values will be generated using the sine function from the IEEE Math library and will be stored in an ROM memory.
Block diagram
Block diagram on the Drawing 1.3 shows the structure of one possible system that can be used to generate required PWM signals.

Drawing
1.3: Block diagram
Let us briefly explain each module shown on the Drawing 1.3:
Frequency Trigger
This module will generate one output signal with two possible frequencies calculated in the Tables 1.1 and 1.2, one with 256 Hz and the second one with 896 Hz. Which frequency will be chosen depends on the position of the two-state on-board switch (sw0).
Counter
This module will be an universal (generic) counter. It's task will be to generate read addresses for the ROM where samples of the sine wave are stored. The speed of the counting will be controlled by the Frequency Trigger module, via freg_trig signal, and the output of the Counter module will be an input of the Digital Sine module.
Digital Sine
This module will generate an digital representation of an analog (sine) signal with desired frequency. It will use the counter values as addresses to fetch the next value of the sine wave from the ROM.
In our case we will make an VHDL package with a parametrized sine signal. 28=256 unsigned amplitude values during one sine-period that will be stored into an ROM array.
VHDL package is a way of grouping related declarations that serve a common purpose. Each VHDL package contains package declaration and package body.
Note: Don't forget to include the Sine package in the code of the Digital Sine module !
PWM
This module will generate an PWM signal modulated using the digital sine wave from the Digital Sine module. This module will be composed of two independent modules. One will be the Frequency Trigger, for generating two different frequencies and the second one will be the Finite State Machine (FSM), for generating the PWM signal.
Frequency Trigger – output from this module will be used to control the frequency at which FSM module works. As we have already said, in PWM signal information is represented as duty cycle value in each period of the signal. Since our digital sine signal can have 4096 possible values, there will also be 4096 different duty cycle values. This means that PWM's FSM must operate at frequency that is 4096 times higher than the one used by the Digital Sine module.
FSM – is necessary to generate the PWM signal. It will generate the PWM signal with correct duty cycle for each period based on the current amplitude value of digital sine signal, that is stored in the ROM.

Drawing
1.4: Details of PWM signal generation
Design steps
This lab will be realized
step by step with the idea to explain the whole procedure of
designing an digital system
On the Drawing 1.4 are shown steps in designing modules of this lab:
- First we will make the Frequency Trigger module that will provide one signal with two possible frequencies
- Then, we will make the Counter module, that will generate read addresses for the ROM where samples of the sine wave are stored
- Then we will make an VHDL package with a parametrized sine signal
- After that, we will make the Digital Sine module, where we will generate an digital representation of an analog (sine) signal and where we will include the Sine package
- At the end, we will generate PWM signal with the PWM module.
Drawing 1.5: Project Design Steps
1.5 Design Flow

Drawing
1.6: Design Flow
Design Entry – the first step in creating a new design is to specify it's structure and functionality. This can be done either by writing an HDL model using some text editor or drawing a schematic diagram using schematic editor.
Design Synthesis – next step in the design process is to transform design specification into a more suitable representation that can be further processed in the later stages in the design flow. This representation is called the netlist. Prior to netlist creation synthesis tool checks the model syntax and analyse the hierarchy of your design which ensures that your design is optimized for the design architecture you have selected. The resulting netlist is saved to an Native Generic Circuit (NGC) file (for Xilinx® Synthesis Technology (XST) compiler) or an Electronic Design Interchange Format (EDIF) file (for Precision, or Synplify/Synplify Pro tools).
Design Implementation
Implementation step maps netlist produced by the synthesis tool onto particular device's internal structure. It consists from three steps:
Generate Programming File - creates a bitstream file that can be downloaded to the device
3.1 Translate step – merges all incoming netlists and constraints into a Xilinx Native Generic Database (NGD) file.
3.2 Map step - maps the design, specified by an NGD file, into available resources on the target FPGA device, such as LUTs, Flip-Flops, BRAMs,... As a result, an Native Circuit Description (NCD) file is created.
3.3 Place and Route step - takes a mapped Native Circuit Description (NCD) file, places and routes the design, and produces an NCD file that is used as input for bitstream generation.
2. FREQUENCY TRIGGER
2.1 Description
Usage: This module will generate one output signal with two possible frequencies, one with 256 Hz and the second one with 896 Hz. Which frequency will be chosen depends on the position of the two-state on-board switch (sw0).
Block diagram:

Drawing
2.1:
Frequency Trigger block diagram
Input signals:
- clk_in: 50 MHz input clock signal
- sw0_freq_sel: input signal from the on-board switch, used for changing output signal frequency
Output signals:
- freq_trig: output signal which frequency depends on the state of the sw0_freq_trig input signal (256 Hz or 896 Hz)
File name: frequency_trigger_rtl.vhd
2.2 Creating Project
To create a new project, follow these steps:
Launch Project Navigator
In the Project Navigator, select File / New Project
Enter project_name (in our case it is modulator) in the Project Name Field
Choose your Working Directory at the Project Location field (*/)
Note: This option will automatically generate a project folder, with the same name as a project name, and place it in the selected working directory.
Verify that HDL option has been selected from the Top-Level Source Type drop-down list
These steps are shown on the Illustration 2.1.

Illustration
2.1: Crating a new project with ISE Wizard
Click Next
Set the following parameters like on the Illustration 2.2:
Design Purpose (for example Automotive, Military, High-Reliability,...)
Product Category: All
Family Specification (for example CoolRunner, Spartan, Virtex,...)
Family: Spartan3E
Device Type (differs in number of CLBs, memory blocks, clock resources,... )
Device: XC3S500E
Different packages (differing from each other in package type and size, number of available IOs, types of IOs, etc.)
Package: FG320
Speed Grade: -5
Synthesis Tool: XST(VHDL/Verilog)
Leave all other options at their default settings

Illustration
2.2: Specifying device properties
Click Next, leaving all fields blank in the Create New Source File dialog box
Click Next, leaving all fields blank in the Add Existing Sources dialog box
Click Finish in the Project Summary dialog box to finish with the creating of the new project
2.3 Creating Module
To create a new module, follow these steps:
Select Project / New Source
In the New Source dialog box, Illustration 2.3, select VHDL Module, enter module_name (in our case it is frequency_trigger_rtl) in the File name field and click Next to open the Define Module dialog box

Illustration
2.3: New Source dialog box
Enter module_entity_name (frequency_trigger) in the Entity name field and module_architecture_typ (rtl) in the Architecture name field
Specify ports for the intended module as shown on the Illustration 2.4

Illustration
2.4: Specifying ports for the Frequency Trigger module
Click Next
Click Finish
Note: The Tool automatically creates a default header and the entity declaration based on the data that you entered.
Important: The automatically generated code is not very handsome and clear, and the recommendation is to modify it. Here are the steps for modifying:
create a module header as comment
set all text to lower case
remove all end descriptions (for example: rtl next to end) and all comments
set all in/outputs in alphabetical order and comment them
Note: As you can see there is a lot of things for modifying. For better designs, our recommendation is not to use the GUI module inserter. Instead of that, create a module in an text editor, rename it to module_name.vhd and insert it into your project.
Frequency Trigger VHDL model:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity frequency_trigger is
generic(
freqhigh_g : std_logic_vector (17 downto 0) := (others=>'0'); -- input clock division factor when sw0_freq_sel = '1'
freqlow_g : std_logic_vector (17 downto 0) := (others=>'0') -- input clock division factor when sw0_freq_sel = '0'
);
port(
clk_in : in std_logic; -- 50 MHz input clock signal
sw0_freq_sel : in std_logic; -- signal used for selecting frequency
freq_trig : out std_logic -- output signal which frequency depends on the sw0_freq_sel state
);
end;
architecture rtl of frequency_trigger is
signal freq_cnt_s : std_logic_vector (17 downto 0) := (others => '0'); -- clock counter
signal sw0_freq_sel_jmp : std_logic := '0'; -- variable who is tracking sw0_freq_sel'event
begin
freq_ce_p : process -- create and select frequency
begin
wait until rising_edge(clk_in);
freq_cnt_s <= freq_cnt_s + 1; -- increment
freq_trig <= '0';
case sw0_freq_sel is -- select sine frequency
when '0' => -- frequency for sw0_freq_sel = '0'
if (sw0_freq_sel_jmp = '1') then
freq_cnt_s <= (others => '0'); -- reset
sw0_freq_sel_jmp <= '0';
end if;
if (freq_cnt_s = freqlow_g - 1) then
freq_trig <= '1';
freq_cnt_s <= (others => '0'); -- reset
end if;
when '1' => -- frequency for sw0_freq_sel = '1'
if (sw0_freq_sel_jmp = '0') then
freq_cnt_s <= (others => '0'); -- reset
sw0_freq_sel_jmp <= '1';
end if;
if (freq_cnt_s = freqhigh_g - 1 ) then
freq_trig <= '1';
freq_cnt_s <= (others => '0'); -- reset
end if;
when others => null;
end case;
end process;
end;
In the Sources window, left-click on the module_name (frequency_trigger – rtl), then in the Processes window expand Synthesize and then double-click on the Check Syntax (see Illustration 2.5).
Note: Please bear in mind that the Implementation option from the “Sources for” drop-down list must be selected.

Illustration
2.5: Check Syntax
Correct any errors before proceeding
2.4 Creating Test Bench
Usage: used to verify correct operation of the frequency_trigger module defined in the frequency_trigger_rtl.vhd file
Test bench internal signals:
- clk_in_s: 50 MHz input clock signal
- sw0_freq_sel_s: input signal used to select output signal frequency
- freq_trig_s: output signal which frequency depends of the sw0_freq_sel_s signal state
- freqhigh_g: input clock division factor when sw0_freq_sel = '1'
- freqlow_g: input clock division factor when sw0_freq_sel = '0'
File name: frequency_trigger_tb.vhd
We are creating a test bench to verify the correctness of a design or model.
Here are the steps necessary for creating an test bench:
Select Project / New Source
In the New Source dialog box, select VHDL Test Bench and enter testbench_name (frequency_trigger_tb) in the File name field (see Illustration 2.6)

Illustration
2.6: New Source dialog box
Click Next to select a source with which to associate the new source
Select the frequency_trigger module. Click Next and click Finish in the Summary dialog box
The ISE software now have created a standard structure for a test bench, which contains:
Test bench description
Component declaration: Based on the Unit Under Test (UUT) that we have designated
Signal declarations: Using the same names as the ports in the UUT module
Time constants for clock generation
Instantiation and port map: Connected the declared component and signals
Stimulus process: Created wait statements for stimulus generation
Important: The automatically generated code is not very handsome and clear, and the recommendation is to modify it. Here are the steps for modifying:
set all text to lower case
remove all time constants, clock process definitions, stimulus processes, port map definitions and comments
rename architecture description into a architecture_tb (frequency_trigger_tb)
suffix all signals with a “_s” (for example: clk_in_s) and update it in the port map on the right side
create a module - and a revision-description as comment (header)
set all in/outputs and signals in alphabetical order and comment them
Note: As you can see there is a lot of things for modifying. For better designs, our recommendation is not to use the GUI module inserter. Instead of that, create a module in an text editor, rename it to module_name.vhd and insert it into your project.
Create a test bench module using the code below:
Frequency Trigger test bench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity frequency_trigger_tb is
generic(
freqhigh_g : std_logic_vector (17 downto 0) := b"0000_0100"; -- input clock division factor when sw0_freq_sel = '1'
freqlow_g : std_logic_vector (17 downto 0) := b"0000_0010" -- input clock division factor when sw0_freq_sel = '0'
);
end;
architecture tb of frequency_trigger_tb is
constant per_c : time := 20 ns; -- clock period (T=1/50 MHz)
signal clk_in_s : std_logic := '1'; -- 50 MHz input clock signal
signal freq_trig_s : std_logic := '1'; -- signal which frequency depends on the sw0_freq_sel state
signal sw0_freq_sel_s : std_logic := '0'; -- signal for selecting frequency
begin
freq_ce : entity work.frequency_trigger (rtl) -- fetch generics and ports of frequency_trigger_rtl.vhd
generic map(
freqhigh_g => freqhigh_g,
freqlow_g => freqlow_g
)
port map(
clk_in => clk_in_s,
sw0_freq_sel => sw0_freq_sel_s,
freq_trig => freq_trig_s
);
clk_in_s <= not (clk_in_s) after per_c/2; -- generates 50 MHz clock signal;
sw0_freq_sel_s <= '1' after 200 ns;
end;
2.5 Simulating (with Isim)
After you have entered the code for the input stimulus in order to perform simulation, follow these steps:
In the Sources window right-click, then select Design Properties
Verify that ISim (VHDL/Verilog) option is selected in the Simulator field, and VHDL is selected in the Preferred Language field (see Illustration 2.7).

Illustration
2.7: Design Properties – ISim
Click Ok
If necessary, select Behavioral Simulation from the “Sources for” drop-down list
Select testbench_name (frequency_trigger_tb.vhd) in the Sources window
In the Processes window, expand ISim Simulator and double-click on the Behavioral Check Syntax (only available for ISE Simulation), Illustration 2.8.

Illustration
2.8: Behavioral Check Syntax
Correct any errors before proceeding
In the Processes window, double-click on the Simulate Behavioral Model (see Illustration 2.8)
Assuming no errors, your simulation result should look similar to the Illustration 2.9.

Illustration
2.9: Simulation Results
Optional: If you want to insert further internal signals from your simulated file, click on the file in the Sim Instances window and drag-and-drop the signal from the Sim Objects window into the waveform window. Now you have to restart and rerun your simulation.
Optional: If you want to restart and rerun simulation for specific time, see Illustration 2.10.

Illustration
2.10: Variable Simulation Time - ISim
Note: In this design you can choose between two different simulators, the integrated ISE Simulator ISim from Xilinx and Mentor Graphic's ModelSim-SE. To learn how to switch and use the ModelSim Simulator, please see Chapter 3.4 Simulating (with ModelSim).
3. COUNTER
3.1 Description
Usage: This module will be an universal (generic) counter. It's task will be to generate read addresses for the ROM where samples of the sine wave are stored. The speed of the counting will be controlled by the Frequency Trigger module, via freg_trig signal, and the output of the Counter module will be an input of the Digital Sine module.
Block diagram:
Drawing
3.1: Counter block diagram
Input signals:
- clk_in: 50 MHz input clock signal
- cnt_en: counter enable
Output signals:
- cnt_out: current counter value
File name: counter_rtl.vhd
3.2 Creating Module
Note: For better designs, our recommendation is not to use the GUI module inserter. Instead of that, create a module in an text editor, rename it to module_name.vhd and insert it into your project.
Here are the steps for creating an module:
Open an text editor (for better usability, take one with VHDL code support)
Insert the VHDL code and add the counter_rtl module header
Save the file as module_name (e.g. counter_rtl) into your working directory
Change the ending from *.txt to *.vhd
Optional: Launch Project Navigator (if it is not already open)
Optional: Open “Modulator" project (modulator.xise)(if it is not already open)
In the Project Navigator, select Project / Add Source
Select module file (e.g. counter_rtl.vhd)
In the Adding Source Files window, select All in the Association drop-down many
Click Ok
Counter VHDL model:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity counter is
generic(
cnt_value_g : std_logic_vector -- threshold value for counter
);
port(
clk_in : in std_logic; -- 50 MHz input clock signal
cnt_en : in std_logic; -- counter enable
cnt_out : out std_logic_vector(cnt_value_g'length - 1 downto 0) -- current counter value
);
end;
architecture rtl of counter is
signal cnt_out_s : std_logic_vector (cnt_value_g'length - 1 downto 0) := (others => '0'); -- current counter value
begin
counter_p: process
begin
wait until rising_edge(clk_in);
if (cnt_en = '1') then
if (cnt_out_s = cnt_value_g - 1) then
cnt_out_s <= (others => '0'); -- counter reset
else
cnt_out_s <= cnt_out_s + 1; -- counter
end if;
end if;
end process;
cnt_out <= cnt_out_s;
end;
In the Sources window, left-click on the module_name (counter_rtl), then in the Processes window expand Synthesize and then double-click on the Check Syntax (see Illustration 2.5).
Note: Please bear in mind that the Implementation option from the “Sources for” drop-down list must be selected.
Correct any errors before proceeding
3.3 Creating Test Bench
Usage: used to verify correct operation of the counter module defined in the counter_rtl.vhd file
Test bench internal signals:
- clk_in_s: 50 MHz input clock signal
- cnt_en_s: counter enable
- cnt_out_s: current counter value
- cnt_value_g: threshold value for counter
File name: counter_tb.vhd
We will now create a test bench for the Counter module (counter_tb.vhd) using the same steps as in creating counter_rtl.vhd module, explained in Chapter 3.2 Creating Module.
Counter test bench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity counter_tb is
generic(
cnt_value_g : std_logic_vector := b"100" -- threshold value for counter
);
end;
architecture tb of counter_tb is
constant per_c : time := 20 ns; -- clock period
signal clk_in_s : std_logic := '1'; -- 50 MHz input clock signal
signal cnt_en_s : std_logic := '0'; -- counter enable
signal cnt_out_s : std_logic_vector (cnt_value_g'length - 1 downto 0) := (others => '0'); -- current counter value
begin
counter : entity work.counter(rtl) -- fetch generics and ports of counter_rtl.vhd
generic map(
cnt_value_g => cnt_value_g
)
port map (
clk_in => clk_in_s,
cnt_en => cnt_en_s,
cnt_out => cnt_out_s
);
clk_in_s <= not (clk_in_s) after per_c/2; -- generate 50 MHz clock
cnt_en_s <= '1' after 100 ns, '0' after 120 ns, '1' after 160 ns, '0' after 180 ns, '1' after 220 ns, '0' after 240 ns, '1' after 320 ns, '0' after 340 ns, '1' after 420 ns, '0' after 440 ns;
end;
3.4 Simulating (with ModelSim)
After you have entered the code for the input stimulus in order to perform simulation, follow these steps:
In the Sources window right-click, then select Design Properties
Verify that Modelsim-SE VHDL option is selected in the Simulator field and VHDL is selected in the Preferred Language field (see Illustration 3.1)
Click Ok

Illustration
3.1: Design Properties – ModelSim
Select testbench_name (counter_tb.vhd) in the Sources window
If necessary, select Behavioral Simulation from the “Sources for” drop-down list
In the Processes window, expand ModelSim Simulator and then double-click on the Simulate Behavioral Model, Illustration 3.2.

Illustration
3.2: Simulate Behavioral Model
Assuming no errors in the ModelSim command line, your simulation result should look similar to Illustration 3.3.

Illustration
3.3: Simulation Results
Optional: If you want to insert further internal signals from your simulated file, click on the file in the Sim Instances – workspace window and drag-and-drop the signal from the Objects window into the waveform window. Now you have to restart and rerun your simulation.
Optional: If you want to restart and rerun simulation for specific time, see Illustration 3.4 .

Illustration
3.4: Variable Simulation Time – ModelSim
Note: In this design you can choose between two different simulators, the integrated ISE Simulator ISim from Xilinx and Mentor Graphic's ModelSim-SE. To learn how to switch and use the lSim Simulator, please see Chapter 2.5 Simulating (with ISim).
4. SINE-PACKAGE
4.1 Description
Usage: In our case we will make an VHDL package with a parametrized sine signal. Total of 28=256 unsigned amplitude values during one sine-period will be stored into an ROM array.
In order to simplify the generation of the PWM signal, we will use the sine wave signal that is shifted upwards. The value of this shift will be selected in a way to make all values of the sine signal positive. This is illustrated on the Drawing 4.1.

Drawing
4.1: Sine-package description
The formula for calculating the sine wave shown on the Drawing 4.1 is:
-
sin (2*pi*i / N) * (2width_c-1 - 1) + 2width_c-1 - 1, N = 2depth_c
depth_c - is the number of samples in one period of the signal (28=256)
width_c - is the number of bits used to represent amplitude value (212=4096)
This formula is defining the nature of the desired sine signal:
sin (2*pi*i / N) - is telling us that the signal is periodic, with 2*pi period; i is the current sample value (from 0 to 255) and N is the number of samples in one period of the signal
*(2width_c-1 -1) – is telling us that the amplitude of the sine signal is 2047
+ 2width_c-1 -1 – is telling us that the DC value of the sine signal is 2047, which means that the whole sine signal is shifted up
File name: modulator_pkg.vhd
4.2 Creating Module
To create a Sine-package module, use steps for creating modules, Chapter 3.2 Creating Module.
Sine-package VHDL model:
library ieee;
use ieee.math_real.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
package modulator_pkg is
type vector_t_arr is array (natural range <>) of integer;
function init_sin_f
(
constant depth_c : in integer; -- is the number of samples in one period of the signal (28=256)
constant width_c : in integer -- is the number of bits used to represent amplitude value (212=4096)
)
return vector_t_arr;
end;
package body modulator_pkg is
function init_sin_f
(
depth_c : in integer;
width_c : in integer
)
return vector_t_arr is
variable init_arr_v : vector_t_arr(0 to (2 ** depth_c - 1));
begin
for i in 0 to ((2 ** depth_c)- 1) loop -- calculate amplitude values
init_arr_v(i) := integer(round(sin((math_2_pi / real(2 ** depth_c))*real(i)) * (real(2 ** (width_c - 1)) - 1.0)))
+ integer(2 ** (width_c - 1) – 1);
end loop;
return init_arr_v;
end;
end;
5. DIGITAL SINE
5.1 Description
Usage: This module will generate an digital representation of an analog (sine) signal with desired frequency. It will use the counter values as addresses to fetch the next value of the sine wave from the ROM.
Note: Don't forget to include the Sine package in the code of the Digital sine module!
Block diagram:
Input signals:

Drawing 5.1: Digital Sine block diagram
- clk_in: 50 MHz input clock signal
- ampl_cnt: address value for the sine waveform ROM
Output signals:
- sine: current amplitude value of the sine signal
File name: sine_rtl.vhd
5.2 Creating Module
To create Digital Sine module, use steps for creating modules, Chapter 3.2 Creating Module.
Digital Sine VHDL model:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.modulator_pkg.all;
entity sine is
generic(
depth_g : integer range 1 to 99 := 8;
width_g : integer range 1 to 99 := 12
);
port(
ampl_cnt : in std_logic_vector(depth_g-1 downto 0); -- address value for the sine waveform ROM
clk_in : in std_logic; -- 50 MHz input clock signal
sine : out std_logic_vector(width_g-1 downto 0) -- current amplitude value of the sine signal
);
end;
architecture rtl of sine is
constant sin_ampl_c : vector_t_arr := init_sin_f(depth_g, width_g); -- returns sine amplitude value
signal ampl_cnt_s : integer range 0 to 255 := 0; -- amplitude counter
signal sine_s : std_logic_vector(width_g-1 downto 0) := (others=>'0'); -- sine
begin
sine_p : process -- fetch amplitude values and frequency - generates sine
begin
wait until rising_edge(clk_in);
ampl_cnt_s <= conv_integer(ampl_cnt); -- convert amplitude counter into integer
sine_s <= conv_std_logic_vector(sin_ampl_c(ampl_cnt_s), width_g); -- fetch amplitude
end process;
sine <= sine_s;
end;
6. DIGITAL SINE tOP
6.1 Description
Usage: This module will merge Frequency Trigger, Counter, Sine package and Digital Sine module in one Digital Sine Top module (Drawings 6.1 and 6.2). It will have two input signals: one will be global clock signal and the second one will be output signal from the Counter module. The only output signal will represent the current amplitude value of the desired sine signal.
Block diagram:

Drawing 6.1: Digital Sine Top block diagram

Drawing
6.2: Digital Sine Top detailed block diagram
Input signals:
- clk_in: 50 MHz input clock signal
- sw0_freq_sel: input signal from the on-board switch, used for changing output signal frequency
Output signals:
- sine_out: current amplitude value of the sine signal
File name: sine_top_rtl.vhd
6.2 Creating Module
To create Digital Sine Top module, use steps for creating modules, Chapter 3.2 Creating Module.
Digital Sine Top VHDL model:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.modulator_pkg.all;
entity sine_top is
generic(
cntampl_value_g : std_logic_vector := x"ff"; -- threshold value for counter
depth_g : integer range 1 to 99 := 8; -- the number of samples in one period of the signal
freqhigh_g : std_logic_vector (17 downto 0); -- threshold value of frequency a
freqlow_g : std_logic_vector (17 downto 0); -- threshold value of frequency b
width_g : integer range 1 to 99 := 12 -- the number of bits used to represent amplitude value
);
port(
clk_in : in std_logic; -- 50 MHz input clock signal
sine_out : out std_logic_vector(width_g-1 downto 0); -- current amplitude value of the sine signal
sw0_freq_sel : in std_logic --- signal used for selecting frequency
);
end;
architecture rtl of sine_top is
constant sin_ampl_c : vector_t_arr := init_sin_f(depth_g, width_g); -- returns sine amplitude value
signal ampl_cnt_s : std_logic_vector(depth_g-1 downto 0) := (others=>'0'); -- amplitude counter
signal freq_trig_s : std_logic := '0';
begin
counterampl : entity work.counter(rtl) -- generates amplitude values
generic map(
cnt_value_g => cntampl_value_g
)
port map (
clk_in => clk_in,
cnt_en => freq_trig_s,
cnt_out => ampl_cnt_s
);
freq_ce : entity work.freq_ce(rtl) -- generates frequency trigger
generic map(
freqhigh_g => freqhigh_g,
freqlow_g => freqlow_g
)
port map(
clk_in => clk_in,
freq_trig => freq_trig_s,
sw0_freq_sel => sw0_freq_sel
);
sine : entity work.sine(rtl) -- generates digital sine
generic map(
depth_g => depth_g,
width_g => width_g
)
port map(
ampl_cnt => ampl_cnt_s,
clk_in => clk_in,
sine => sine_out
);
end;
6.3 Creating Test Bench
Usage: used to verify correct operation of the sine_top module defined in the sine_top_rtl.vhd file
Test bench internal signals:
- clk_in_s: 50 MHz input clock signal
- sw0_freq_sel_s: input signal from the on-board switch, used for changing output signal frequency
- sine_out_s: current amplitude value of the sine signal
- cntampl_value_g: threshold value for counter
- depth_g: the number of samples in one period of the signal
- width_g: the number of bits used to represent amplitude value
- freqhigh_g: threshold value of frequency a
- freqlow_g: threshold value of frequency b
File name: sine_top_tb.vhd
We will now create a test bench for Digital Sine Top module (sine_top_tb.vhd) using the same steps as in creating counter_rtl.vhd module, explained in Chapter 3.2 Creating Module.
Digital Sine Top test bench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_unsigned.all;
entity sine_top_tb is
generic(
cntampl_value_g : std_logic_vector := x"ff"; -- threshold value for counter
depth_g : integer range 1 to 99 := 8; -- the number of samples in one period of the signal
freqhigh_g : std_logic_vector (17 downto 0) := b"00_0000_0000_1100_0011"; -- threshold value of frequency a
freqlow_g : std_logic_vector (17 downto 0) := b"00_0000_0000_0011_0111"; -- threshold value of frequency b
width_g : integer range 1 to 99 := 12 -- the number of bits used to represent amplitude value
);
end;
architecture tb of sine_top_tb is
constant per_c : time := 20 ns; -- clock period
signal clk_in_s : std_logic := '0'; -- 50 MHz input clock signal
signal sine_out_s : std_logic_vector(width_g-1 downto 0) := (others=>'0'); -- current amplitude value of the sine signal
signal sw0_freq_sel_s : std_logic := '0'; -- signal used for selecting frequency
begin
dut : entity work.sine_top -- fetch generic and port of sine_top_rtl.vhd
generic map(
cntampl_value_g => cntampl_value_g,
depth_g => depth_g,
freqhigh_g => freqhigh_g,
freqlow_g => freqlow_g,
width_g => width_g
)
port map(
clk_in => clk_in_s,
sine_out => sine_out_s,
sw0_freq_sel => sw0_freq_sel_s
);
clk_in_s <= not (clk_in_s) after per_c/2; -- 50 MHz input clock signal
sw0_freq_sel_s <= '0', '1' after 1 ms;
end;
6.4 Simulating
Choose your simulator:
ISIM (VHDL) (see Chapter 2.5 Simulating (with ISim))
ModelSim (see Chapter 3.4 Simulating (with ModelSim))
Simulate 4 ms
ISIM (VHDL) (see Chapter 2.5 Simulating (with ISim) – step 11)
ModelSim (see Chapter 3.4 Simulating (with ModelSim) – step 9)
Display digital as analog sine signal (this option is only available for ModelSim!)
Zoom In/Out to see all simulated signals
Right-click on sine_out_s
Select Format / Analog (see Illustration 6.1)

Illustration
6.1: Display analog sine – ModelSim
Format: Analog Step
Click Ok
Right-click on sine_out_s again
Select Radix / Unsigned (see Illustration 6.2)

Illustration
6.2: Change Radix to Unsigned
Assuming no errors, your simulation results should look similar to Illustrations 6.3 and 6.4.
Analog

Illustration
6.3: Analog representation of the sine signal – ModelSim
Digital

Illustration
6.4: Digital representation of the sine signal – ModelSim
6.5 Synthesize
Synthesize, checks code syntax and analyse the hierarchy of your design. This ensures that your design is optimized for the design architecture that you have selected (e.g. Number of Flip-Flops, LUTs, Clock- and IO-Buffers). The resulting netlist is saved to an Native Generic Circuit (NGC) file (for Xilinx® Synthesis Technology (XST) compiler) or an Electronic Design Interchange Format (EDIF) file (for Precision, or Synplify/Synplify Pro tools).
To synthesize your design, follow these steps:
In the Sources window, right-click on the synthesizable module (sine_top_rtl) and select Set as Top Module (see Illustration 6.5), if it is not already set.
In the Sources window, select synthesizable module (sine_top_rtl). In the Processes window, double-click on the Synthesize – XST (see Illustration 6.6).

Illustration
6.5: Set as Top Module

Illustration
6.6: Synthesize
Synthesize Report shows IO and logic resources usage. To view Synthesize Report:
Select Project / Design Summary/Reports
Select Detailed Reports / Synthesis Report
In the Synthesize Report you will find:
1) Synthesis Options Summary
2) HDL Compilation
3) Design Hierarchy Analysis
4) HDL Analysis
5) HDL Synthesis
5.1) HDL Synthesis Report
6) Advanced HDL Synthesis
6.1) Advanced HDL Synthesis Report
7) Low Level Synthesis
8) Partition Report
9) Final Report
9.1) Device Utilization Summary
9.2) Partition Resource Summary
9.3) Timing Report
RTL and Technology Schematic Viewers allow you to view a schematic representation of your synthesized netlist. These viewers help you to:
Analyse how components were inferred
Analyse timing paths
Identify issues and improve your design early in the design process
RTL Schematic Viewer
RTL Schematic Viewer allows you to view a schematic representation of the design in terms of generic symbols that are independent of the targeted Xilinx device, for example, in terms of adders, multipliers, counters, AND gates, and OR gates.
To use the RTL Schematic Viewer, follow these steps:
In the Sources window, left-click on the synthesizable module (sine_top_rtl), expand Synthesize and double-click on the View RTL Schematic
For creating a detailed RTL Schematic you have to add VHDL-file to the Selected Elements box and left-click on the Create Schematic, which is shown on the Illustrations 6.7, 6.8 and 6.9.

Illustration
6.7: Create RTL Schematic

Illustration
6.8: RTL Schematic of the Digital Sine Top module

Illustration
6.9: Detailed RTL Schematic of the Digital Sine Top module
Optional: If you want a more detailed logical view of your design, double-click on the schematic part to zoom-in
Optional:
If you want to return to the Top-Schematic, you should left-click on
the green arrow on the left side of your schematic
Technology Schematic Viewer
Technology Schematic Viewer allows you to view a schematic representation of the design in terms of logic elements optimized to the target Xilinx device or "technology," for example, in terms of LUTs, carry logic, I/O buffers, and other technology-specific components.
6.5.5 Checking Syntax
The Check Syntax process checks the syntax of the selected source file prior to generating a netlist of the design by synthesis or compile, or prior to running a simulation with ISim.
To see how to start Check Syntax process, please see Chapter 2.3 – step 7.
6.5.6 Generate Post-Synthesis Simulation Model
You can generate a simulation model after synthesizing your design. For this process, NetGen converts the synthesis output (NGC) to a simulation model (a structural UNISIM-based VHDL or Verilog file). The simulation model can be used to verify that the functionality is correct after synthesis by running a post-synthesis simulation in your simulator.
To Generate Post-Synthesis Simulation Model, follow these steps:
In the Processes window, expand Synthesize – XST
Right-click on the Generate Post-Synthesis Simulation Model / Process Properties, write in the “Rename Top Level Architecture To” filed rtl, and click Ok
Note: Verify that the Advanced Property Display Level is enabled in the Process Properties dialog box (see Illustration 6.10).

Illustration
6.10: Process Properties – Simulation Model Properties
At the end, double-click on the Generate Post-Synthesis Simulation Model (see Illustration 6.11)
Illustration 6.11: Generate Post-Synthesis Simulation Model
7. PWM
7.1 Description
Usage: This module will generate an PWM signal modulated using the digital sine wave from the Digital Sine module. This module will be composed of two independent modules. One will be the Frequency Trigger, for generating two different frequencies and the second one will be the Finite State Machine (FSM), for generating the PWM signal.
Frequency Trigger module is the same module explained as in Chapter 2.
FSM module will generate the PWM signal. It will generate the PWM signal with correct duty cycle for each period based on the current amplitude value of digital sine signal, that is stored in the ROM. State diagram of the FSM is shown on the Drawing 7.2.
Block diagram:

Drawing 7.1: PWM block diagram

Drawing 7.2: FSM state diagram
Input signals:
- clk_in: 50 MHz input clock signal
- sw0_freq_sel: input signal from the on-board switch, used for changing output signal frequency
- sine_ampl: current amplitude value of the sine signal
Output signals:
- pwm: pulse width modulated signal
File name: pwm_rtl.vhd
7.2 Creating Module
To create PWM module, use steps for creating modules, Chapter 3.2 Creating Module.
PWM VHDL model:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity pwm is
generic(
width_g : integer range 1 to 99 := 12; -- the number of bits used to represent amplitude value
freqhigh_g : std_logic_vector (17 downto 0) := (others=>'0'); -- input clock division when sw0_freq_sel = '1'
freqlow_g : std_logic_vector (17 downto 0) := (others=>'0') -- input clock division when sw0_freq_sel = '0'
);
port(
clk_in : in std_logic; -- 50 MHz input clock signal
sw0_freq_sel : in std_logic; -- signal made for selecting frequency
sine_ampl : in std_logic_vector(width_g-1 downto 0); -- current amplitude value of the sine signal
pwm : out std_logic -- pulse width modulated signal
);
end;
architecture rtl of pwm is
type state_type is (s0,s1,s2);
signal state: state_type ;
signal ce_s : std_logic := '0'; -- clock enable signal for the fsm
begin
process1: process (clk_in)
variable treshold : integer range 0 to 4095 := 0;
variable count : integer range 0 to 4095 := 0;
begin
if (clk_in = '1' and clk_in'event) then
if (ce_s = '1') then
case state is
when s0 =>
treshold := conv_integer (sine_ampl);
count := 0;
if (sine_ampl > 0) then
state <= s1;
elsif (sine_ampl = 0) then
state <= s2;
end if;
when s1 =>
count := count + 1;
if (count < 4095 and count < treshold) then
state <= s1;
elsif (count = 4095) then
state <= s0;
elsif (count < 4095 and count = treshold) then
state <= s2;
end if;
when s2 =>
count := count + 1;
if (count < 4095) then
state <= s2;
elsif (count = 4095) then
state <= s0;
end if;
end case;
end if;
end if;
end process process1;
process2 : process (state)
begin
case state is
when s0 => pwm <= '0';
when s1 => pwm <= '1';
when s2 => pwm <= '0';
end case;
end process process2;
fsm_ce: entity work.frequency_trigger(rtl) -- instance of the frequency trigger
generic map (
freqhigh_g => freqhigh_g,
freqlow_g => freqlow_g
)
port map (
clk_in => clk_in,
sw0_freq_sel => sw0_freq_sel,
freq_trig => ce_s
);
end;
7.3 Creating Test Bench
Usage: used to verify correct operation of the PWM module defined in the pwm_rtl.vhd file
Test bench internal signals:
- clk_in_s: 50 MHz input clock signal
- sw0_freq_sel_s: input signal from the on-board switch, used for changing output signal frequency
- sine_out_s: current amplitude value of the sine signal
- cntampl_value_g: threshold value for counter
- depth_g: the number of samples in one period of the signal
- width_g: the number of bits used to represent amplitude value
- freqhigh_g: threshold value of frequency a
- freqlow_g: threshold value of frequency b
File name: pwm_tb.vhd
We will now create a test bench for PWM module (sine_top_tb.vhd) using the same steps as in creating counter_rtl.vhd module, explained in Chapter 3.2 Creating Module.
PWM test bench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_unsigned.all;
entity pwm_tb is
generic(
cntampl_value_g : std_logic_vector := x"ff"; -- threshold value for counter
depth_g : integer range 1 to 99 := 8; -- the number of samples in one period of the signal
width_g : integer range 1 to 99 := 12 -- the number of bits used to represent amplitude value
);
end;
architecture tb of pwm_tb is
constant per_c : time := 20 ns; -- clock period
signal clk_in_s : std_logic := '0'; -- 50 MHz input clock signal
signal sine_out_s : std_logic_vector(width_g-1 downto 0) := (others=>'0'); -- current amplitude value of the sine signal
signal sw0_freq_sel_s : std_logic := '0'; -- signal made for selecting frequency
begin
dut1 : entity work.sine_top -- fetch generic and port of sine_top_rtl.vhd
generic map(
cntampl_value_g => cntampl_value_g,
depth_g => depth_g,
freqhigh_g => "001010000000000000", -- 40960=10*4096
freqlow_g => "010100000000000000", -- 81920=20*4096
width_g => width_g
)
port map(
clk_in => clk_in_s,
sine_out => sine_out_s,
sw0_freq_sel => sw0_freq_sel_s
);
dut2 : entity work.pwm
generic map(
width_g => width_g,
freqhigh_g => "000000000000001010", -- 10
freqlow_g => "000000000000010100" -- 20
)
port map(
clk_in => clk_in_s,
sw0_freq_sel => sw0_freq_sel_s,
sine_ampl => sine_out_s
);
clk_in_s <= not (clk_in_s) after per_c/2; -- 50 MHz input clock signal
sw0_freq_sel_s <= '0', '1' after 1 ms;
end;
7.4 Simulating
Choose your simulator:
ISIM (VHDL) (see Chapter 2.5 Simulating (with ISim))
ModelSim (see Chapter 3.4 Simulating (with ModelSim))
Simulate 100 ms
ISIM (VHDL) (see Chapter 2.5 Simulating (with ISim) – step 11)
ModelSim (see Chapter 3.4 Simulating (with ModelSim) – step 9)
Assuming no errors, your simulation result should look similar to Illustration 7.1.

Illustration
7.1: Simulation Results – ISim
8. MODULATOR
8.1 Description
Usage: This module will merge all the previously designed modules.
Block diagram:

Drawing 8.1: Modulator block diagram
Input signals:
- clk_in: 50 MHz input clock signal
- sw0_freq_sel: input signal from the on-board switch, used for changing output signal frequency
Output signals:
- pwm: pulse width modulated signal
File name: modulator_rtl.vhd
8.2 Creating Module
To create Modulator module use steps for creating modules, Chapter 3.2 Creating Module.
Modulator VHDL model:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_unsigned.all;
library unisim;
use unisim.vcomponents.all;
entity modulator is
generic(
cntampl_value_g : std_logic_vector := x"ff"; -- clk counter amplitude border
depth_g : integer range 1 to 99 := 8; -- the number of samples in one period of the signal
freqhigh_g : std_logic_vector (17 downto 0) := b"110000000000000000"; -- threshold value of frequency a =196608
freqlow_g : std_logic_vector (17 downto 0) := b"001110000000000000"; -- threshold value of frequency b = 57344
width_g : integer range 1 to 99 := 12 -- the number of bits used to represent amplitude value
);
port(
clk_in : in std_logic; -- 50 MHz input clock signal
sw0_freq_sel : in std_logic; -- signal made for selecting frequency
pwm : out std_logic -- pulse width modulated signal
);
end;
architecture rtl of modulator is
signal ampl_cnt_s : std_logic_vector (depth_g-1 downto 0); -- amplitude counter
signal sine_ampl_s : std_logic_vector (width_g-1 downto 0); -- current amplitude value of the sine signal
signal freq_trig_s : std_logic := '0'; -- signal which frequency dipends on the sw0_freq_sel state
begin
freq_ce : entity work.frequency_trigger(rtl) -- generates frequency trigger
generic map(
freqhigh_g => freqhigh_g,
freqlow_g => freqlow_g
)
port map(
clk_in => clk_in,
freq_trig => freq_trig_s,
sw0_freq_sel => sw0_freq_sel
);
counterampl : entity work.counter(rtl) -- generates amplitude values
generic map(
cnt_value_g => cntampl_value_g
)
port map (
clk_in => clk_in,
cnt_en => freq_trig_s,
cnt_out => ampl_cnt_s
);
sine : entity work.sine(rtl) -- generates digital sine
generic map(
depth_g => depth_g,
width_g => width_g
)
port map(
ampl_cnt => ampl_cnt_s,
clk_in => clk_in,
sine => sine_ampl_s
);
pwmmodule : entity work.pwm (rtl) -- generates pwm signal
generic map (
width_g => width_g,
freqhigh_g => "000000000000"&freqhigh_g (17 downto 12), --freqhigh_g / 4096
freqlow_g => "000000000000"&freqlow_g (17 downto 12) --freqlow_g / 4096
)
port map (
clk_in => clk_in,
sw0_freq_sel => sw0_freq_sel,
sine_ampl => sine_ampl_s,
pwm => pwm
);
end;
8.3 Creating Test Bench
Usage: used to verify correct operation of the Modulator module defined in the modulator_rtl.vhd file
Test bench internal signals:
- clk_in_s: 50 MHz input clock signal
- sw0_freq_sel_s: input signal from the on-board switch, used for changing output signal frequency
- sine_out_s: current amplitude value of the sine signal
- pwm_s: pulse width modulated signal
- depth_g: the number of samples in one period of the signal
- width_g: the number of bits used to represent amplitude value
- freqhigh_g: threshold value of frequency a
- freqlow_g: threshold value of frequency b
File name: modulator_tb.vhd
We will now create a test bench for Modulator module (modulator_tb.vhd) using the same steps as in creating counter_rtl.vhd module, explained in Chapter 3.2 Creating Module.
Modulator test bench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_unsigned.all;
entity modulator_tb is
generic(
depth_g : integer range 0 to 99 := 8; -- the number of samples in one period of the signal
width_g : integer range 0 to 99 := 12; -- the number of bits used to represent amplitude value
freqhigh_g : std_logic_vector (17 downto 0) := b"110000000000000000"; -- threshold value of frequency a = 196608
freqlow_g : std_logic_vector (17 downto 0) := b"001110000000000000" -- threshold value of frequency b = 57344
);
end;
architecture tb of modulator_tb is
constant per_c : time := 20 ns; -- clock period
signal clk_in_s : std_logic := '1'; -- 50 MHz input clock signal
signal sw0_freq_sel_s : std_logic := '1'; -- signal made for selecting frequency
signal pwm_s : std_logic := '0'; -- pulse width modulated signal
begin
pwmmodulator : entity work.modulator -- fetch generics and ports of modulator_rtl.vhd
generic map(
width_g => width_g,
freqhigh_g => freqhigh_g,
freqlow_g => freqlow_g
)
port map(
clk_in => clk_in_s,
sw0_freq_sel => sw0_freq_sel_s,
pwm => pwm_s
);
clk_in_s <= not (clk_in_s) after per_c/2; -- generates 50 MHz input clock signal
sw0_freq_sel_s <= '1', '0' after 25 us;
end;
8.4 Simulating
Choose your simulator:
ISIM (VHDL) (see Chapter 2.5 Simulating (with ISim))
ModelSim (see Chapter 3.4 Simulating (with ModelSim))
Simulate 100 ms
ISIM (VHDL) (see Chapter 2.5 Simulating (with ISim) – step 11)
ModelSim (see Chapter 3.4 Simulating (with ModelSim) – step 9)
Assuming no errors, your simulation result should look similar to Illustration 8.1.

Illustration
8.1: Simulation Results
8.5 Creating UCF-File
The ISE software allows you to specify different types of constraints to help improve your design performance. Each type of constraint serves a different purpose and is recommended under different circumstances. Following are some of the most commonly used types of constraints:
Timing Constrains – are typically specified globally but can also be specified for individual paths. Global constraints include period constraints for each clock, setup times for each input, and clock-to-out constraints for each output. You can enter timing constraints using the Create Timing Constraints process in Project Navigator. This creates a text-based User Constraints File (UCF).
Placement Constraints - for FPGA designs, you can specify placement constraints for each type of logic element, such as BRAMs, DSPs, LUTs, FFs, I/Os, IOBs, and global buffers. Individual logic gates, such as AND and OR gates, are mapped into CLB function generators before the constraints are read and cannot be constrained. For CPLD designs, you can specify placement constraints for macrocells, for function blocks, and for I/Os.
Synthesis Constraints - Synthesis constraints instruct the synthesis tool to perform specific operations. When using XST for synthesis, synthesis constraints control how XST processes and implements FPGA resources, such as state machines, multiplexers, and multipliers, during the HDL synthesis and low level optimization steps. Synthesis constraints also allow control of register duplication and fanout control during global timing optimization.
Note: To learn more about UCF Constraints, please see Xilinx's “Constraints Guide” document.
There are two different ways of generating an UCF-File:
by Wizard (PlanAhead-Floorplanner Wizard)
by Text Editor
For creating through the PlanAhead-Floorplanner Wizard (see Chapter 8.6):
If necessary, select Implementation from the “Sources for” drop-down list
Select the top modulator file (modulator_rtl.vhd) in the Sources window
Select Project / New Source
In the New Source dialog box, select Implementation Constraints File, enter module_name_ucf (modulator_rtl) in the File name field an click Next (see Illustration 8.2)

Illustration
8.2: Select Source Type dialog box
Click Finish
If necessary, select again the top modulator file (modulator_rtl.vhd) in the Sources window
In the Processes window, expand User Constraints and double-click on the I/O Pin Planning (PlanAhead) – Pre-Synthesis (see Illustration 8.3).

Illustration
8.3: Constraint Editor
When the PlanAhead is opened, in the I/O Ports window (below the colored chip graphic), expand Scalar ports, which shows all I/O Ports of your design (see Illustration 8.4).

Illustration
8.4: I/O Ports
For connecting your logical with your physical ports, select one scalar port (for example pwm)
Insert the Port Mark (for pwm it is P11) into the Site field of the popped up I/O Port Properties window (see Illustration 8.5).

Illustration
8.5: I/O Port Properties
For further configuration left-click on the Configure button bellow the Site field and fill out the needed port configurations as shown on the Illustration 8.6.

Illustration
8.6: Port configuration
Click Apply to save your port configuration
Repeat these configuration steps for all ports using the port map information from “Creating through Text Editor”
For creating through Text Editor, follow these steps:
Open any text editor (for better usability take one with VHDL code support)
Insert the ucf constraints from below
Save the file as module_name (e.g. modulation_rtl) into your working directory
Change the ending from *.txt to *.ucf
Optional: Launch Project Navigator (if it is not already open)
Optional: Open “Modulator” project (modulator.xise)(if it is not already open)
If necessary, select Implementation from the “Sources for” drop-down list
Select the top modulator file (modulator_rtl.vhd) in the Sources window
Select Project / Add Source
Select module file (e.g. modulation_rtl.ucf)
Click Ok
ucf constraints:
NET "clk_in" LOC = "C9" | IOSTANDARD = LVCMOS33;
NET "sw0_freq_sel" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP;
NET "pwm" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;
Note: Put a pin location where you want to route the PWM signal.
8.6 PlanAhead-Floorplanner
Floorplanner™ is an interactive graphical tool that you can use to improve the performance of your design by constraining critical paths or adjusting the automatic placement. Floorplanner perform the following functions on your designs:
Doing detailed-level floorplanning
Creating an Relationally Placed Macro (RPM) core that can be used in other designs
Viewing and editing location constraints (see Chapter 8.5 - with the PlanAhead Wizard)
Finding logic or nets by name or connectivity
Cross probing from the Timing Analyzer to the Floorplanner
Placing ports automatically for modular design (part of a design)
The graphical user interface includes pull-down menus and toolbar buttons that contain the necessary commands for changing the design hierarchy, floorplanning, and performing design rule checks. Dialog boxes allow you to set parameters and options for command execution.
Note: For more informations and instructions please read in the Floorplanner Help.
8.7 Implementation/Translation
Translate, merges all of the input netlists and design constraints and outputs a Xilinx Native Generic Database (NGD) file, which describes the logical design reduced to Xilinx primitives.
ISE Translate Utility: NGD Builde
To run the translation step, please do the following:
In the Sources window, right-click on the translateable module (modulator_rtl) and select Set as Top Module, if it is not already set
In the Sources window, select the translateable module (modulator_rtl). In the Processes window, expand Implement Design and double-click on the Translate option, Illustration 8.7.

Illustration
8.7: Translate Modulator module
Translation Report displays NGDBUILD Design Results Summary.
To see Translation Report:
Select Project / Design Summary/Reports
Select Detailed Reports / Translation Report
NetGen converts the Translate process output (an NGD file) to a post-translate simulation model (a structural SIMPRIM-based VHDL and Verilog file). This model is then used in the Simulate Post-Translate Model process to verify that design functionality is correct after the translation stage as the input file for your simulator.
To Generate Post-Translate Simulation Model, follow these steps:
In the Processes window, expand Implement Design / Translate
Right-click on the Generate Post-Translate Simulation Model / Process Properties, write in the “Rename Top Level Architecture To” field rtl, and click Ok
Note: Verify that the Advanced Property Display Level is enabled in the Process Properties dialog box (see Illustration 8.8).

Illustration
8.8: Process Properties – Simulation Model Properties
At the end, double-click on the Generate Post-Translate Simulation Model

Illustration
8.9: Generate Post-Translate Simulation Model
8.8 Implementation/Map
The Map process maps the design specified by an NGD file into available resources on the target FPGA device, such as Flip-Flops, CLBs, IOBs... As a result is an Native Circuit Description (NCD) file.
To run the mapping step, please do the following:
In the Sources window, right-click on the mapping module (modulator_rtl) and select Set as Top Module, if it is not already set
In the Sources window, select the mapping module (modulator_rtl). In the Processes window, expand Implement Design and double-click on the Map (see Illustration 8.10).

Illustration
8.10: Map Modulator module
Map Report shows Design Information and Design Summary. In the Design Summary, INFO or WARNING messages indicate correct design setup.
To see Map Report:
Select Project / Design Summary/Reports
Select Detailed Reports / Map Report
In the Map Report / Design Summary, you will find:
Section 1 - Errors
Section 2 - Warnings
Section 3 - Informational
Section 4 - Removed Logic Summary
Section 5 - Removed Logic
Section 6 - IOB Properties
Section 7 - RPMs
Section 8 - Guide Report
Section 9 - Area Group and Partition Summary
Section 10 - Modular Design Summary
Section 11 - Timing Report
Section 12 - Configuration String Information
Section 13 - Control Set Information
Section 14 - Utilization by Hierarchy
You can optionally generate a post-map static timing report for your design. A post-map timing report lists the signal path delays in your design, derived from the design logic. This report can be useful in evaluating timing performance of the logic paths, particularly if your design does not meet timing requirements.
Although route delays are not accounted for in this report, the logic delays can provide valuable information about the design, which can help identify problems with logic path timing. You can eliminate potential problems before investing time in examining routing delays. To eliminate problems, you may choose to redesign the logic paths to use fewer levels of logic, tag the paths for specialized routing resources, move to a faster device, or allocate more time for the path.
To Generate Post-Map Static Timing, follow these steps:
In the Processes window, expand Implement Design / Map
Right-click on the Generate Post-Map Static Timing / Process Properties and make the appropriate selections for the report details
At the end, double-click on the Generate Post-Map Static Timing (see Illustration 8.11)

Illustration
8.11: Generate Post-Map Static Timing
After running this process, you can run the Analyze Post-Map Static Timing process to open the static timing report and your design NCD file for further timing analysis in Timing Analyzer.
You can use Timing Analyzer to perform static timing analysis on mapped, placed only or placed and routed FPGA designs.
Timing Analyzer:
reports path delay and the slack based upon the specified timing requirements.
analyze critical paths in a circuit,
the cycle time of the circuit,
quick analysis of the effect speed grades, voltage, and temperature prorating have on the same design
set up and hold checks (works with synchronous systems comprising synchronous elements and combinatorial logic)
creates timing analysis reports based on timing constraints or user-specified paths within the program.
uses Timing Wizard for all FPGA analysis functions, ensuring consistency with PAR
Note: For more information and instructions please read in the Timing Analyzer Help
You can use FPGA Editor to manually place and route critical components of your design before running the Place & Route process. After running the Map process, the output design is a Native Circuit Description (NCD) file that physically represents the design mapped to components of the Xilinx FPGA, such as CLBs and IOs. The FPGA Editor requires an NCD file as input.
Note: Manually routing sections of the design is not recommended unless absolutely necessary.
FPGA Editor launches and displays the routed design NCD file. FPGA Editor reads from and writes to a physical constraints file (PCF) as follows:
When you create a constraint in FPGA Editor , the constraint is written to the PCF file whenever you save your design.
When you delete a constraint in FPGA Editor and then save the design file, the constraint is commented out in the PCF file and is not removed.
Note: For more information on using FPGA Editor, see the FPGA Editor Help.
To Manually Place and Route a design:
In the Processes window, expand Implement Design / Map
Double-click on the Manually Place & Route (FPGA Editor) (see Illustration 8.12).

Illustration
8.12: Manually Place&Route (FPGA Editor)
The following is a list of a few functions you can perform on your design in the FPGA Editor.
Place and route critical components before running the automatic place and route tools.
Finish placement and routing if the routing program does not completely route your design.
Add probes to your design to examine the signal states of the targeted device. Probes are used to route the value of internal nets to an IOB for analysis during the debugging of a device.
Cross-probe your design with Timing Analyzer.
Run the BitGen program and download the resulting BIT file to the targeted device.
View and change the nets connected to the capture units of an ILA core in your design.
Create an entire design by hand (advanced users).
You can generate a simulation model after mapping your design. For this process, NetGen converts the output of the Map process (an NCD file) to a post-map simulation model (a structural SIMPRIM-based VHDL or Verilog file) and a standard delay format (SDF) file. The SDF file contains estimates of the timing delays in your design. The simulation model and SDF files are then used in the Simulate Post-Map Model process to verify that functionality is correct at this stage of implementation.
To Generate Post-Map Simulation Model:
In the Process window, expand Implement Design / Map
Right-click on the Generate Post-Map Simulation Model / Process Properties, write in the “Rename Top Level Architecture To” field rtl, and click Ok
Note: Verify that the Advanced Property Display Level is enabled in the Process Properties dialog box (see Illustration 8.13)

Illustration
8.13: Process Properties – Simulation Model Properties
At the end, double-click on the Generate Post-Map Simulation Model

Illustration
8.14: Generate Post-Map Simulation Model
8.9 Implementation/Place&Route
The Place and Route process takes a mapped Native Circuit Description (NCD) file, places and routes the design, and produces an NCD file that is used as input for bitstream generation.
To run the place&route step, please do the following:
In the Sources window, right-click on the place&route module (modulator_rtl) and select Set as Top Module, if it is not already set
In the Sources window, select the place&route module (modulator_rtl). In the Processes window, expand Implement Design and double-click on the Place&Route (see Illustration 8.15).

Illustration
8.15: Place&Route Modulator module
Lists which resources in the device were utilized to implement the design, lists all clocks used in the design, and details design performance against timing constraints.
To see Place & Route Report:
Select Project / Design Summary/Reports
Select Detailed Reports / Place and Route Report
After placing and routing your design, this process generates a post-place and route static timing report. A post-place and route static timing report incorporates timing delay information to provide a comprehensive timing summary of your design. You can customize the report contents to help you determine how well your design has met the timing requirements.
If a placed and routed design has met all of your timing constraints, then you can create configuration data. If you identify problems in the timing report, you can redesign the logic paths to use fewer levels of logic, tag the paths for a specialized routing resources, move to a faster device, or allocate more time for the paths.
You can generate one of two report types:
Error report, which lists timing errors and associated net and path delay information.
Verbose report, which lists delay information for all nets and paths.
To Generate Post-Place & Route Static Timing, follow these steps:
In the Processes window, expand Implement Design / Place & Route
Right-click on the Generate Post-Place & Route Static Timing / Process Properties and make the appropriate selections for the report details
At the end, double-clock on the Generate Post-Place & Route Static Timing (see Illustration 8.16)

Illustration
8.16: Generate
Post-Place & Route Static Timing
You can open the static timing report and the NCD file for further timing analysis in Timing Analyzer.
To Analyze Post-Place & Route Static Timing:
In the Processes window, expand Implement Design / Place & Route
After that, expand Generate Post-Place & Route Static Timing
At the end, double-click on the Analyze Post-Place & Route Static Timing (see Illustration 8.17)

Illustration
8.17: Analyze Post-Place & Route Static Timing
You can also generate and view a static timing netlist from your placed and routed design. To Generate a Primetime Netlist:
In the Processes window, expand Implement Design / Place & Route
After that, expand Generate Post-Place & Route Static Timing
At the end, double-click on the Generate Primetime Netlist (see Illustration 8.18)

Illustration
8.18: Generate Primetime Netlist
Project Navigator reruns the processes necessary update the design files before it generates a PrimeTime netlist. You can open the generated netlist or view the PrimeTime static priming report in Synopsys PrimeTime Timing Analyzer.
To read more about Plan-Ahead-Floorplanner, please see Chapter 8.6. PlanAhead-Floorplanner).
To Analize Timing / Floorplan Design (PlanAhead):
In the Processes window, expand Implement Design / Place & Route
Double-click on the Analyze Timing / Floorplan Design (PlanAhead) (see Illustration 8.19)

Illustration
8.19: Analyze Timing / Floorplan Design (PlanAhead)
You can view or edit your routed design in FPGA Editor to fine tune your design or to improve the performance of the automatic place and route tools. After placing and routing your design, the Native Circuit Description (NCD) output file can be viewed or edited in FPGA Editor.
To read more about FPGA Editor, please see Chapter 8.8.5 Manually Place&Route (FPGA Editor).
To View/Edit Routed Design (FPGA Editor):
In the Processes window, expand Implement Design / Place & Route
Double-click on the View/Edit Routed Design (FPGA Editor) (see Illustration 8.20)

Illustration
8.20: View/Edit Routed Design (FPGA Editor)
Use the XPower Analyzer interactive graphic tool to perform the following functions on your design:
Analyze Power consumption for Xilinx FPGA and CPLD devices
Report thermal information (junction temperature)
Report static and dynamic power for the different voltage supplies
Validate the accuracy of the estimation given in Xilinx Power Estimator
Analyze power data supplied by hierarchical power reporting
Examine the data for areas where power can be reduced
Generate design power consumption reports and add them to the overall project documentation
To open XPower Analizer:
In the Processes window, expand Implement Design / Place & Route
Double-click on the XPower Analizer (see Illustration 8.21)

Illustration
8.21: XPower Analyzer
You can optionally generate power data for your entire design or for one module in your design. Power data provides measurements about the usage of voltage and other power resources.
To Generate Power Data:
In the Processes window, expand Implement Design / Place & Route
Double-click on the Generate Power Data (see Illustration 8.22)

Illustration
8.22: Generate Power Data
You can generate a simulation model after placing and routing your design. For this process, NetGen converts the Place & Route process results (an NCD file) to the simulation model (a structural SIMPRIM-based VHDL or Verilog file) and a standard delay format (SDF) file. The SDF file contains true timing delay information for your design. The simulation model file and SDF file can be used to verify the functionality and timing of your design at this point in the design flow by using the Simulate Post-Place and Route Model process.
To Generate Post-Place & Route Simulation Model:
In the Processes window, expand Implement Design / Place & Route
Right-click on the Generate Post-Place & Route Simulation Model / Process Properties, write in the “Rename Top Level Architecture To” field rtl, and click Ok
Note: Verify that the Advanced Property Display Level is enabled in the Process Properties dialog box (see Illustration 8.23)

Illustration
8.23: Process properties – Simulation Model Properties
At the end, double-click on the Generate Post-Place & Route Simulation Model (see Illustration 8.24)

Illustration
8.24: Generate Post-Place & Route Simulation Model
You can generate an Input Output Buffer Information Specification (IBIS) file that contains a pin list and models that are unique to your design. IBIS is a device modelling standard that allows for the development of behavioral models used to describe the signal behavior of device I/Os, while preserving proprietary circuit information.
The IBIS models can be used for the following:
To model Best and worst case models by using min, max current with the proper min, max ramp rates.
To simulate and predict electrical performance by providing I/V and V/T characteristics of the I/Os.
The IBIS Writer tool, the tool that generates the model, requires a design source file as input:
For FPGA designs, the design source is a physical description of the design in a Native Circuit Description (NCD) file with an .ncd file extension.
For CPLD designs, the input is produced by the CPLD fitter tools and has a .pnx file extension.
To Generate IBIS Model:
In the Processes window, expand Implement Design / Place & Route
Right-click on the Generate IBIS Model / Process Properties and make the appropriate selections (verify that the Advanced Property Display Level is enabled) (see Illustration 8.25)

Illustration
8.25: Process Properties: IBIS Model Generation Properties
At the end, double-click on the Generate IBIS Model (see Illustration 8.26)

Illustration
8.26: Generate IBIS
After running this process, you can do either of the following:
View the generated IBIS model
Read the IBIS model file into a signal integrity simulation tool for further simulation and analysis.
To View IBIS Model:
In the Processes window, expand Implement Design / Place & Route
After that, expand Generate IBIS Model
At the end, double-click on the View IBIS Model (see Illustration 8.27)

Illustration
8.27: View IBIS Model
You can run the Back-annotate Pin Locations process after you implement your design. The Back-annotate Pin Locations process runs the PIN2UCF program which back-annotates pin locking constraints from a successfully placed and routed FPGA design to a User Constraints File (UCF). This process extracts pin locations and logical pad names from the NCD file and writes this information to an existing UCF. If a UCF does not exist in your project, a new file is created.
Note: By default, PIN2UCF does not write conflicting constraints to a UCF. If user-specified constraints are exact matches of PIN2UCF generated constraints, a pound sign (#) is added in front of all matching user-specified location constraint statements. If PIN2UCF discovers conflicting constraints, it writes this information to the pinlock.rpt report file.
To Back-annotate Pin Locations:
In the Processes window, expand Implement Design / Place & Route
Double-click on the Back-annotate Pin Locations (see Illustration 8.28)

Illustration
8.28: Back-annotate Pin Locations
After running this process, you can perform any of the following:
View the back-annotate pin report
Generate Post-Place & Route Static Timing
Run Generate Programming File
To View Locked Pin Constraints:
In the Processes window, expand Implement Design / Place & Route
After that, expand Back-annotate Pin Locations
At the end, double-click on the View Locked Pin Constraints (see Illustration 8.29)

Illustration
8.29: View Locked Pin Constraints
8.10 Generate Programming File
You can run the Generate Programming File process after your design has been completely fitted (for CPLDs) or routed (for FPGAs). The Generate Programming File process produces a bitstream for Xilinx device configuration. After the design is completely routed, you must configure the device to execute the desired function.
To run the Generate Programming File process:
In the Sources window, right-click on the programming module (modulator_rtl) and select Set as Top Module, if it is not already set
In the Sources window, select programming module (modulator_rtl). In the Processes window double-click on the Generate Programming File (see Illustration 8.30).

Illustration
8.30: Generating Programming File for the Modulator module
Generate Programming File Report provides information about the results of the BIT file generation process, including a list of the property options and any warnings or errors that occurred.
To see Bitgen Report:
Select Project / Design Summary/Reports
Select Detailed Reports / Bitgen Report
8.11 Configure Target Device
The Configure Target Device process uses the output from the Generate Programming File process, a BIT, JEDEC, or ISC file to configure or program your target device. The target device can be any of the following:
FPGA - The BIT and ISC files contain all of the configuration information from the NCD file, which defines the internal logic and interconnections of the device, plus device-specific information from other files associated with the target device.
CPLD - The JEDEC and ISC files contain all of the necessary configuration information from the design database. The data from the JEDEC or ISC files is downloaded to the CPLD device.
PROM or Flash configuration device – Used to configure FPGAs, the configuration information in the BIT or ISC file is used to create a PROM file. The data from the PROM file then programs the PROM or Flash device.
To Configure Target Device:
In the Sources window, select programming module (modulator_rtl)
In the Processes window, expand Configure Target Device and double-click on the:
Generate Target PROM/ACE File, or
Manage Configuration Project (iMPACT)
The Generate Target PROM/ACE File process runs iMPACT in the background to generate the target PROM or ACE file. The file is generated according to the settings in an iMPACT project (.ipf) file saved from an iMPACT session.
Note: Alternatively, you can generate a target PROM or ACE file when you run the Configure Target Device process. By setting the automatically run Generate Target PROM/ACE File process property for the Configure Target Device process, a PROM or ACE file is generated each time the Configure Target Device Process is run.
To Generate Target PROM/ACE File:
In the Sources window, select programming module (modulator_rtl).
In Processes window, expand Configure Target Device and double-click on the Generate Target PROM/ACE File (see Illustration 8.31).

Illustration
8.31: Generate Target PROM/ACE File
Generating PROM Programming File
To generate PROM programming file, please follow these steps:
Double-click on the PROM File Formatter in the iMPACT Flows window
Select
Xilinx
Flash/PROM
in the Step 1. “Select Storage Target” and left-click on
the green
arrow
Select
Auto
Select PROM
(for beginners) in the Step 2. “Add Storage Device(s)”
and left-click on the second green
arrow
Type file name (modulator) in the File Name Field in the Step 3. “Enter Data”, check if the File Location is your working directory and the File Format is set to MCS (see Illustration 8.32)

Illustration
8.32: PROM File Formatter
Click Ok at the bottom of the window
Click Ok to start adding device file to Data Stream
Open the modulator.bit file from the modulator directory
If necessary, you can add another device file to the PROM File Formatter by repeating the previous steps.
After you have included all device files, you can generate PROM file by clicking on the “Generate File” option in the iMPACT Processes window.
Generating ACE Programming File
The ACE file is a programming file for the System ACE CF family. System ACE CF is a two-chip solution that requires the System ACE CF controller, and either a CompactFlash card on one-inch Microdrive disk drive technology as the storage medium. System ACE CF has a built-in microprocessor interface to coordinate FPGA configuration directly with system requirements.
To generate ACE programming file, please follow these steps:
Double-click on the SystemACE in the iMPACT Flows window
Choose between Novice and Expert Operating Mode in Prepare System ACE Files dialog box and click Next
Select System ACE CF Size and Reserve Space for configuration files in the System ACE Compact Flash Size dialog box and click Next
Specify Collection Name and Location in the System ACE Name and Location dialog box and click Next
Assign Configuration Address and Design Name in the System ACE Configuration Address And Design dialog box and click Next
Check the entered information in the System ACE File Generation Summary dialog box and if you are satisfied, click Finish to start adding device files
Click Ok to start assigning device configuration files
Open the modulator.bit file from the modulator directory
Add any other device configuration files
After you have included all device files, you can generate ACE file by clicking on the “Generate File” option in the iMPACT Processes window.
Note: The used Spartan-3E demo board has no CompactFlash card slot.
8.11.2 Manage Configuration Project (iMPACT)
The Manage Configuration Project (iMPACT) process opens iMPACT, the tool that allows you to perform device configuration and configuration device file generation. iMPACT uses the output from the Generate Programming File process a BIT, JEDEC, or ISC file, to configure your target device or to create the following types of programming files: System ACE CF, PROM, SVF, SXVF, and STAPL files.
To Manage Configuration Project (iMPACT):
In the Sources window, select programming module (modulator_rtl).
In the Processes window, expand Configure Target Device and double-click on the Manage Configuration Project (iMPACT) (see Illustration 8.33).

Illustration
8.33: Manage Configuration Project (iMPACT)
8.12 Programming
Instead of programming the device by following the steps explained in the Chapter 8.11: Configure Target Device, you can start iMPACT independently:
Connect the JTAG download cable
Power on the Spartan-3E Demoboard
Launch iMPACT
Click Cancel (do not open an existing project)
Double-click on the Boundary-Scan
Right-Click in the Boundary window / Initialize JTAG chain
Verify that iMPACT found the device

Illustration
8.34: Boundary Scan
Assign the binary design file (e.g. *.bit) - modulator.bit from your working directory into the volatile memory, and click Open
Optional: Assign the binary design file (e.g. *.mcs) from your working directory into the non-volatile memory, and click Open – else click Bypass
Optional: Assign the binary design file (e.g. *.jed) from your working directory into the onboard CPLD, and click Open – else click Bypass
Click Ok, or change Device Programming Properties if required
Right-click on the programming device (device which displays the modulator.bit file) / Program. This command will load your design into the device
Assuming no errors occurs, you can test your design with a Chipscope core or an oscilloscope.
8.13 Chipscope
After configuring your device, you can debug your FPGA design using the Xilinx ChipScope Pro tool. The ChipScope Pro tool comprises from:
CORE Generator Tool – provides core generation capability for the ICON, ILA, VIO and ATC2 cores
IBERT Core Generator – provides full design generation capability for the IBERT core targeting the Virtex-4 and Virtex-5 families
Core Inserter – automatically inserts the ICON, ILA and ATC2 cores into the user's synthesized design
PlanAhead Design Analysis Tool - automatically inserts the ICON and ILA cores into the design netlist
Analyzer – provides design configuration, trigger setup, and trace display for the ILA, IBA/OPB, IBA/PLB, VIO, and IBERT cores. The Analyzer tool also provides device configuration, project management, and control over the IBERT core, including monitoring status and controlling variables
ChipScope Engine Tcl (CSE/Tcl) Scripting Interface – the scritable CSE/Tcl command interface makes it possible to interact with devices in a JTEG chain from a TCL shell
For a typical design it is enough to use CORE Generator Tool or Core Inserter, to create and insert ChipScope Pro cores and Analyzer Tool to debug a design.
ChipScope Pro Tool Design Flow:
Insert ChipScope Pro cores in your design using the CORE Generator software or ChipScope Pro Core Inserter
In the Project Navigator, implement your design in and configure your device
In the ChipScope Pro Analyzer, analyze your design

Illustration
8.35: ChipScope Pro Tool Design Flow
8.13.2 ChipScope Pro Cores
The ChipScope Pro tool allows you to embed the following cores within your design, which assist with on-chip debugging: integrated logic analyzer (ILA), integrated bus analyzer (IBA), and virtual input/output (VIO) low-profile software cores. These cores allow you to view internal signals and nodes in your FPGA.
ChipScope Pro cores and there functions:
ILA: The ILA core is a customizable logic analyzer core that can be used to monitor the internal signals in your design. Because the ILA core is synchronous to the design being monitored, all design clock constraints applied to your design are also applied to the components inside the ILA core.
ATC2: The Agilent Trace Core 2 (ATC2) is a customizable logic analyzer core, which is not included in the standard ISE (shareware) and is similar to the ILA core but does not use on-chip Block RAM resources to store captured trace data. The ATC2 core synchronizes ChipScope Pro to the Agilent FPGA dynamic probe technology, delivering the first integrated application for FPGA debug with an external logic analyzers.
VIO: The virtual input/output core is a customizable core that can both monitor and drive internal FPGA signals in real time. Unlike the ILA and IBA cores, the VIO core does not require on-chip RAM.
ICON: The Integrated Controller (ICON) core provides the communication between the embedded ILA, IBA, and VIO cores and the computer running the ChipScope Pro Analyzer software.
Note: EDK provides additional specific cores.
The ISE software and ChipScope Pro tool are integrated. Within the ISE software, you can create a ChipScope Definition and Connection (CDC) file to associate with the HDL or EDIF design that you process in the Project Navigator. This file stores information about source files, destination files, core parameters, and core settings for the ChipScope Pro Core Inserter. The CDC file is also used as input to the ChipScope Pro Analyzer to import signal names.
The CDC file is treated as a source file, and appears in the Project Navigator Hierarchy window. You can double-click the file to launch the ChipScope Pro Core Inserter software in which you can specify the ChipScope Pro cores.
To run the ChipScope Pro Core Inserter:
Select Project / New Source
In the New Source dialog box, select ChipScope Definition and Connection File, enter chipscope_name (modulator) in the File name field, and click Next (see Illustration 8.36)

Illustration
8.36: Select Source Type dialog box
In the Associate Source dialog box, select modulator as a source with which to associate the new source, and click Next (see Illustration 8.37)

Illustration
8.37: New Source Wizard – Associate Source
Click Finish
Double-Click on the chipscope file (modulator.cdc) in the “Sources for” window to start the ChipScope Pro Core Inserter
Click Next (or change if required)
Note: Only one CDC may exist in a project. To remove all traces of ChipScope Pro cores in an ISE project, remove the CDC file and recompile the design.
After starting ChipScope Pro Core Inserter, you will have a possibility to make one of two possible Units (see Illustration 8.38):
New ILA Unit, or
New ATC2 Unit

Illustration
8.38: ChipScope Pro Core Inserter
New ILA Unit:
Select New ILA Unit in the ChipScope Pro Core Inserter
Click on the ILA module, above the Core Utilization window, to modify the core
Set the Trigger Parameters, as it is shown on the Illustration 8.39. Set Trigger Width (it is the number of signals that trigger port is composed of) to 13 and # Match Units (it is the number of units for comparing) to 2 and check is Enable Storage Qualification enabled in the Storage Qualification Condition Settings.
The number of Trigger Width is 13, because the size of the sine_ampl_s signal, that we want to see in the ChipScope, is 12 bits and the size of the freq_trig signal, with which we will do the storage qualification, is 1 bit.
Storage qualification condition is a Boolean combination of events that is detected by match unit comparators that are attached to the trigger ports of the core. Only when this combination is detected, data will be stored in the ChipScope's buffer.
The number of the Match Units is 2, because one is necessary for the trigger condition (when the sine_ampl_s signal is 0) and the second one is necessary for the storage qualification condition (when the freq_trig signal is 1).

Illustration
8.39: ChipScope Pro Core Inserter – modifying the ILA core
Click Next
In the Capture Parameters tab, choose 512 Samples in the Data Depth drop-down many
Click Next
In the Net Connections tab select Modify Connections
Select clk_in_BUFGP as clock signal and click Make Connections (Illustration 8.40).

Illustration
8.40: Select Net
Select Trigger/Data Signals tab in the Net Selections tab
Make following connections, as we made a connection for clk_in_BUFGP clock signal in step 8 (see Illustration 8.41)
connect sine_ampl_s (11 downto 0) signal, and
connect freq_trig signal

Illustration
8.41: ILA Trigger/Data Signals
Click Ok
Click Return to Project Navigator
Save and Close ChipScope Pro Core Inserter Project
Return to the Implement Design (see Chapters 8.7 - 8.9)
Generate Programming File (see Chapter 8.10. Generate Programming File)
Configure Device (see Chapters 8.11 and 8.12)
New ACT2 Unit:
Select New ACT2 Unit in the ChipScope Pro Core Inserter
Click on the ACT2 module, above the Core Utilization window, to modify the core
Set the ATD Pin Count in the Pin Selection Parameters tab to 12 and Data Width to 13, as it is shown on the Illustration 8.42

Illustration
8.42: ChipScope Pro Core Inserter – modifying the ACT2 core
Set the Individual Pin Settings as it is shown on the Illustration 8.42 and add the pin locations in the Pin Loc tab
Select Modify Connections in the Net Connections tab
Modify connections like for an ILA core (see steps 7-11)
Save and Close ChipScope Pro Core Inserter Project
Return to Implement Design (see Chapters 8.7 – 8.9)
Generate Programming File (see Chapter 8.10. Generate Programming File)
Configure Device (see Chapters 8.11 and 8.12)
8.13.4 Analyze a design using a ChipScope Pro tool
To launch the ChipScope Pro Analyzer from the Project Navigator:
Select Implementation from the “Sources for” drop-down list, if it is not already set
In the Sources window, select analyzable module (modulator_rtl)
In the Processes window, double-click on the Analyze Design Using Chipscope (see Illustration 8.43).

Illustration
8.43: Analyze Design Using ChipScope

In the ChipScope Analyzer click on the icon Open Cable/Search JTAG Chain
Note: Verify that your design is running
Click Ok
In the Signals window, expand Data Port and select signals starting from CH:0 up to CH:11. Right click on it and select Move to Bus → New Bus option (see Illustration 8.44)

Illustration
8.44: Creating a bus
Enter desired name of the bus (in our case it is sine_ampl_s) and press Enter
Rename the remaining channel (CH: 12 DataPort[12]) to freq_trig (select the channel, right click on it and select Rename option)
Select sine_ampl_s bus and freq_trig signal, right click, and select Add to View → Waveform option
In the Waveform window, right click on the sine_ampl_s bus, and select Bus Radix → Unsigned Decimal option (see Illustration 8.45)

Illustration
8.45: Changing Bus Radix
Configure Trigger Setup, as it is shown on the Illustration 8.46.

Illustration
8.46: Configuring Trigger Setup
In the Match section, configure Value of the M0:TriggerPort0 to X_0000_0000_0000 and M1:TriggerPort0 to 1_XXXX_XXXX_XXXX, and check is Radix set as Bin
In the Capture section, configure Storage Qualification to M1. To open and configure the Storage Condition, left click on the Storage Qualification box, enable the M1 as Match Unit and click Ok (see Illustration 8.47)

Illustration
8.47: Storage Condition
Run the ChipScope Analyzer (see Illustration 8.48)

Illustration
8.48: Running the ChipScope Analyzer
Now you should see your design being analyzed by the onboard ChipScope module (see Illustration 8.49)

Illustration
8.49: Content of the ChipScope waveform window after trigger
has been detected
If you compare Illustration 8.49 with Illustration 7.1, you can see that the signals sine_ampl_s and sine_out_s have identical waveforms. This means that the implemented Modulator design in the FPGA is behaving in the same way as it was predicted by the simulation.
To analyze the operation of the Modulator design in case of the other output signal frequency, move the onboard switch (sw0) to the other position and run the ChipScope Analyzer again by pressing the Arm Trigger button as it is shown in the Illustration 8.48.
Note: For more information, please see “ChipScope Pro 11.1 Software and Cores User Guide”.
8.14 Oscilloscope
An oscilloscope is a type of electronic instrument that creates a two-dimensional graph of one or more electrical potential differences. Typically horizontal, or x-axis, represents function of time and vertical, or y-axis, represents voltage.
To see the pwm signal on the oscilloscope, follow these steps:
Connect the USB Type B Connector to the Starter Kit Board Connector and to the PC
Connect the oscilloscope's probe to some expansion connector on the Starter Kit Board (see Illustration 8.50)

Illustration
8.50: Using oscilloscope for viewing PWM signal
Power on the Spartan-3E Demoboard
In the modulator_rtl.vhd file made the following corrections:
add a new pwm1 port in the modulator entity declaration:
pwm1: out std_logic;
in the architecture add a new temporary signal declaration:
signal temp_out_s: std_logic;
in the port map of the pwm module (pwmmodule) connect the pwm port with the temp_out_s signal:
pwm => temp_out_s;
at the and of the architecture connect the pwm and pwm1 signals with the temp_out_s signal:
pwm <= temp_out_s;
pwm1 <= temp_out_s;
Now, the modulator_rtl.vhd source file should look like the code below:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_unsigned.all;
library unisim;
use unisim.vcomponents.all;
entity modulator is
generic(
cntampl_value_g: std_logic_vector := x"ff"; -- clk counter amplitude border
depth_g : integer range 1 to 99 := 8; -- the number of samples in one period of the signal
freqhigh_g : std_logic_vector (17 downto 0) := b"110000000000000000"; -- threshold value of frequency a = 196608
freqlow_g : std_logic_vector (17 downto 0) := b"001110000000000000"; -- threshold value of frequency b = 57344
width_g : integer range 1 to 99 := 12 -- the number of bits used to represent amplitude value
);
port(
clk_in : in std_logic; -- 50 MHz input clock signal
sw0_freq_sel : in std_logic; -- signal made for selecting frequency
pwm : out std_logic; -- pulse width modulated signal
pwm1 : out std_logic -- pulse width modulated signal – for the oscilloscope
);
end;
architecture rtl of modulator is
signal ampl_cnt_s : std_logic_vector(depth_g-1 downto 0); -- amplitude counter
signal sine_ampl_s : std_logic_vector(width_g-1 downto 0); -- current amplitude value of the sine signal
signal freq_trig_s : std_logic := '0'; -- signal which frequency depends on the sw0_freq_sel state
signal temp_out_s : std_logic; -- temporary signal
begin
freq_ce : entity work.frequency_trigger(rtl) -- generates frequency trigger
generic map(
freqhigh_g => freqhigh_g,
freqlow_g => freqlow_g
)
port map(
clk_in => clk_in,
freq_trig => freq_trig_s,
sw0_freq_sel => sw0_freq_sel
);
counterampl : entity work.counter(rtl) -- generates amplitude values
generic map(
cnt_value_g => cntampl_value_g
)
port map (
clk_in => clk_in,
cnt_en => freq_trig_s,
cnt_out => ampl_cnt_s
);
sine : entity work.sine(rtl) -- generates digital sine
generic map(
depth_g => depth_g,
width_g => width_g
)
port map(
ampl_cnt => ampl_cnt_s,
clk_in => clk_in,
sine => sine_ampl_s
);
pwmmodule : entity work.pwm (rtl) -- generates pwm signal
generic map (
width_g => width_g,
freqhigh_g => "000000000000"&freqhigh_g (17 downto 12), --freqhigh_g / 4096
freqlow_g => "000000000000"&freqlow_g (17 downto 12) --freqlow_g / 4096
)
port map (
clk_in => clk_in,
sw0_freq_sel => sw0_freq_sel,
sine_ampl => sine_ampl_s,
pwm => temp_out_s
);
pwm <= temp_out_s;
pwm1 <= temp_out_s;
end;
In the UCF file add location of the pwm1 signal. Location of the pwm1 signal should be chosen in such way to allow easy access for the oscilloscope's probe
Return to the Implement Design (see Chapters 8.7 – 8.9)
Generate Programming File (see Chapter 8.10. Generate Programming File)
Configure Device (see Chapters 8.11 and 8.12)
Configure the oscilloscope, and if your oscilloscope's settings are correct, you should see a pwm signal on the display, see Illustration 8.51.

Illustration
8.51: PWM signal measured by oscilloscope



