Silicon ChipiCEstick - May 2020 SILICON CHIP
  1. Outer Front Cover
  2. Contents
  3. Subscriptions: PE Subscription
  4. Publisher's Letter: Publisher's Statement
  5. Publisher's Letter
  6. Feature: The Fox Report by Barry Fox
  7. Feature: Techno Talk by Mark Nelson
  8. Feature: Net Work by Alan Winstanley
  9. Project: 433MHz Wireless Data Range Extender by John Clarke
  10. Project: Bridge-mode Audio Amplifier Adaptor by NICHOLAS VINEN
  11. Project: iCEstick by Tim Blythman
  12. Project: Ultra-low-distortion Preamplifier with Tone Controls by John Clarke
  13. Feature: Circuit Surgery by Ian Bell
  14. Feature: PIC n’Mix by Mike Hibbett
  15. Feature: Make it with Micromite by Phil Boyce
  16. Feature: AUDIO OUT by Jake Rothman
  17. Feature: Visual programming with XOD by Julian Edgar
  18. Back Issues by Julian Edgar
  19. Feature: Max’s Cool Beans by Max the Magnificent
  20. PCB Order Form
  21. Advertising Index

This is only a preview of the May 2020 issue of Practical Electronics.

You can view 0 of the 80 pages in the full issue.

Articles in this series:
  • Techno Talk (May 2020)
  • Techno Talk (May 2020)
  • Techno Talk (June 2020)
  • Techno Talk (June 2020)
  • Techno Talk (July 2020)
  • Techno Talk (July 2020)
  • Techno Talk (August 2020)
  • Techno Talk (August 2020)
  • Techno Talk (September 2020)
  • Techno Talk (September 2020)
  • Techno Talk (October 2020)
  • Techno Talk (October 2020)
  • (November 2020)
  • (November 2020)
  • Techno Talk (December 2020)
  • Techno Talk (December 2020)
  • Techno Talk (January 2021)
  • Techno Talk (January 2021)
  • Techno Talk (February 2021)
  • Techno Talk (February 2021)
  • Techno Talk (March 2021)
  • Techno Talk (March 2021)
  • Techno Talk (April 2021)
  • Techno Talk (April 2021)
  • Techno Talk (May 2021)
  • Techno Talk (May 2021)
  • Techno Talk (June 2021)
  • Techno Talk (June 2021)
  • Techno Talk (July 2021)
  • Techno Talk (July 2021)
  • Techno Talk (August 2021)
  • Techno Talk (August 2021)
  • Techno Talk (September 2021)
  • Techno Talk (September 2021)
  • Techno Talk (October 2021)
  • Techno Talk (October 2021)
  • Techno Talk (November 2021)
  • Techno Talk (November 2021)
  • Techno Talk (December 2021)
  • Techno Talk (December 2021)
  • Communing with nature (January 2022)
  • Communing with nature (January 2022)
  • Should we be worried? (February 2022)
  • Should we be worried? (February 2022)
  • How resilient is your lifeline? (March 2022)
  • How resilient is your lifeline? (March 2022)
  • Go eco, get ethical! (April 2022)
  • Go eco, get ethical! (April 2022)
  • From nano to bio (May 2022)
  • From nano to bio (May 2022)
  • Positivity follows the gloom (June 2022)
  • Positivity follows the gloom (June 2022)
  • Mixed menu (July 2022)
  • Mixed menu (July 2022)
  • Time for a total rethink? (August 2022)
  • Time for a total rethink? (August 2022)
  • What’s in a name? (September 2022)
  • What’s in a name? (September 2022)
  • Forget leaves on the line! (October 2022)
  • Forget leaves on the line! (October 2022)
  • Giant Boost for Batteries (December 2022)
  • Giant Boost for Batteries (December 2022)
  • Raudive Voices Revisited (January 2023)
  • Raudive Voices Revisited (January 2023)
  • A thousand words (February 2023)
  • A thousand words (February 2023)
  • It’s handover time (March 2023)
  • It’s handover time (March 2023)
  • AI, Robots, Horticulture and Agriculture (April 2023)
  • AI, Robots, Horticulture and Agriculture (April 2023)
  • Prophecy can be perplexing (May 2023)
  • Prophecy can be perplexing (May 2023)
  • Technology comes in different shapes and sizes (June 2023)
  • Technology comes in different shapes and sizes (June 2023)
  • AI and robots – what could possibly go wrong? (July 2023)
  • AI and robots – what could possibly go wrong? (July 2023)
  • How long until we’re all out of work? (August 2023)
  • How long until we’re all out of work? (August 2023)
  • We both have truths, are mine the same as yours? (September 2023)
  • We both have truths, are mine the same as yours? (September 2023)
  • Holy Spheres, Batman! (October 2023)
  • Holy Spheres, Batman! (October 2023)
  • Where’s my pneumatic car? (November 2023)
  • Where’s my pneumatic car? (November 2023)
  • Good grief! (December 2023)
  • Good grief! (December 2023)
  • Cheeky chiplets (January 2024)
  • Cheeky chiplets (January 2024)
  • Cheeky chiplets (February 2024)
  • Cheeky chiplets (February 2024)
  • The Wibbly-Wobbly World of Quantum (March 2024)
  • The Wibbly-Wobbly World of Quantum (March 2024)
  • Techno Talk - Wait! What? Really? (April 2024)
  • Techno Talk - Wait! What? Really? (April 2024)
  • Techno Talk - One step closer to a dystopian abyss? (May 2024)
  • Techno Talk - One step closer to a dystopian abyss? (May 2024)
  • Techno Talk - Program that! (June 2024)
  • Techno Talk - Program that! (June 2024)
  • Techno Talk (July 2024)
  • Techno Talk (July 2024)
  • Techno Talk - That makes so much sense! (August 2024)
  • Techno Talk - That makes so much sense! (August 2024)
  • Techno Talk - I don’t want to be a Norbert... (September 2024)
  • Techno Talk - I don’t want to be a Norbert... (September 2024)
  • Techno Talk - Sticking the landing (October 2024)
  • Techno Talk - Sticking the landing (October 2024)
  • Techno Talk (November 2024)
  • Techno Talk (November 2024)
  • Techno Talk (December 2024)
  • Techno Talk (December 2024)
  • Techno Talk (January 2025)
  • Techno Talk (January 2025)
  • Techno Talk (February 2025)
  • Techno Talk (February 2025)
  • Techno Talk (March 2025)
  • Techno Talk (March 2025)
  • Techno Talk (April 2025)
  • Techno Talk (April 2025)
  • Techno Talk (May 2025)
  • Techno Talk (May 2025)
  • Techno Talk (June 2025)
  • Techno Talk (June 2025)
  • Techno Talk (July 2025)
  • Techno Talk (July 2025)
