Monday 29 August 2022

Installing GHDL and GTKwave on Windows

GHDL is a well established and powerful VHDL simulator that is free and open source. For more information, visit the GHDL web site or the GHDL Github repository.

GTKwave is a very useful companion to GHDL: it's a wave viewer which supports common simulation output formats, and is also free and open source. For more information, visit the GTKwave web site or the GTKwave Github repository.

This post is for hardware engineers who want to get GHDL and GTKwave up and running quickly on a Windows PC (Windows 10 or later is recommended, and your Windows version should be 64-bit). It includes instructions on how to add Vivado and Quartus libraries to the GHDL installation, so that you can use it for real FPGA projects.


GTKwave UI

There is more than one way to install these tools, but I believe that the recipe presented here is a good one.

1. Installing MSYS2

You can read about MSYS2 on the project web site. It provides the underpinnings to enable applications developed for Linux and other Unix flavours to run on Windows PCs, with little or no modification to their source code. It also includes some basic infrastructure for development, including a command line (a terminal for interacting with its Bash shell) and tools for easy installation and management of packages of software.

MSYS2 includes various "environments" (or "subsystems"). They are described here. We will be using the MINGW64 environment throughout.

To install MSYS2 on your Windows PC, download the latest installer from here: MSYS2 x86-64 binaries. You will see a long list of files to chose from; scroll to the bottom and pick the last one listed in the form msys2-x86_64-date.exe where data is consists of year then month then day. For example: msys2-x86_64-20220603.exe.

Run the downloaded executable. The "Setup - MSYS2 64 bit" dialog is displayed:


Click the Next button. The "Installation Folder" dialog is displayed:


Edit the installation folder if desired. For example, all my development tools live in the devtools directory on  D drive, so I changed this to read D:\devtools\msys64. Click the Next button. The "Start Menu Shortcuts" dialog is displayed:


Click the Next button. The "Installing MSYS2 64 bit" dialog is displayed:

The green progress bar will move to the right as the installer progresses. This can take a minute or so. When complete, the "Completing the MSYS2 64 bit Wizard" dialog will displayed:


Untick the "Run MSYS2 64 bit now" box and then click the Finish button. MSYS2 is now installed.

2. Update Windows Environment Variables

If you are not familiar with editing environment variables, please do a bit of searching to familiarise yourself with the procedure for your version of Windows.

Define an MSYS2 environment variable set to your MSYS2 install location (C:\msys64 by default). This will allow scripts to locate MSYS2 components easily.

In a development session you will often want to run both MSYS2 programs and Windows programs, so it makes sense to update the Windows path to ensure that you can run MSYS2 and MINGW64 binaries from a Windows Command Prompt or Windows Terminal. Add the following directories to your path: %MSYS2%\usr\bin and %MSYS2%\mingw64\bin.

3. The MSYS2 Terminal

To open an MSYS2 terminal (shell), run the MSYS2 MinGW x64 application from the Start Menu. The MSYS2 terminal window will appear:

Notice that the user, machine and environment names are displayed at the shell prompt (the $) along with the current directory, with ~ signifying the user's home directory. To find out where this actually is,  enter the bash command pwd:

user@MACHINE MINGW64 ~
$ pwd
/c/work

Notice that the path is /c/work not C:\work. MSYS2 is doing its job, translating Windows paths into Linux/Unix format for programs running under MSYS2. That means the slashes are changed from backwards to forwards, and drive letters become lower case prefixed by a slash, with the colon replaced by another slash.

Most of the time, when specifying a path to a MSYS2 program, you will need to use the MSYS2 path format.

4. Install GHDL and GTKwave

We will use the pacman package management tool to install GHDL and GTKwave in MSYS2.

Open an MSYS2 terminal and enter the following command exactly as shown:

pacman -S mingw-w64-x86_64-{ghdl-llvm,gtkwave}

pacman will list 70+ packages, and give a total size for the download and installation, and ask you if you wish to proceed. Something like this:

user@MACHINE MINGW64 ~
$ pacman -S mingw-w64-x86_64-{ghdl-llvm,gtkwave}
resolving dependencies...
looking for conflicting packages...
warning: dependency cycle detected:
warning: mingw-w64-x86_64-libwebp will be installed before its mingw-w64-x86_64-libtiff dependency
warning: dependency cycle detected:
warning: mingw-w64-x86_64-harfbuzz will be installed before its mingw-w64-x86_64-freetype dependency

