This tutorial outlines the development flow for FPGA programming and presents a simplified example to elaborate FPGA programming in real life. The example is based on Intel’s development board that consists of analog-to-digital converters (ADC) and digital-to-analog converter (DAC).
In this FPGA programming tutorial we will create a simple project that is taking an input signal for ADC from on-board potentiometer and outputs to user LEDs and DAC that are also located on the development board. User LEDs and DAC output are changing according to the potentiometer input voltage. Watch the following video to see the demo live.
In this article, we will be using two tools: Quartus 16.0 IDE and Modelsim-Intel together with an FPGA development board for MAX 10 and USB Bluster. MAX 10 development board has two ADCs. The ADCs provide the MAX 10 devices with built-in capability for on-die temperature monitoring and external analog signal conversion.
This FPGA programming tutorial provides all the required steps, instruction and source files to help you get started and to allow you try re-creating this project in your own environment.
MAX 10 Development Kit is centered around Max 10 FPGA devices from Intel (Altera). The board is used for development and evaluation of the Intel MAX 10 FPGA family and provides well documented hardware platform for beginners in FPGA development.
Let’s start from setting up and simulation the ADC core. In the Quartus Prime Standard Edition start new project, specify working directory (please note – there is shouldn’t be spaces in the name of directory), name of project and select 10M50DAF484C8GES device. Open in the IP catalog Intel Modular ADC core, write entity name adc_core and set settings like shown below:
The core variant for 1st ADC is ADC control core only, it allows to control the ADC core directly from the HDL code without soft processor Nios. This enables user created expected output file for simulation ADC core. Set only one channel – number 6, that is tied to potentiometer on the development kit. Point to user expected output file (in my case is CH6_data.txt). File CH6_data.txt consist information about step and voltage are going to apply to ADC channel:
The left column is used for arranging voltage Vin that is taken from right column. There is space between two columns. The output of ADC core will be computed like Vin \ 2.5 V * 4096 [2].
Now, generate the ADC core and check create simulation model before. Manually add adc_core.qip, adc_core.sip and adc_core.qsys files into project. Create top-level Verilog file max10_dsp.v with ADC and ALTPLL IP cores included:
The IP core ALTPLL should be added to project for generating clock and locked signals to ADC. Settings of ALTPLL IP core is: 50 MHz input clock, unchecking areset signal, the output clock frequency is 10 MHz. Now, run Analysis and Synthesis.
The project’s working directory consists of folder adc_core with all necessary files for simulation ADC IP core except testbench file. So — there is quite simple testbench file that describes behavior of ADC core inputs as follows:
The Modelsim-Intel tool will be used for simulation of the ADC IP core therefore it’s necessary to create a launch script .do file. For creating a launch script go to mentor folder situated into adc_core/simulation folder. There is a Quartus generated msim_setup.tcl script file that is used for creating Modelsim-Intel launch file. From msim_setup.tcl take only the part between # # TOP-LEVEL TEMPLATE – BEGIN and # # TOP-LEVEL TEMPLATE – END strings and edit like this:
# # TOP-LEVEL TEMPLATE – BEGIN
# #
# # QSYS_SIMDIR is used in the Quartus-generated IP simulation script to
# # construct paths to the files required to simulate the IP in your Quartus
# # project. By default, the IP script assumes that you are launching the
# # simulator from the IP script location. If launching from another
# # location, set QSYS_SIMDIR to the output directory you specified when you
# # generated the IP script, relative to the directory from which you launch
# # the simulator.
# #
set QSYS_SIMDIR .
# #
# # Source the generated IP simulation script.
source $QSYS_SIMDIR/mentor/msim_setup.tcl
# #
# # Set any compilation options you require (this is unusual).
# set USER_DEFINED_COMPILE_OPTIONS <compilation options>
# #
# # Call command to compile the Quartus EDA simulation library.
dev_com
# #
# # Call command to compile the Quartus-generated IP simulation files.
com
# #
# # Add commands to compile all design files and testbench files, including
# # the top level. (These are all the files required for simulation other
# # than the files compiled by the Quartus-generated IP simulation script)
# #
vlog -vlog01compat -work work submodules/adc_core_modular_adc_0.v
vlog -vlog01compat -work work submodules/Intel_modular_adc_control.v
vlog -vlog01compat -work work submodules/Intel_modular_adc_control_avrg_fifo.v
vlog -vlog01compat -work work submodules/Intel_modular_adc_control_fsm.v
vlog -vlog01compat -work work submodules/chsel_code_converter_sw_to_hw.v
vlog -vlog01compat -work work submodules/fiftyfivenm_adcblock_primitive_wrapper.v
vlog -vlog01compat -work work submodules/fiftyfivenm_adcblock_top_wrapper.v
vlog -vlog01compat -work work adc_core.v
vlog -vlog01compat -work work adc_core_tb.v
# #
# # Set the top-level simulation or testbench module/entity name, which is
# # used by the elab command to elaborate the top level.
# #
set TOP_LEVEL_NAME adc_core_tb
# #
# # Set any elaboration options you require.
# set USER_DEFINED_ELAB_OPTIONS <elaboration options>
# #
# # Call command to elaborate your design and testbench.
elab
# #
# # Run the simulation.
add wave *
view structure
view signals
run -a
# #
# # Report success to the shell.
# exit -code 0
# #
# # TOP-LEVEL TEMPLATE – END
Save it into modelsim_script.do file. This file consists of information about ADC IP core files for simulation in Modelsim-Intel tool and may be used separately without Quartus software. Now, open created modelsim_script.do by modelsim.exe application. In the command line run do modelsim_script.do command, it allows to run testbench for ADC IP core. The Wave simulation looks like this:
Signal command_valid always high, signal command_channel is set to 6, wire response_channel is 6 and response data is 164, 328, 819, 1311 and so on, the data is set according voltage being write down in CH6_data.txt (0.1/2.5 * 4096 = 164, 0.2/2.5*4096=328 and so on).
The majority of Intel IP cores could be simulated in such manner. That is good starting point for using IP cores.
The DAC component of the development kit is represented by Texas Instrument DAC8551 microchip [3]. One has three wire input that is compatible with standard SPI interfaces, a diagram for SPI serial write operation is shown below:
The write operation is provided by asserting to low SYNC signal and SCLK clock up to 30 MHz, 24 bits of data is clocked on falling edge. A simple finite state machine (FSM) for developing DAC driver will be used for this tutorial. When writing any HDL code it’s recommended to use for reference Recommended HDL Coding Styles [4] or templates that can be found in Quartus software. This ensures the FPGA developer that all basic elements (trigger, latch, ROM memory, etc.) will be correctly recognized by the RTL logic by synthesis tool.
A typical FPGA Design Flow consists of:
Design Entry
Synthesis
Implementation
Program FPGA
Step 2: FPGA Design Entry
Let’s start with inserting a template for Verilog HDL 4-state Moor FSM. Moor FSM outputs are depending only on current state; outputs for DAC are DAC_SYNC, DAC_SCLK, DAC_DIN. HDL code for Moor FSM
// FSM DAC logic
// Declare state register
reg [1:0] state;
reg clkDAC = 1’b0;
reg [23:0] shift_reg;
reg [5 :0] half_bit;
reg [11:0] adc_reg;
wire DAC_SYNC_Latch;
// Declare states
parameter Idle = 0,
Wait = 1,
Load = 2,
Feed = 3;
// Determine the next state
always @ (posedge CLK_50_MAX10) begin
if (!CPU_RESETn)begin
state <= Idle;
shift_reg <= 24’d0;
half_bit <= 6’d0;
clkDAC <= 1’b0;
adc_reg <= 12’d0;
end
else
case (state)
Idle: begin
state <= Wait;
clkDAC<= 1’b1;
half_bit<= 6’d0;
end
Wait:
if (response_valid && response_channel == 5’d6)begin
Register adc_reg is used for taking data from ADC 6 channel on response_valid high signal and 24 bit shift register shift_reg is used for moving data in serial on DAC_DIN signal. The FSM state will define level and behavior of DAC_SYNC and DAC_SCLK signals. Counting of bits in shift register is done by half_bit counter.
Step 3: FPGA Synthesis
After the Analysis & Synthesis step, the HDL code will be checked and recognized in RTL logic. The Quartus state machine viewer FSM states will look like this:
There are 4 states: Idle, Wait, Load and Feed. After reset, the FSM will move to Idle state, where all registers will be initialized. The state Wait FSM will be expecting response_valid signal from ADC on 6th channel. On Load state the shift register will be loaded after getting ADC response_data by adc_reg register. The Feed state provides correct level and behavior of DAC_SYNC, DAC_SCLK and shifting data in shift register. When Feed state finished moving data to DAC FSM it will return back to Idle state and all registers will be reinitialized.
Functional simulation is performed on the synthesis step. This kind of simulation doesn’t consider timing requirements. Now, the entire project with ADC/DAC can be simulated with testbench. It will look like this:
`timescale 1 ps/ 1 ps
module max10_dsp_vlg_tst();
// reg CLK_10_ADC;
reg CLK_50_MAX10;
reg CPU_RESETn;
// wires
wire DAC_DIN;
wire DAC_SCLK;
wire DAC_SYNC;
// assign statements (if any)
max10_dsp i1 (
// port map – connection between master ports and signals/registers
// .CLK_10_ADC(CLK_10_ADC),
.CLK_50_MAX10(CLK_50_MAX10),
.CPU_RESETn(CPU_RESETn),
.DAC_DIN(DAC_DIN),
.DAC_SCLK(DAC_SCLK),
.DAC_SYNC(DAC_SYNC)
);
always #20 CLK_50_MAX10 = ~CLK_50_MAX10;
initial
begin
CLK_50_MAX10 = 0;
CPU_RESETn = 0;
# 1000;
CPU_RESETn = 1;
# 150000;
$stop;
$display(“end simulation”);
end
endmodule
The signals CLK_50_MAX10 and CPU_RESETn are set and ADC will be useing input analog signals defined in CH6_data.txt file. Simulation results are shown below:
The Project simulation allows debugging the behavior of FSM for DAC data serialization. After simulation, a pinout assignment is needed. All pinout will set according MAX10 development kit user guide. Assignment may be found in max10_dsp.qsf file and for outputs look like this:
Before starting the Implementation phase, it’s needed to add signals by using the Signal tap. This tool allows debugging the design after place and route the project into an FPGA. Same signals are used in the functional simulation. After Implementation and Program FPGA Signal tap tool is used for debugging the project directly into FPGA.
Step 5: FPGA Programming and Results
The results of debugging after implementation are the same as in the functional simulation. A very important step was missed in this tutorial ‑ timing analyze. This step should be done if project is very large or\and consists of logic for working with fast peripheral like high speed ADC, PCIe, Ethernet and so on.
Please click on the video below to watch the project demo in real life:
This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.
Strictly Necessary Cookies
Strictly Necessary Cookie should be enabled at all times so that we can save your preferences for cookie settings.
If you disable this cookie, we will not be able to save your preferences. This means that every time you visit this website you will need to enable or disable cookies again.
3rd Party Cookies
This website uses Google Analytics to collect anonymous information such as the number of visitors to the site, and the most popular pages.
Keeping this cookie enabled helps us to improve our website.
Please enable Strictly Necessary Cookies first so that we can save your preferences!
Additional Cookies
This website uses the following additional cookies:
(List the cookies that you are using on the website here.)
Please enable Strictly Necessary Cookies first so that we can save your preferences!