Tutorial: VHDL Coding & Logic Synthesis with Quartus Prime#


HDL-based Logic Synthesis#

In an HDL-based FPGA design flow, synthesizable VHDL source code of the logic design must be compiled and optimized using a logic synthesis tool to produce a lower-level netlist, similar to a gate-level netlist.

This netlist is then mapped to FPGA internal resources, which are subsequently fitted during the place and route steps to produce a post-fitting netlist. In the final step, a corresponding bitstream file is generated for configuration of the FPGA.

Figure: Intel / Altera FPGA Design Flow using Quartus Prime tools

Quartus Prime provides synthesis optimization options that target area, performance, power, or a balanced configuration, depending on design requirements. These options impact both synthesis run time and key design metrics such as area and performance.

Figure: Synthesis Options

 


Quartus Prime - VHDL Templates#

HDL coding styles have a significant effect on the quality of results for programmable logic designs. It is vitally important to understand the linkage between VHDL code and the corresponding logic produced by the synthesis tool.

Quartus Prime offers a collection of helpful HDL Code Templates (for VHDL, Verilog, and SystemVerilog), which can assist in accelerating development and ensuring best practices.

Figure: Quartus Prime - VHDL Code Template

 


VHDL Modeling: MUX2_1 + D-Type Flip-Flop#

 

In this section, we will explore how VHDL models of basic digital logic circuits are synthesized using the Quartus Prime software.

The following is the entity declaration of an example design (MUX2_1 + DFF):

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY synth_test IS
    PORT (
        CLK   : IN STD_LOGIC; -- clock input
        RST_N : IN STD_LOGIC; -- asynchronous reset, active-low
        CE    : IN STD_LOGIC; -- clock enable
        D0    : IN STD_LOGIC; -- data input 0
        D1    : IN STD_LOGIC; -- data input 1
        SEL   : IN STD_LOGIC; -- data select
        Q     : OUT STD_LOGIC -- data output
    );
END ENTITY;

Two versions of architectural implementations of the design example are provided below. Both versions lead to the same synthesis results.

Version 1

ARCHITECTURE rtl OF synth_test IS
    SIGNAL q_int : STD_LOGIC;
BEGIN
    mux_dff_proc: PROCESS (CLK, RST_N)
    BEGIN
        IF RST_N = '0' THEN -- asynchronous reset
            q_int <= '0';
        ELSIF rising_edge(CLK) THEN
            IF CE = '1' THEN
                IF SEL = '0' THEN
                    q_int <= D0;
                ELSE
                    q_int <= D1;
                END IF;
            END IF;
        END IF;
    END PROCESS;

    Q <= Q_int;

END ARCHITECTURE;

 

Version 2

ARCHITECTURE rtl OF synth_test IS
    SIGNAL data_next : STD_LOGIC;
    SIGNAL q_int : STD_LOGIC;
BEGIN
    -- MUX2_1: conditional concurrent assignment
    data_next <= D1 WHEN SEL = '1' ELSE D0;

    -- D-type flip-flop with async. reset and sync. clock enable
    dff_proc : PROCESS (CLK, RST_N)
    BEGIN
        IF RST_N = '0' THEN -- asynchronous reset
            q_int <= '0';
        ELSIF rising_edge(CLK) THEN
            IF CE = '1' THEN -- clock enable is active.
                q_int <= data_next; -- update data
            END IF;
        END IF;
    END PROCESS;

    Q <= q_int;

END ARCHITECTURE;

The key difference between the two versions is that the first one is modeled using a single process block, whereas the second one uses a conditional concurrent signal assignment for a 2-to-1 multiplexer, and a process block for a D-type flip-flop, where the data input comes from the output of the multiplexer.

Note: Inferring in the context of digital design and synthesis means that the synthesis tool automatically recognizes and generates hardware components — such as multiplexers, flip-flops, adders, or ROM / RAM blocks — from the HDL code, without explicitly describing those components.

The synthesis tool can automatically infer a multiplexer and a D-type flip-flop from the VHDL code. The synthesis report shows that the design utilizes two logic elements (LEs) and one register (flip-flop).

Figure: Synthesis Report

 

Note: A Logic Element (LE) is the smallest unit of logic in the MAX 10 device family architecture. Each LE includes the following features:

  • Logic resources:
    • A 4-input Look-Up Table (LUT) for combinational logic
    • A programmable register (flip-flop) for sequential logic
    • A carry chain connection (for fast arithmetic operations)
    • A register chain connection (for shift register functionality)
  • Interconnects:
    • Local interconnects (for nearby LEs within the same Logic Array Block)
    • Global interconnects (for communication across the FPGA fabric)

Netlist Viewers#

The result of the design compilation can be visualized using the RTL Viewer, the Post-Mapping Viewer and the Post-Fitting Viewer.

  • The RTL Viewer provides a high-level, graphical view of the synthesized VHDL/Verilog code, showing abstract logic (multiplexers, flip-flops) directly from the VHDL/Verilog code.
  • The Post-Mapping Viewer presents a detailed, technology-specific look at the design after mapping to actual device-specific FPGA resources (e.g. LUTs, LABs, IOBs).
  • The Post-Fitting Viewer shows the final physical implementation of the design after placement and routing. It displays how the logic elements, interconnects, and I/O blocks are physically placed within the FPGA fabric.