Packages (74) mingw-w64-x86_64-adwaita-icon-theme-42.0-1
mingw-w64-x86_64-atk-2.38.0-1 mingw-w64-x86_64-binutils-2.38-2
mingw-w64-x86_64-brotli-1.0.9-4 mingw-w64-x86_64-bzip2-1.0.8-2
...
mingw-w64-x86_64-zstd-1.5.2-2
mingw-w64-x86_64-ghdl-llvm-2.0.0.r77.g4775ebbd6-1
mingw-w64-x86_64-gtkwave-3.3.111-1

Total Download Size: 287.71 MiB
Total Installed Size: 1896.30 MiB

:: Proceed with installation? [Y/n]

Enter Y to begin. The packages are downloaded in parallel, with progress bars. This will be followed by stage that processes package changes, then "post-transaction hooks". The whole process will take a few minutes.

GHDL and GTKwave are now installed and may be used - unless you need vendor libraries, in which case see below.

You can check the installed version of each application as follows:

user@MACHINE MINGW64 ~
$ ghdl --version
GHDL 3.0.0-dev (2.0.0.r77.g4775ebbd6) [Dunoon edition]
Compiled with GNAT Version: 11.2.0
llvm code generator
Written by Tristan Gingold.

Copyright (C) 2003 - 2022 Tristan Gingold.
GHDL is free software, covered by the GNU General Public License. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

user@MACHINE MINGW64 ~
$ gtkwave --version
GTKWave Analyzer v3.3.111 (w)1999-2020 BSI

This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

5. Compiling Vendor Libraries

If you want to use Vivado or Quartus libraries in your simulation, you will need to build them from the source code that is provided as part of the installation of these tools.

Start by opening an MSYS2 terminal and navigating to the GHDL vendor libraries directory:

cd /mingw64/lib/ghdl/vendors

Note that in the MSYS2 environment, / corresponds to the MSYS2 install directory. So if MSYS2 is installed in c:\msys64 then the MSYS2 path /mingw64/lib/ghdl/vendors corresponds to  the Windows path C:\msys64\mingw64\lib\ghdl\vendors. You need to know this because the next step is to open and edit the config.sh file which is located there in your preferred text editor (I recommend Notepad++).

You need to find the sections corresponding to Vivado and/or Quartus and update them to match the installation directories on your PC.

For Vivado, find the following section e.g. by searching for "vivado":

declare -A Xilinx_Vivado_Settings=(
	["InstallationDirectory"]=""              # "/opt/Xilinx/Vivado/2020.2"
	["SourceDirectory"]="data/vhdl/src"
	["DestinationDirectory"]="xilinx-vivado"
)

