Programming_the_Built-in_Hardware
This chapter describes how to use Verilog to access the built-in hardware on the BlackIce II board.
This built-in hardware covered consists of:
The 4 user LEDS
The two user buttons
The 4 DIP switches
The UART
Memory access including accessing the SRAM, and access to the SD card reader is covered in later chapters.
Development environment
All the projects are built using the open source icestorm tools: yosys, arachne-pnr, and icepack, and Makefiles are used to build the bit streams to configure the Ice40 FPGA.
Instructions for setting the tools up for BlackIce II are here.
Each project has its own directory contains the Verilog (.v) files, a .pcf file that maps pin names onto physical pin numbers, and a Makefile of the form:
Where blackice.mk is:
LEDs
The BlackIce II board has 4 built in LEDs that are available to the FPGA:
A blue LED, labelled LED1, with pin number 71;
A green LED, labelled LED2, with pin number 67;
An orange LED, labelled LED3, with pin number 68;
A red LED, labelled LED4, with pin number 70.
Turn on an LED
You should create a development directory for running the examples in this book. Put the blackice.mk file given above in that directory.
Inside that development directory, make a directory called led, and in it add the following files.
You need a pcf file, led.pcf, to give the pin a name:
And a Verilog file, led.v:
And a Makefile:
Before building this example, you should do:
This lets you see messages from the iceboot software when you upload bitstreams.
To run this example, type:
You should see messages on the iceboot console including the version number of iceboot and “Config done”. You may also see “Setup done” and “Waiting for serial”.
When configuration is successful the green (DONE) LED will be on and the red (DBG1) LED will be off.
Your design should then run, and the blue LED should turn on. The other LEDs may be either on or off or floating depending on their previous state. It is therefore more sensible to program all 4 LEDs as an array – see the next section.
before you run “make upload”.
If the config fails for any reason, the green (DONE) LED will be off and red (DBG1) LED will be on. DBG1 comes on while the config is in progess.
Config will fail if /dev/tyyACM0 has not been set to raw, or if the bitstream (chip.bin) is invalid in some way. After a config failure, you will need to press the reset button before you try again. Config can also fail if you have removed the jumper from the RPi header so you are in DFU and not normal mode. If can fail if the internal mux on the board is enabled and switched to the RPi header, but that only happens if you are using non-standard firmware.
Another problem that can occur on Linux machine is that a program called modemmanager is running and accessing /dev/ttyACM0. If modemmanager is installed on your Linux machine, you should uninstall it, disble it ot stop it while you are doing BlackIce development.
An array of LEDs
You can address all 4 LEDs at once. Make a directory called led and in it add:
leds.pcf:
leds.v:
Makefile:
Buttons
The BlackIce II board has two built-in buttons available to the FPGA.
Button 1, pin 63
Button 2, pin 64
Light an LED when button pressed
Make a directory called button and in it add: button_test.pcf:
button_test.v:
Makefile:
If you need more buttons for your project, you can buy the Digilent Pmod BTN, which has 4 buttons.
Debouncing
Accessing buttons as in the way given by the previous example is not recommended as a button takes a while to stabilise when it is pressed and if this is not programmed for, a single button press can appear as multiple presses.
Coping with this behaviour is known as debouncing the button.
There is an article on this at fpgafun.com.
To see the problem, lets implement a simple button press module and use the 4 leds as a counter:
Make a directory called bounce and add:
bounce.pcf
bounce.v
We use negedge as the button is pulled low when pressed.
Build and upload in the normal way and you should see the led counter increasing by more than one per press.
To fix this, we will use the debouncer from fpgafun.com.
So, create a directory called debounce and add:
debounce.pcf:
Then add the debouncer from fpgafun.com:
PushButton_Debouncer.v:
Then, to test it add debounce.v:
and a Makefile:
When you make and run this you should see the led counter increase by 1 for each button press.
Using the DIP switches
The BlackIce II board has 4 built in tiny slider switches on pins 37, 38, 39 and 41.
They can be used for configuration settings, but the pins are also used for some other purposes such as SD card access, so care must be taken using them.
If you need more switches, you can buy the Digilent PmodSwt 4 slider switch Pmod.
The following example sets the LEDs according to the switch setting.
Make a directory called switches and in it add:
switch_test.pcf:
And then add a Makefile and run it in the normal way.
PWM
Pulse width modulation (PWM) is a technique to vary the power output on a digital pin by turning it on and off in pulses. A square wave of a specific frequency is sent to the pin and the length of time it is set high for each period is called the duty cycle.
This technique can be used to specify the position of servo motors, the speed of gear motors, or the volume of audio (see 1-bit DAC below). It is a sort of digital equivalent of specifying the voltage level for an analog output, and can sometimes be used for the same purpose, avoiding the need for digital to analog converters.
Here we will use it to set the brightness of a built-in LED.
Make a directory called LEDglow and in it add:
LEDglow.pcf
LEDglow.v
Makefile:
Then run the Makefile in the normal way. You will see the blue LED glowing.
UART
The BlackIce github sites has a set of example programs including comprehensive example of use of the uart.
The uart is connected to pins 85 and 88 of the Ice40 and the RTS pin can be used as a reset and is connected to pin 128 (gReset).
The HelloWorld example using just the TX pin and gReset. It writes “Hello World!\n” to the uart at 115200 baud every one and a half seconds.
The uart_loopback example does both reading and writing. It reads from the uart and echoes back what it reads at 115200 baud.
The uart is useful for debugging Verilog program. Here is an example of using a debug module.
Last updated