The RTL Viewer shows that the design, after synthesis, consists of two components at the register transfer level (RTL): a 2-to-1 multiplexer (MUX2_1) and a D-type flip-flop (DFF) (with some control inputs).

Figure: RTL Viewer

The Post-Mapping Viewer shows how the multiplexer and flip-flop are technology-mapped onto the resources of the MAX 10 device. The schematic displays the circuit components, including I/O buffer blocks for input and output signals, two combinational logic cells (LOGIC_CELL_COMB), and a flip-flop.

A combinational logic cell is typically a look-up table (LUT) with up to 4 inputs and one output. These logic cells can be used to implement logic gate networks or grouped logic functions. In this example, the LUTs are used to implement data selection logic, such as multiplexers.

Figure: Post-Mapping / Technology-Map Viewer

 

The Post-Fitting Viewer shows that additional logic resources and pins (e.g., JTAG pins, configuration status pins) are included alongside the user-defined logic.

Figure: Post-Fitting Viewer

 

The final placement or locations of physical resources can be inspected in the Chip Planner. The figure below shows the Chip Planner view in Quartus Prime, displaying a simplified view of the internal structure of the MAX 10 DA50 device:

  • The large region located at the top-left corner corresponds to the on-chip Flash memory (CFM/UFM), responsible for storing the FPGA configuration bitstream.
  • Along the boundary of the chip are the I/O blocks (IOBs).
  • The central grid consists of Logic Array Blocks (LABs), each containing logic elements such as 4-input LUTs, flip-flops, and associated control logic. These LABs are arranged in vertical columns across the chip.
  • Embedded memory blocks and DSP blocks (not used in this design) are also organized in vertical columns within the FPGA fabric.

Figure: A simplified view of the MAX 10 FPGA floorplan

Figure: Chip Planner view of the MAX 10 50DA device

 


VHDL Modeling: D-Type Latch#

The following is the entity of a design in VHDL that can be inferred as a D-type latch (with enable and asynchronous active-low clear).

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY synth_test IS
    PORT (
        CLR_N : IN STD_LOGIC; -- asynchronous clear (active-low)
        EN    : IN STD_LOGIC; -- latch enable
        D     : IN STD_LOGIC; -- data input
        Q     : OUT STD_LOGIC -- data output
    );
END ENTITY;

There are two equivalent VHDL implementations of the D-type latch.

Version 1

ARCHITECTURE rtl OF synth_test IS
    SIGNAL q_int : STD_LOGIC := '0'; -- with initial value
BEGIN

    latch_proc : PROCESS (CLR_N, EN, D)
    BEGIN
        IF CLR_N = '0' THEN
            q_int <= '0';
        ELSIF EN = '1' THEN
            q_int <= D;
        END IF;
    END PROCESS;

    Q <= Q_int;

END ARCHITECTURE;

 

Version 2

ARCHITECTURE rtl OF synth_test IS
    SIGNAL q_int : STD_LOGIC := '0'; -- with initial value
BEGIN
    q_int <= '0' when CLR_N = '0' 
         ELSE D WHEN EN = '1' ELSE q_int;
    Q <= Q_int;

END ARCHITECTURE;

 

Figure: Post-Mapping Viewer of a D-type latch with enable and asynchronous active-low clear

Basically, a D-type latch can be implemented using a 2-to-1 multiplexer (MUX2_1) with a feedback path from its output to one of its data inputs.

In the Post-Mapping Viewer, it can be seen that the logic cell (LOGIC_CELL_COMB), which is a 4-input LUT (LUT4), implements a MUX2_1 and an AND2 gate.

The LUT4 has 4 inputs with connected as follows:

  • DATAA = D
  • DATAB = q_int
  • DATAC = EN
  • DATAD = CLR_N

The output (O) is defined by the following Boolean equation:

O = ((!EN * q_int) + (EN * D)) * CLR_N,

where * and + represent logical AND and OR operators, respectively.

The Truth table of the output function is shown below.

D C B A | O
-----------
0 0 0 0 | 0
0 0 0 1 | 0
0 0 1 0 | 0
0 0 1 1 | 0
0 1 0 0 | 0
0 1 0 1 | 0
0 1 1 0 | 0
0 1 1 1 | 0
1 0 0 0 | 0
1 0 0 1 | 0
1 0 1 0 | 1
1 0 1 1 | 1
1 1 0 0 | 0
1 1 0 1 | 1
1 1 1 0 | 0
1 1 1 1 | 1

The output bits are be expressed as a binary or hex string: 1010_1100_0000_0000 or AC00 (referred to as the LUTMASK).

The following Python code can be used to compute the LUT4 table for the given Boolean expression.

print("D C B A | O")
print("-----------")
for i in range(16):
    #print(f'{i:b}'.zfill(4))
    D      = (i >> 0) & 1 # A
    q_int  = (i >> 1) & 1 # B
    EN     = (i >> 2) & 1 # C
    CLR_N  = (i >> 3) & 1 # D
    O = ((not EN and q_int) or (EN and D)) and CLR_N
    print(f"{CLR_N} {EN} {q_int} {D} | {int(O)}")

 


This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Created: 2025-06-01 | Last Updated: 2025-06-02