(Note that the # marks a comment which can be ignored.)

Amend the "InstallationDirectory" entry to match the Vivado installation on your PC, using an MSYS2 path format. For example:

declare -A Xilinx_Vivado_Settings=(
	["InstallationDirectory"]="/c/Xilinx/Vivado/2022.1"
	["SourceDirectory"]="data/vhdl/src"
	["DestinationDirectory"]="xilinx-vivado"
)

For Quartus, find the following section by searching e.g. for "intel":

declare -A Intel_Quartus_Settings=(
	["InstallationDirectory"]=""              # "/opt/intelFPGA/20.1/quartus"
	["SourceDirectory"]="eda/sim_lib"
	["DestinationDirectory"]="intel"
)

Amend the "InstallationDirectory" entry to match the Quartus installation on your PC, using an MSYS2 path format. For example:

declare -A Intel_Quartus_Settings=(
	["InstallationDirectory"]="/c/intelFPGA_lite/21.1/quartus"
	["SourceDirectory"]="eda/sim_lib"
	["DestinationDirectory"]="intel"
)

Once you have made these edits, save config.sh and quit your editor app.

You may now build the libraries you need by entering one or more of the following commands - one at a time - in an MSYS2 terminal:

  • for Vivado and VHDL-1993: ./compile-xilinx-vivado.sh -a --vhdl93
  • for Vivado and VHDL-2008: ./compile-xilinx-vivado.sh -a --vhdl2008
  • for Quartus and VHDL-1993: ./compile-intel.sh -a --vhdl93
  • for Quartus and VHDL-2008: ./compile-intel.sh -a --vhdl2008

Each command invokes a script which will build the (many) source files required. Note that this process takes many minutes - maybe many tens of minutes. Here's an example of a successful run - despite the warning and error messages:

user@MACHINE MINGW64 /mingw64/lib/ghdl/vendors
$ ./compile-xilinx-vivado.sh -a --vhdl93
Loading environment...
Creating vendor directory: '/mingw64/lib/ghdl/vendors/xilinx-vivado'.
Analyzing library 'unisim'...
Creating VHDL Library 'unisim'...
Analyzing files into library 'unisim'...
  WARNING: D:/devtools/Xilinx/Vivado/2022.1/data/vhdl/src/unisims/primitive/SYSMONE4.vhd:1536:44:warning: prefix of array attribute must be an object name [-Wattribute]
SCRIPT ERROR: Unfiltered line
v_str_time_length := time'image(now)'length;
SCRIPT ERROR: Unfiltered line
^
  Warnings detected by filtering script.
Analyzing library 'secureip'...
Creating VHDL Library 'secureip'...
Analyzing files into library 'secureip'...
Analyzing library 'unimacro'...
Creating VHDL Library 'unimacro'...
Analyzing files into library 'unimacro'...
Analyzing library 'unifast'...
Creating VHDL Library 'unifast'...
Analyzing files into library 'unifast'...
Analyzing library 'secureip'...
Creating VHDL Library 'secureip'...
Analyzing files into library 'secureip'...
  WARNING: D:/devtools/Xilinx/Vivado/2022.1/data/vhdl/src/unifast/secureip/GTHE2_CHANNEL.vhd:29:1:warning: entity "gthe2_channel" was also defined in file "D:/devtools/Xilinx/Vivado/2022.1/data/vhdl/src/unisims/secureip/GTHE2_CHANNEL.vhd" [-Wlibrary]
SCRIPT ERROR: Unfiltered line
library IEEE;
SCRIPT ERROR: Unfiltered line
^
  Warnings detected by filtering script.
  WARNING: D:/devtools/Xilinx/Vivado/2022.1/data/vhdl/src/unifast/secureip/GTXE2_CHANNEL.vhd:34:1:warning: entity "gtxe2_channel" was also defined in file "D:/devtools/Xilinx/Vivado/2022.1/data/vhdl/src/unisims/secureip/GTXE2_CHANNEL.vhd" [-Wlibrary]
SCRIPT ERROR: Unfiltered line
library IEEE;
SCRIPT ERROR: Unfiltered line
^
  Warnings detected by filtering script.
--------------------------------------------------------------------------------
Compiling Xilinx Vivado libraries [SUCCESSFUL]

You are now ready to simulate designs including Vivado and Quartus libraries. Note that you need to tell GHDL the path to the compiled libraries by adding a -P option to the command line for the analysis and elaboration steps. For example:

ghdl -a -frelaxed -fsynopsys -P/mingw64/lib/ghdl/vendors/xilinx-vivado top.vhd


Thursday 18 August 2016

Tag-Connect - A Smaller, Better Debug Connector

I design circuit boards (PCBs) with programmable devices - things like MCUs, PLDs and FPGAs - for a living. It's almost always necessary to provide a connector so that an external programmer, debugger or something as simple as a serial port can be hooked up to a board.

Programming, Debug and Serial Interface Hardware
In the early stages, this connector enables development and debug. Later on, it allows programming and configuration in the production process. The connector is often a simple header with one or two rows of pins on a 0.1 inch (2.54mm) pitch. Device manufacturers specify various pinouts to match their own programming and debug hardware. So far, so not very exciting...

Recently, I needed to design a board with an Atmel AVR MCU. It had to be no larger than 60mm x 14mm. There was no way I could fit Atmel's standard 2x3 header, so I started looking at placing small test pads and producing a companion board with pogo pins to break these out to a full size header. This is often a good way to go - the companion board can take on other duties, and maybe evolve into a full blow test jig - but it's another design task, and I was short of time and trying to keep costs down.

Enter Tag-Connect with their own clever take on this problem:

10 way Tag-Connect to IDC cable ("no legs" version)
Tag-Connect make cables with various standard connectors at one end, wired to a "plug of nails" at the other - a small array of pogo pins, together with rigid alignment pins.

6-way and 10-way Tag-Connect plugs, and a retaining clip
You place a corresponding array of round pads on your PCB, and locating holes to match the alignment pins. The "plug of nails" can then be pushed into the board with no danger of misalignment or rotation, allowing the relevant signals to be brought out to a programmer or whatever.

If you need to hold the plug in place for a while, there are a couple of options. For short periods of time, a clip (shown in the above image) can be used to hold the alignment pins.

10 way Tag-Connect attached to target board and retained by clip
If you want to work for longer, a more secure option is to use a version of the plug with "legs" that clip into additional holes on the board.

Tag-Connect version with legs for longer term attachment
Be careful about your PCB layout - Tag-Connect provide advice on this subject. And remember that the socket pins on the retaining clip may touch down on the back surface of your PCB; keep tracks and vias out of these areas to avoid mysterious and intermittent short circuits!

TC2050 land pattern with leg holes, showing escape routing
So the Tag-Connect approach saves space as well as the cost of purchasing and fitting a physical connector. And because not everybody has a Tag-Connect cable, or knows your pin-out, it can also add a little bit of security-through-obscurity.

Thanks to Chris Monslow at Kielowatts for pointing me at Tag-Connect.

Wednesday 30 March 2016

Switching Mains Loads with Relays

I want to control the external lights around my home from a small computer to provide a bit of automation. The plan is to use an Arduino, and have it switch the lights on and off via relays. There are plenty of low cost relay boards to choose from. Most seem to be clones of the same basic designs which offer either 2, 4 or 8 relays. Here's a typical 4 way board:

4 Way Relay Board
4 Way Relay Board
This board has a 2.54mm pitch pin header with 6 pins - ground, +5VDC power and 4 inputs that control the coils of the 4 relays. Each relay is provided with an individual 3 way screw terminal block that is wired to its common, normally open and normally closed contacts. Note that these terminals are big enough for 1-1.5mm solid wire and the relays are rated for up to 10 Amps. My advice is to stay way below this.

The inputs are protected from the "heavy lifting" of energising the relay coils by opto-isolators. Grounding an input pin allows current to flow from the +5VDC supply through a current limiting resistor, a surface mount red LED, and then the LED within the opto-isolator. The forward current is about 2mA in this situation so it's fine to directly connect these inputs to digital I/Os on an Arduino. The relay coils are wired to the +5VDC supply and the opto-isolator phototransistor collectors, and each is provided with a usual flyback diode. (Note that the +5VDC supply might get in the way of using one of these boards with a Raspberry Pi; these use 3.3V digital I/Os and could be damaged by higher voltages.)

So far I've built a box with an 8 way relay board and connected it to 8 external lamps. A small AC-DC module provides +5VDC locally; I will locate the control system elsewhere, with the link to the relay box containing just relay control lines and ground in a multi-core cable.

8 Way Relay Board - Driving Lights
8 Way Relay Board - Driving Lights
Working on electrical installations can be dangerous and is heavily regulated by law. Consult a qualified electrician!

Tuesday 15 March 2016

12 Volt DC PIRs for Outdoor Use

I've wanted to automate the operation of some external lights in my home for a long time, and PIR motion sensors are a must. I already have several as part of an intruder alarm system, but they are not rated for outdoor use; electronics that is typically uses components with wider than normal operating temperatures (e.g. -40 to +85 degrees Celsius instead of 0 to +70), and conformal coating is often used to protect circuitry from moisture (condensation).

When I first looked for external PIRs (several years ago), I found that almost every one of them was designed to be powered by the mains, and to switch a mains load (a lamp). But I need to drive the inputs of a microprocessor based control system from the PIR, so I would prefer a contact closure (volt free) output. I did find one or two low voltage DC units, but they were horrendously expensive (nearly 100 GBP).

A more recent search turned up a much more reasonable solution:

12V DC Outdoor PIR Motion Sensor
12V DC Outdoor PIR Motion Sensor

This unit retails for under 25 GBP from Solar and Wind Power Systems. It is IP44 rated, runs from a 12 Volt (AC or DC) power supply and has a relay that can switch up to 10 Amps. It allows adjustments to on-time, range (sensitivity) and ambient light.

Note that the unit is supplied with a 4 way terminal block that is quite large (appropriate for 10 Amps). I swapped this for a smaller one. Also, the knock-outs molded into the ABS plastic housing are quite difficult to remove - I resorted to drilling them out.

Here's a video of a quick test of one. In this setup, the ambient light adjustment is at maximum (to allow daylight operation), the range/sensitivity is low, and the on-time is at a minimum - corresponding to about 5 seconds. The power supply is 12VDC, and the output is wired to ground the cathode of a blue LED - the anode is wired to 12V via a 470R resistor.



Notice that the unit's output remains on while the PIR is detecting motion, and stays on afterwards for 5 seconds.

I checked the range quickly in this setup, and detection worked reliably at 4 meters in daylight.

Wednesday 9 March 2016

Arduino 16x2 LCD/Keypad Shield

Many embedded projects benefit from a user interface, and shields with a 16x2 LCD and a 5 button keypad are popular with Arduino users. Most are almost exactly like this one. As with many Arduino peripherals, they are very inexpensive - less than 6 GBP at the time of writing for the one I chose with first class postage within the UK, less still if you can wait for one from China.

Arduino LCD/keypad Shield
Arduino LCD/keypad Shield
Boards such as this are often referred to as "1602A" type, with various manufacturers adding various prefixes and suffixes. They all seem to be based on the Hitachi HD44780 LCD controller (or a compatible clone). And most seem to use a 4-bit parallel interface to this controller (which can also support 8-bit operation). The keypad buttons are wired with a resistor ladder between the power rails so that a unique voltage corresponding to each button is delivered into one of the MCU's ADC inputs.

There are various examples and drivers available for 1602A display/keypad boards running on the Arduino, but I wanted to understand it from first principles, so I coded my own simple driver in C after studying the controller datasheet and the board schematic. This allows you to clear and write strings to the display, and read debounced key presses. I wrote a quick demo program in C using Atmel Studio 7 for this which you can download here.

Note that the documentation is not reliable when it comes to the character set burned into the controller's ROM. The upper 128 character codes in my module did not match the data sheet, so - for example - I had to create a user defined character to get a "degree" symbol for the temperature reading shown in the above picture.

Here's a video showing the demo program running:


LED Brightness Control from an Arduino with PWM

I wanted to be able to control the brightness of an LED backlight in some pushbuttons. The AVR microcontroller on an Arduino has hardware timers with a Pulse Width Modulation (PWM) feature that allows you to send a regular stream of pulses out of a pin with control of the ratio of on time to off time (the mark/space ratio). This is a well established way of controlling LED brightness.

After setting up the AVR timer correctly, you write a value to its output comparison register (OCR) to control the mark/space ratio. A minor catch is that the ratio can be varied between 1:255 and 256:0 (for the 8-bit case) so the output can be fully on, but not quite fully off - indeed you see a perceptible but faint glow from the LED when the OCR is written with zero. My fix to this was to adjust things so the mark/space ratio can be varied between 0:256 and 255:1; the fact that "fully on" is no longer quite possible is imperceptible. This is accomplished by writing the brightness level minus one to the OCR, and treating zero as a special case - by turning off the output pin (via its Data Direction Register), relying on an external pulldown to keep the pin low.

I built a very simple driver circuit on a breadboard with a 2N7000 MOSFET; the Arduino drives its gate, which is pulled down with a 10k resistor. The source is grounded and the drain connects to the LED cathode. The LED anode connects to +12VDC via a 470R resistor which sets the forward current at about 20mA (the forward voltage is about 3V).

I wrote a quick test in C using Atmel Studio 7 - you can download it from here. And here's a video of the result, showing a fade up, a fade down, a sharp on transition, and a sharp off transition:


The fading effect looks much better to me.

Tuesday 8 March 2016

Arduino Real Time Clock

I needed an accurate real time clock for an Arduino based home automation project; many are I2C controlled and based on Maxim's DS3231 which is achieves an accuracy of about 1 minute per year (2ppm) through temperature compensation - a potentially useful side effect of this is that the part provides a temperature reading. Most boards also include an I2C EEPROM. I found a seller on eBay offering 3 units for under 5 GBP, including next day postage:

Real Time Clock and EEPROM board
Real Time Clock and EEPROM board

The board provides a header with 6 pins:
  • GND - ground
  • VCC - power (3.3V or 5V)
  • SCL - I2C clock
  • SDA - I2C data
  • SQW - programmable interrupt/square wave output
  • 32K - free running 32kHz clock output
There's a holder for a CR2032 coin cell on the reverse, to provide battery backup. Note that these are typically not included with the boards (there are international restrictions on shipping lithium batteries).

I hooked it up to my Arduino Mega 2560 with male-female flying leads: I wired GND and VCC to GND and 5V on the power header, SCL and SDA to their counterparts on the communication header, and the SQW output to the INT3 input.

I then wrote a quick program in to test the board (I prefer to code in C using Atmel's Studio for AVR microcontroller development, for more on this see here.) This used the nice, stable and simple I2C master driver written by Peter Fleury. Note that I ignored the board's EEPROM.

The program prints the current time, day, date and temperature once a second:

       
RTC test
time: 12:14.44   day: TUE   date: 08/03/2016   temperature: +24.00
time: 12:14.45   day: TUE   date: 08/03/2016   temperature: +24.00
time: 12:14.46   day: TUE   date: 08/03/2016   temperature: +24.00


The program uses the Arduino's USB serial port for console I/O, based on Mika Tuupola's recipe here. I use TeraTerm on a desktop Windows PC for this, connected to the Arduino's COM port at 115200 baud.

You can download a ZIP of the Atmel Studio 7 project from here.