Want to give a project the retrocomputer look? Or do you just need a convenient way to display a screen full of text on a low-cost monitor? Then this nifty project is for you. It generates a VGA signal akin to something from an early PC, or even a Commodore 64 or Amiga. It does this using a low-cost iCEstick FPGA development board and a very simple add-on board and is controlled via a serial port. iCEstick Part 2 – creating an FPGA VGA Terminal F ollowing on from our review of the iCEstick and IceStudio software in last month’s issue, we wanted to see if we could do something more useful and exciting than flashing an LED. After all, field programmable gate arrays (FPGAs) are considerably more capable than microcontrollers. So we had to think of an application that couldn’t be done with a 555 timer IC or the most basic micro you can buy! So we’ve come up with some ‘code’ which configures the FPGA chip (an iCE40HX-1k) on the iCEstick to generate VGA-compatible video signals using the eight digital outputs available on its PMOD connector. The output is displayed as 16 rows and 32 columns of text, with selectable foreground and background colours for each 8 × 8 pixel character. The colours come from a palette of 16, chosen from 64 possibilities. The graphics ROM includes pseudo-graphics characters to create block graphics, boxes and shaded regions. The module is controlled by a serial (UART) data line running at 9600 baud which accepts regular ASCII characters, LF, CR and FF control codes, as well as the pseudographics above ASCII code point 127. There are also control codes to set the colours. 30 This project could be used as the starting point of a more ambitious FPGA-based project, or you could combine it with a microcontroller of your choice, using the serial port as your micro’s display interface to the VGA monitor, to display text and graphics. Note that when it comes to FPGAs, it no longer makes sense to refer to the code as ‘software’. The IceStudio software takes our HDL (hardware description language) and synthesises it into a bitstream. This bitstream could be considered an equivalent to a binary firmware image; it can be stored in a computer file or uploaded to an EEPROM on a target system. But rather than being a sequence of instructions for a processor to execute, it describes how the various elements within the FPGA are connected or configured. For more detail on this aspect, see last month’s tutorial. by Tim Blythman For this article, we’re providing a complete IDE project which you can open up and use straight away. But it’s also a great starting point for experimentation, and a wonderful tool for learning about how FPGAs work (and about digital logic in general). Circuit description Most of the hardware required is on the pre-built iCEstick module. A small breakout board that we’ve designed plugs into the 12-pin PMOD connector, converting the digital signals from the iCEstick into signals which are fed to the VGA connector, to generate VGA video. The circuit diagram of this add-on board is shown in Fig.1. The horizontal synchronisation (HSYNC) and vertical synchronisation (VSYNC) lines are effectively fed digital pulses via series resistors, which provide a degree of protection to the FPGA in case of static electricity and so on. The red, green and blue VGA signals are formed by primitive 2-bit DACs, made using pairs of resistors in a 2:1 ratio, giving four evenly spaced voltage levels between fully off and fully on. For example, if pins 3 and 9 of CON1 are held low (0V), then 0V is applied to pin 2 of CON2, the green signal. If both these pins are high (3.3V), then pin 2 of CON2 is at 3.3V. If pin 3 of CON1 is Practical Electronics | May | 2020 Here’s the complete (!) project attached to the iCEstick, which in turn plugs into a free USB socket. 7 2 8 3 9 4 10 5 11 6 12 Fig.1: the circuit for our VGA Adaptor is TO iCEstick delightfully simple, since so much of the hard work is done SC by reconfiguring the 20 1 9 blocks inside the FPGA. Three resistive two-bit DACs are formed by the 1.1kand 560resistors, to control the red, green and blue voltage levels on the VGA connector. The HSYNC and VSYNC pulses are digital signals fed straight to the VGA socket, with 68 series resistors for safety. The unusual pin numbering of CON1 is to match the numbering on the iCEstick; they are treated as two side-by-side SIL headers, even though it’s physically a DIL header. CON1 6 VGA OUTPUT CON2 560 RED 1.1k GREEN 560 BLUE 1.1k 560 6 1 7 2 8 3 9 4 10 5 1.1kΩ 11 12 13 HSYNC 14 VSYNC 15 2x 68 iCEstick VGAVGA Adaptor icestick ADAPTOR Practical Electronics | May | 2020 1 2 3 4 560Ω CON2 VGA out 68Ω CON1 Generating the clocks The iCEstick only has a 12MHz oscillator, so we need to use the iCE40HX-1k’s phase-locked loop (PLL) to bring that up to around 25MHz. We are generating a 100.5MHz signal, which we divide by four to get 25.125MHz. This is the closest the PLL can get to our target frequency of 25.2MHz, using a 12MHz source. This small error doesn’t end up causing any problems. This clock signal is divided by a factor of 800 in the FPGA, to give a 31.4kHz line clock, then again by 525 to give the frame/screen refresh clock of 59.8Hz. That’s 0.2Hz slower than our target of 60Hz, but it isn’t uncommon to see video refresh rates that are not an exact number of hertz, and virtually all monitors will handle this. We have created a 10-bit horizontal pixel counter in the FPGA which starts at zero and counts up to 799, incrementing on each clock pulse (at 25.125MHz), then resets back to zero. Each time it resets, the 10-bit vertical pixel counter is incremented, and it’s reset to zero as soon as it exceeds 524. 1.1kΩ 1.1k 1 the VSYNC pin is pulsed every vertical scan (ending a frame). 560Ω 7 1 (under) to iCEstick 1.1kΩ 560Ω 68Ω Operating principles We’re generating a 640 × 480 pixel VGA signal, which involves scanning 800 × 525 pixels. The extra pixels are hidden in black borders outside the normal display area of the screen (in the front/back porch and rescan areas). For a standard 60Hz monitor update rate, we need a 25.2MHz pixel clock (800 × 525 × 60Hz). Our alphanumeric terminal occupies a central 512 × 384 pixel region of the 640 × 480 display image, with black borders around the edge. We’ve done this because the 512 × 384 pixel region maps to 32 × 16 alphanumeric characters, and 32 × 16 = 512 which is the number of bytes in each block of RAM within the FPGA. It would be possible to combine multiple RAM blocks to allow a larger character display (possibly filling the screen), but that would complicate the code design somewhat. Making the relevant changes could be a good exercise for readers who really want to delve into FPGA programming. The FPGA scans the 800 × 525 area, uses its video RAM to determine which character should be displayed at any given point, then uses the font ROM to determine whether the foreground or background colour should be displayed for each pixel. The HSYNC signal is pulsed at the end of each horizontal scan (ending a line), and 12 high (3.3V) and pin 9 is low (0V) then the voltage divider formed by the 560Ω and 1.1kΩ resistors means that around 2.2V is fed to pin 2 of CON2, while if those voltages are reversed, pin 2 is at around 1.1V. By using various combinations of levels on the red, green and blue lines, we can generate 4 × 4 × 4 = 64 different colours on the screen. The 560Ω and 1.1kΩ resistor values have been chosen to avoid exceeding the FPGA’s 8mA per pin sink/source current rating. We found that on some monitors, this resulted in colours which were a bit dark, so you may wish to try slightly lower values (eg, 470Ω and 910Ω or 430Ω and 820Ω). If you are unsure, stick with the suggested values. All timing and signal generation is done within the FPGA. We won’t claim the output is fully VGA compliant, but we have had no troubles using it with a few different monitors we tested. SC 20 1 9 Fig.2: fit the resistors to the PCB as shown here, then the VGA socket, which goes on the same side as the resistors, and finally the 6 × 2 pin header, on the opposite side. The resulting assembly then plugs straight into the iCEstick and a standard VGA monitor cable. 5 6 7 8 9 10 11 12 13 14 15 VGA socket – looking at pins. 31 Screen1: this is a broad map of the functional parts of the ‘iCEstick VGA Terminal.ice’ project. You will need to install IceStudio, download and open that file and zoom in to see the detail of each block. So these two counters allow us to keep track of which pixel is currently being emitted. When these pixel values are within the 512 × 384 active area in the middle of the screen, they are further divided by 16 (horizontal) and 24 (vertical) to determine which character position is currently being displayed. The FPGA then retrieves the 8-bit ASCII character value and two 4-bit colour (background/ foreground) values from its video RAM. The 4-bit colour values are then used to look up the 16-entry palette to determine the 6-bit colour values to use as the foreground and the background for the character currently being emitted. Similarly, the ASCII character value is used to look up an entry in the font ROM. All these lookups culminate in a pixel colour value which is then fed to the RGB outputs (pins 2-4 and 8-10). At the same time, the HSYNC (pin 1) and VSYNC (pin 7) lines are driven based on the horizontal and vertical counters, to generate the required sync pulses for the monitor. In more detail, when the horizontal pixel counter is between 0-511, that is the active part of the display, and the RGB outputs are driven. The rest of the time, the RGB outputs remain low, so the front porch, back porch and borders are black. When the horizontal counter is between 592 and 688, pin 7 is set high, creating the HSYNC pulse. Similarly, the vertical (line) pixel clock counts from zero to 524, with the RGB outputs active from 0-383, and VSYNC is driven high on lines 443-445. The lines between 446 and 524 are the vertical refresh period, so the RGB outputs remain low. Fig.3: this shows how font glyphs are converted into bitmap values, by adding the value of the pixels that should show the foreground colour. IceStudio expects hexadecimal numbers in the font ROM, so you will need to convert the decimal sums to hexadecimal format (eg, using a ‘programmer’s calculator’). 32 These sync values have been chosen by trial and error, to centre the display on our test monitor. They can be changed in the FPGA configuration to adjust the location on your monitor, although the differences between the values should remain the same to maintain the same sync pulse widths. Implementing this in the FPGA We’re using the IceStudio software to demonstrate what can be done using this software, and while the IceStudio project looks quite complicated, it can be broken down into small, easy-tounderstand functional blocks that each accomplish one small task. We hope this gives you an insight into just how easy it is to jump into creating your own FPGA projects with Verilog inside IceStudio; do keep in mind as you work with FPGAs that the outcome is actually an arrangement of logic gates and flipflops that all work simultaneously, rather than code that is processed in sequence. Screen1 shows the IceStudio project in its entirety. The FPGA is configured by connecting various blocks together, and we’ve labelled groups of blocks to indicate their purpose. If you want to examine the design in more detail as we explain what each block does, skip to the section below titled ‘Installing the software on your computer’, then come back and read the following description. Practical Electronics | May | 2020 Screen2: if you have successfully built the hardware and programmed the FPGA, you will be greeted by this display on your VGA monitor. Clock generation is performed by the area marked PLL in the project window. The code in this block contains synthesiser directives that describe how to configure the PLL. The iCEcube2 software that we reviewed in last month’s Part 1 is capable of generating PLL configuration data if you want to experiment with this block. To the right of the PLL block and left of the HSYNC/VSYNC sections are the clock dividers. The small blue block divides the 100.5MHz clock by four to give the 25.125MHz pixel clock, which is then divided by 800 to give the line clock. This is in turn divided by 525 to give the frame clock. The ACTIVE VIDEO DETECT section compares the pixel and line clocks to the fixed values indicated above, producing two outputs which are both high when the current pixel is part of the 512 × 384 pixel active area. These are fed to the colour decoder, which generates black unless both (horizontal and vertical) active video bits are set. Below ACTIVE VIDEO DETECT is a section which divides the pixel count by two to create indexes for the font ROM. The line count is effectively divided by three, to create the vertical font index. But rather than using a divider, which would be quite large and complex to implement in the FPGA, instead, a separate counter is used, which is only incremented on every third pulse from the line clock, then reset when it reaches 128 (ie, 384 ÷ 3). Serial data handling The FPGA needs to accept serial data from the host, both for configuration and to update the displayed characters and/or colours. The UART block is shown to the left of the PLL in Screen1. This is made using opensource Verilog code that is available at. https://github.com/cyrozap/osdvu, which also includes a description of how to interface to it. We don’t need to send any data back to the host, so we removed the Practical Electronics | May | 2020 Screen3: in the window that appears after clicking View → Command Output, the folder containing the generated Verilog file is visible (highlighted section). Open this folder and find the file named ‘main.v’, which is the generated Verilog equivalent of the IceStudio project. transmit-specific sections, to save FPGA resources. While a microcontroller would wait and then branch to code to read from a buffer when the host is sending data to it, the FPGA is always ready to react, and the data from the UART is put into the video RAM within nanoseconds of it arriving, simultaneously with the video output tasks occurring elsewhere on the chip. The UART decoder filters the incoming serial data and also holds a video RAM pointer. This filtering checks the three high-order bits of each received character. If all of these are low, then the received serial data ASCII value is less than 32. That means that it is a control byte and processed as such. The control bytes work as follows. A carriage return (code 13) causes the video RAM pointer to be reset to the start of its line by ANDing its value with 32. A line feed (code 10) moves the pointer to the next line by adding 32, and a form feed (code 12) moves the cursor to position zero by resetting the pointer, as though starting a new page. If the received data value is 32 or higher (and thus an ASCII character), the received character is written to the video RAM at a position corresponding to the pointer’s value and the pointer is incremented by one. Thus, characters received consecutively appear at consecutive locations on the display. The currently selected foreground and background colour combination is also written to a separate RAM which is used to later decode the colour data for display. Other control codes are decoded by the small block to the left of the colour decoder. Code 14 sets a flag so that the background colour is set, while code 15 sets the flag to the foreground. If a value from 16 to 31 is received, it is sent to the foreground or background register per the flag. Because all except the lower four bits are ignored here, code 16 selects colour 0 and code 31 selects colour 15 from the palette. Screen6 shows the default palette of colours that are available. The video RAM section takes an address value made from combining parts of the horizontal and vertical ‘scan’ position. The small code box on the left just combines the bits to create a linear address. Video RAM The larger box is the video RAM itself. This has been coded in a specific way to use part of the iCE40HX-1k’s BRAM (block RAM). If not done in quite the right way, the memory is synthesised from flip-flops instead of using the dedicated block RAM. This alternative is a very poor use of resources; as an experiment, we tried this, and found that the 512 bytes of RAM took about half of the FPGA’s flip-flop resource. The iCE40HX-1k contains 16 separate 512-byte blocks of double-ported RAM. The double-port feature means that it can be read and written at the same time, which is essential in our application because we may be trying to change the display at the same time that the VGA display logic is reading from it (as it is reading video RAM almost constantly). The small beige block above the video RAM initialises it at startup to display some splash-screen text. If you Parts list iCEstick VGA Terminal 1 Lattice iCEstick FPGA development board [Mouser 842-ICE40HX1KSTICKEV, Digikey 220-2656-ND] 1 double-sided PCB, code 02103191, 49.5 x 32mm [PE PCB Service] 1 2x6 male pin header (CON1) 1 DE-15 (or HD-15) high-density 15pin female D-connector (CON2) [AMP 1-1734530-1, MULTICOMP SPC15430] Resistors (all 1/4W 1% metal film) 3 1.1kΩ 3 560Ω 2 68Ω 33 Screen4: the default character map/font for the iCEstick VGA Terminal. It can be changed by editing the font ROM blocks. The first three lines are the standard ASCII characters at positions 32-127, followed by some pseudo-graphics characters that can be used to draw boxes, bar graphs and so on. don’t want this, replace the contents of the beige block with zeroes, or your own hexadecimal values for a custom splash screen. The small block to the right of the video RAM generates an address into the font ROM, based on the displayed character value from video RAM and the vertical position of the scan. Font ROM The font ROM consists of three BRAM blocks, each fed by a separate initialising block. While implemented using RAM blocks, there are no connections to the write lines, so they remain unchanged as long as the FPGA is powered, and are effectively read only. By using multiple BRAM blocks and a four-way multiplexer, we can overcome the 512-byte limit of each block (hint: this might be a good way to expand the video RAM). Each BRAM block encodes 64 characters in eight bytes each, for a total of 512 bytes. There’s room to add a fourth BRAM block below, but we only need 192 characters in the font ROM, so we have not done so. Each byte of the font ROM encodes a horizontal line of eight pixels as a bitmap. The small block next to the font ROM decodes the horizontal character sub-position into a single bit; it is effectively an eight-to-one multiplexer. The output of the font ROM is a single bit indicating whether the foreground or background should be displayed for the current pixel. Colour In a similar fashion to the way the video RAM is read, data is read from the colour RAM to determine the combination of foreground and background colours to be displayed at the current scan position. This is a separate RAM block that uses the same address and clock lines as video RAM as its input. 34 The output of the colour RAM is fed to the colour decoder. The colour decoder has a pair of small 6 × 16 bit ROMs, which are initialised by the beige blocks above them. These decode the 4-bit colour palette index value into the necessary output pin states to generate that specific colour in the palette. The two blocks are identical; one is used to decode the foreground colour and one the background colour, to simplify the following logic. The colours have been chosen based on those used in the venerable Commodore 64, which also had a 16-colour display. To the right of the ROMs are a row of multiplexers, one for each output pin involved in driving the VGA colour lines. The multiplexer chooses between the foreground and background colours according to the line from the font ROM. This is followed by an AND gate. The data from the multiplexer is ANDed with a bit that indicates if the current scan position is inside the central 512 × 384 pixel box, in which case the foreground or background colour is produced. Otherwise, the result is low, so the outputs of all the AND gates are low and therefore all the output pins are low and black is displayed. Finally, a D-flipflop is used to buffer this signal into the output pins, so that their states only change on the pixel clock. This ensures our pixels are not subject to jitter and thus line up squarely on the screen. The result is a very stable display. Screen5: the RX (receive) pin of the UART module can be changed using this drop-down box. Not all pins in the list can be used; for example, we are already using all the PMOD pins for the VGA output. Installing the software on your computer To build this project, you need to install the IceStudio integrated development environment (IDE) software. There are versions available for Linux, Windows and macOS. If reading last month’s Part 1, an FPGA tutorial, then you may have already installed it. Otherwise, follow the installation instructions at: https:// github.com/FPGAwars/icestudio We used version 0.4.0. Once installed, you should also install the toolchain and enable the driver for the iCEstick (only needed on Windows). If you’re unsure how to do this, read the aforementioned tutorial, which explains this in detail, or read the IceStudio documentation at: https:// icestudio.readthedocs.io/en/latest/ Now download the iCEstick VGA Terminal.ice file from the May 2020 page of the PE website and open it in IceStudio. You will see something similar to what’s shown in Screen1, and you can now examine the blocks in closer detail. If you need to change any of the configuration parameters, such as the serial port baud rate, these are ‘hard coded’ into the project, so you will need to change the .ice file using the IDE graphical interface. Other settings that can be changed include the colour palette and font glyphs. Details on how to change all these parameters are given below. By default, the serial interface is connected to iCEstick’s USB/serial Practical Electronics | May | 2020 Screen6: these are the colour combinations that can be displayed by the iCEstick VGA Terminal. The characters shown at each column are combined with the Control key to create the foreground colour shown in many serial terminal programs. These 16 colours are selected from a set of 64 possible colours – you can modify the ROM values in the IceStudio project to choose different ones. converter IC, but this could be remapped to an external I/O pin for interfacing with a microcontroller such as an Arduino board or MicroMite. Construction As you can see from the PCB overlay diagram in Fig.2, there are few components on the board so it shouldn’t take long to build. The board is coded 02103191, measures 49.5 × 32mm, and is available from the PE PCB Service. Start by fitting the two 68resistors; these are closest to CON2. Bend the legs at right angles, put through the holes and splay the legs to hold in place. Solder and trim the leads just above the solder fillet on the reverse of the board. Fit the 560Ω and 1.1kΩ resistors using a similar procedure. Now mount the VGA socket next, ensuring it is properly seated and flush with the PCB. Solder the larger mechanical pins, turning up your soldering iron temperature if necessary. Do ensure you solder the fine pins of the signal lines carefully to avoid bridging adjacent pins. You may find it easier to work with the centre row of pins first, and check that they are soldered and tidy before accessing the outer rows, which have more surrounding space to work with. Finally, fit the 2 × 6 pin header. This sits underneath the PCB, on the opposite side to the other components, and is soldered from the top. Avoid excessive heat, as this may melt the plastic shroud, putting the pins out of alignment. Check that there are no solder bridges or short circuits, and plug the board into the PMOD header of the iCEstick. The VGA socket faces away from the USB plug of the iCEstick. Practical Electronics | May | 2020 Plug a VGA cable from the VGA socket to a monitor or television. Building and uploading the code With the iCEstick VGA Terminal.ice file open in IceStudio, select the iCEstick from the Select → Board menu. To synthesise the design, click Tools → Build, and when the green ‘Build done’ message appears, click Tools → Upload. The keyboard shortcuts for these commands are Ctrl-B and Ctrl-U respectively. Now connect a VGA monitor and check to see if you have a display, similar to that shown in Screen2. If you have a terminal program installed, such as TeraTerm, PuTTY or even the Arduino IDE, figure out which serial port the iCEstick is using and open a connection to it at 9600 baud with eight bits, no parity (8-N-1). Type into the terminal, and you should see text appear on the screen. If the Enter key generates a CR/LF pair in your terminal program, pressing Enter should cause subsequent text to appear at the start of the next line. Assuming your terminal program supports control codes (which most do, except for the Arduino IDE), you can change the colours by using control key combinations. ASCII control codes 1-26 correspond to pressing Ctrl and one of the letters A-Z on the keyboard; as A is the first letter of the alphabet, Ctrl-A sends control code 1. Press Ctrl-N or Ctrl-O to switch between setting the foreground or background colour, and press Ctrl-P through to Ctrl-Z to change that colour. The five remaining codes between 27 and 31 map to a combination of Ctrl plus another key, those keys being: [, \, ], ^ and _, respectively. You can now use the iCEstick VGA Terminal as-is, or you may wish to experiment further to see what is possible with IceStudio. Debugging the project While the block-and-wire methodology of creating a design does not leave much opportunity for errors, manually entered code blocks certainly could be erroneous, and thus can cause a build error. In this case, you will see a red bar appear instead of ‘Build done’ after attempting a build. It’s possible to view the entire Verilog file that is generated during the build process. IceStudio converts the graphical design into a text-based (Verilog) HDL file, then builds that into the binary bitstream. That’s an intensive process which involves figuring out which FPGA resources can be used to create the required logic and how they should ideally be interconnected, so it can take some time. To view the generated Verilog, click on the View → Command Output menu option and open the folder shown in Screen3. In this folder, there is a main.v file, which is the Verilog code that IceStudio has generated. If you do get a build error, scroll towards the bottom of the Command Output window and you should see an error message indicating the line number on which the error occurred (and the nature of the error). This, in combination with the generated Verilog, should help lead you to the source of the error. It’s a good idea to open main.v in a text editor which displays line numbers. When building the project, you may also see some warnings; most warnings can safely be ignored. Verilog code blocks Now that you know how to debug the code, you may wish to dabble with the Verilog inside the code blocks in this project. Here are some tips to get you started; but don’t think this is the complete book on Verilog coding! Like the C language, all statements end with a semi-colon. Some lines in the Verilog code are direct assignments, such as the following used to generate the HSYNC signal. These generate simple digital logic: assign out = ((count < stop) && (count >= start)) ? 1 : 0; Here, the ternary operator (? :) assigns the ‘out’ register the value of 1 (high) if the value of ‘count’ is less than ‘stop’ and equal to or greater than ‘start’. Otherwise, ‘out’ is assigned the value 0 (low). 35 The VGA Adaptor simply plugs into the matching socket on the iCEstick PCB, while the socket at left connects to the VGA screen/monitor. This could pass for valid C code, apart from the ‘assign’ keyword, but it should be remembered that we are synthesising hardware in the form of logic gates rather than compiling machine code. At a few places in this project, we want to increment a counter based on an input, for example: reg [9:0] counter = 0; always <at>(posedge clk) begin counter <= (counter == div - 1) ? 0 : counter + 1; clkout <= (counter < div/2) ? 1 : 0; end This code is in the block that divides the pixel clock down to a line clock. The first line specifies that ‘counter’ is a 10-bit register, and is set to zero on power-up. The second line indicates that the following sequence will only occur on the positive edge of the clk signal. The resulting synthesis will use flip-flops to retain the state of the registers between clk pulses. The begin/end statements are used to group the two following lines so that they both occur inside the always block. Here, counter is incremented (ie, its value is increased by one), unless it has reached one less than the value of div, in which case it is reset to zero. Thus, counter counts from zero to div-1, which gives us our horizontal pixel position in the counter register. The clkout register is set to one while counter is in the bottom half of its cycle (less than div/2), and zero when it is in the top half, thus dividing the incoming clk signal by the ratio of div. This clkout signal is fed into another similar code block, so that every time the horizontal counter reaches zero, the vertical counter is incremented. This is how our raster is generated. You might note that these registers are loaded with a <= symbol instead of a =. The <= means that they are nonblocking assignments, so they are considered to occur simultaneously. If a specific order of assignment is needed, then the = blocking assignment operator can be used to enforce 36 this, particularly if the result of one expression depends on the result of a previous expression. The memory block demonstrates a few other features of Verilog. Using this specific form of assignment is needed to enforce the use of block RAM, as mentioned earlier: reg [7:0] mem [511:0]; always <at>(posedge wclk) begin if (write_en) mem[waddr] <= din; end always <at>(posedge rclk) begin dout <= mem[raddr]; end initial begin if (MEM) $readmemh(MEM,mem); end The first line defines an internal register file mem, which has 512 (511-0) eight-bit (7-0) elements, effectively, an array. The first always block is responsible for writing to the memory, where the 8-bit value din is stored at position waddr in mem on the positive edge of wclk, but only if write_en is high (one). The second always block performs a read, loading the value of the memory (mem) at raddr to the dout register on the rising edge of rclk. Block RAM is always synchronous (requiring a clock) on the iCEstick’s iCE40HX-1k. Changing the baud rate We suggested earlier that some of the features such as baud rate, graphics and colours can easily be modified. The baud rate is controlled by a single value within the UART block. Around line 26 inside the UART block is the definition of the CLOCK_ DIVIDE parameter. You can select 115200 baud by commenting (adding // to the start of) this line: parameter CLOCK_DIVIDE = 312; and removing the // from the start of: //parameter CLOCK_DIVIDE = 26; Note that the CLOCK_DIVIDE value is determined by dividing 12,000,000 by four times the baud rate (or 3,000,000 divided by the baud rate) and choosing the next lower integer. Choosing the next lower integer means the baud rate is slightly faster than desired, but this will handle receiving a steady stream of characters better than a slightly slower baud rate. Changing the font The font ROM consists of groups of eight 8-bit hexadecimal values inside the three FONT blocks. The top-most block encodes ASCII codes 0-63, the second 64-127, and the third 128-191. The most-significant bit is at left, and the least-significant bit at right, with the data in rows in order from top to bottom. Refer to Fig.3, which shows how the letter ‘A’ is encoded (it is found at addresses 0x08 to 0x0F near the top of the second font ROM block). The whole font is shown in Screen4. Changing the colours The colours are formed by a similar bitmap, with 16 6-bit hexadecimal entries. The two most-significant bits are for the blue level, the middle two bits for the green, and the bottom two bits for red. Thus 0x00 is black and 0x3F is white, as per the first two entries, with the third entry 0x03 being red. Because the foreground and background colours are stored in separate ROMs, you could provide different colour maps for each, but that might be a bit confusing to use. I/O pin assignments Finally, you may wish to map the serial data to a different pin, so you aren’t using the USB/serial converter. This is done by changing the pin connected to the ‘rx’ input of the UART module, as shown in Screen5. We recommend using the ‘TR’ or ‘BR’ groups of pins for I/O; these are the rows of solder pads along the edges of the board. (Refer to the iCEstick manual to check which pin is which.) Take care as the pins are only rated for 3.3V I/O levels, so directly connecting a 5V microcontroller is not recommended, and a level converter or voltage divider should definitely be used in that case. Reproduced by arrangement with SILICON CHIP magazine 2020. www.siliconchip.com.au Practical Electronics | May | 2020