sdrRewind and Black Cat ALE

Many DXers record large swaths of the radio spectrum, and then go back to analyze the recordings, looking for signals of interest. Much of the time, they play the recordings back through their SDR software. This works, but is a slow process, no better than monitoring in real time.

Modern software can dramatically speed up the process. In this article, I’ll show how sdrRewind and Black Cat ALE can team up and speed up the process of finding and decoding ALE (Automatic Link Establishment) transmissions.

Black Cat ALE is a full featured multi-channel ALE decoder for Windows and macOS. It decodes ALE transmissions from either audio fed into a sound card input (live decoding) or from WAVE audio files. Download a copy here: https://blackcatsystems.com/software/black_cat_ale_decoder.html

sdrRewind may take a little more explanation. Rather than just play back an SDR recording file, it allows you to select any of your SDR I/Q recording files, and display a waterfall of the entire file at once, as one large waterfall, with a temporal resolution of one second per line. This is more than adequate to see the various transmissions contained in the recording. Select a signal of interest by dragging a rectangle around it with your mouse, and sdrRewind will demodulate and play back the audio, either to your speakers or a virtual audio device feeding a decoder. It can also demodulate to WAVE files, which can then be fed into your decoding software.

It’s also possible to define a set of frequencies and process several SDR I/Q files at once, generating a collection of WAVE files which can then be fed into the decoding software. In the case of Black Cat ALE, it can be configured to monitor a directory looking for new WAVE files, and automatically process them. So even if the demodulation and decoding process will take some time, you can set it up, then walk away and do something more productive while your computer is busy processing the data. Then come back when it is done and view the results.

Download a copy of sdrRewind here: https://www.blackcatsystems.com/software/sdr_iq_recording_playback_program.html

Black Cat ALE Configuration:

Select Set Directory To Monitor For New Files from the File menu, and choose the directory in which sdrRewind will store demodulated WAVE files. (Create one if you need to)

Select Monitor File Directory from the File menu. Black Cat ALE will start looking in this directory for new WAVE files. The name of these files must end in “.wav” or “.WAV”. It will ignore any files that already exist in this directory.

sdrRewind Configuration:

Set the directory for your SDR recording files, using Set Recording Directory in the File menu

Open Settings in the Edit menu, go to the Demod Directories tab, and create one or more entries for where demodulated WAVE files should be stored, including at least the directory Black Cat ALE will be monitoring. Create each entry by right clicking on the list and select Add Entry. Then right click on that entry and select Set Path and select the directory to use. Repeat as necessary. Close Settings. Go to Select Demod File Directory in the File menu and select the directory where Black Cat ALE will be monitoring for new WAVE files.

Select one of your SDR I/Q recording files from the list of files in the list on the left side of the main window. After a moment, a waterfall for the entire file will appear. Adjust the min and max dB sliders as necessary for good contrast.

Set the mode to USB.

Find an ALE signal in the waterfall and drag around it with the mouse cursor (can’t find any? Go to another I/Q file). You’ll want to make sure the lower frequency is an integer kHz value (or 0.5 kHz for those ALE channels), so edit the frequency as needed. Zero Frequency kHz in the Edit menu can quickly do this for you. Don’t forget to make sure the upper frequency is high enough to cover the entire ALE spectrum, about 3 kHz. Click the Timestamped button. sdrRewind will demodulate the signal and write it to the specified directory. When Black Cat ALE sees the file, it will open and decode it, printing out the results.

Sometimes you want to decode ALE signals from one or more specific frequencies, over an entire set of SDR I/Q recording files. sdrRewind can help with this as well.

Select Demodulate Multiple Files from the Edit menu and a new window appears.

On the left hand side is a list of your recording files, as in the main window. Select a file and basic information about that file will be displayed: the center frequency, sample rate, bandwidth, starting date and time, and length in seconds.

Demodulation settings are displayed immediately to the right of this, again as in the main window. Configure this for the frequency of interest, then select one or more I/Q files and click the Start button. Each I/Q file will be demodulated and written to a separate timestamped WAVE audio file. The entire I/Q file will be demodulated, from start to finish.

Do not make any changes to any controls in this window will files are being processed.

If you wish to demodulate several frequencies from each file, instead use the list to the right:

Right click in it and select Add Entry. A new row will be added. Set the low and high frequency limits of the IF passband, as well as (optionally) the pass band tuning (PBT). Change the mode by right clicking on it, and select a different mode from the popup menu. The same AGC settings will be used for all entries.

When you are finished, click the Start All button. Each I/Q file will again be processed, this time for each of the frequencies in the list. Click abort to stop processing additional files, however the file currently being processed will need to finish.

The Clear button can be used to quickly remove all entries from the list.

Winter 2021-2022 Snowfall

   HF Weather Fax     
   For Android     

High atop Parr’s Ridge in northern Carroll County, MD at about 850 ft elevation.

Monday November 29, 2021
Snow flurries.

Tuesday November 30, 2021
Snow flurries.

November Total: 0.0″

Monday December 27, 2021
1.0″ of snow

December Total: 1.0″

Friday January 7, 2022
6.0″ of snow



Sunday January 16, 2022
3.0″ of snow, then rain.

Monday January 17, 2022
0.5″ of snow

Thursday January 20, 2022
1.0″ of snow after rain

Friday January 28, 2022
About 1.0″, light snow all day.

January Total: 11.5″

Sunday February 13, 2022
5.8″ of snow

Monday February 14, 2022
1.0″ of dry puffy snow

February Total: 6.8″

Saturday March 12, 2022
5.5″ wet snow snow

March Total: 5.5″

Season Total: 24.8″

Shortwave Pirate Radio 2020 – A Year In Review

To gauge shortwave pirate radio activity in 2020, I analyzed the Shortwave Pirate loggings forum of the HF Underground (http://www.hfunderground.com). A computer script parsed the message thread titles, as well as the timestamps of the messages. This information was used to produce some statistics about the level of pirate radio activity. Of course, as Mark Twain has written: “There are three kinds of lies: lies, damned lies, and statistics.” A fourth might be pirate logging message titles. Don’t expect all the numbers to exactly add up. Still, let’s see what we can learn.

There were 15,545 messages posted to 2,400 unique threads, 29% and 10% higher than last year. Shortwave pirate activity is at historically high levels. Back in the 1990s, it was not uncommon for an entire month to go by with only a handful of pirate stations logged. If you want to know when the “golden age” of shortwave pirate radio was, I would say it is right now.

Ideally, each thread represents an individual pirate station transmission. Also ideally, each message posted to a thread represents one logging. In reality, there is some error involved. Let’s dive in.

First, we can look at the transmission mode used:

USB again leads AM, with the other modes rarely used.

Next, we can see how much activity there is for each day of the week:

Weekends (Friday, Saturday, Sunday) are still the most active, but almost a third of broadcasts were on other days of the week.

We can also look at the number of logging threads per month, to gauge activity:

Some seasonal variability, but still very active throughout the entire year.

We might be interested in knowing the best time of the day to try to hear a pirate station. Here’s a plot of the start times of the logged broadcasts, binned
by UTC hour of the day:

Evenings are most active as expected, but still lots of morning and afternoon broadcasts. The wee hours were very quiet, probably due in part to the low solar activity levels.

Here’s a graph showing the number of broadcasts per day of the year that were logged:

Halloween really sticks out this year!

Finally some graphs of the number of logging threads per frequency:

And zoomed in vertically to see the less commonly used frequencies:

The shift to the 4 and 5 MHz bands for many stations is quite evident, driven by the solar minimum conditions making 43 meters useful mostly for just long distance propagation at night. Still, it is the most active pirate band.

If you’re interested in hearing pirates, the best ways to keep up to date on what is being heard is via the HFUnderground.com message board, as well as the real time Rocket Chat. Rather than finding out about a transmission after it is over, you can tune in while it is still on the air. Also visit our Facebook group.

And of course, your loggings and other posts on the HF Underground are most welcome! This is how we find out what stations are being heard.

Shortwave Pirate Radio 2019 – A Year In Review

To gauge shortwave pirate radio activity in 2019, I analyzed the Shortwave Pirate loggings forum of the HF Underground (http://www.hfunderground.com). A computer script parsed the message thread titles, as well as the timestamps of the messages. This information was used to produce some statistics about the level of pirate radio activity. Of course, as Mark Twain has written: “There are three kinds of lies: lies, damned lies, and statistics.” A fourth might be pirate logging message titles. Don’t expect all the numbers to exactly add up. Still, let’s see what we can learn.

There were 12,078 messages posted to 2,186 unique threads. Activity levels are essentially flat, down slightly from 2018, but still at historically high levels. Back in the 1990s, it was not uncommon for an entire month to go by with only a handful of pirate stations logged. If you want to know when the “golden age” of shortwave pirate radio was, I would say it is right now.

Ideally, each thread represents an individual pirate station transmission. Also ideally, each message posted to a thread represents one logging. In reality, there is some error involved. Let’s dive in.

First, we can look at the transmission mode used:

USB beat out AM as the most popular mode, but both account for virtually all transmissions.

Next, we can see how much activity there is for each day of the week:

Weekends (Friday/Saturday/Sunday) are by far the most active, but the rest of the week still accounts for over a third of broadcasts.

We can also look at the number of logging threads per month, to gauge activity:

No summer slump this year, summer was in fact the most active period.

We might be interested in knowing the best time of the day to try to hear a pirate station. Here’s a plot of the start times of the logged broadcasts, binned
by UTC hour of the day:

Most activity is in the evening as expected. But there’s still a fair amount of morning/afternoon activity.

Here’s a graph showing the number of broadcasts per day of the year that were logged:

Finally some graphs of the number of logging threads per frequency:

And zoomed in vertically to see the less commonly used frequencies:

6925 is by far the most active frequency, and 43 meters is busy overall. Old Time Radio on 6770 sticks out. We’re starting to see more activity on the 4 and 5 MHz bands, most likely driven by the low solar activity conditions.

6925 is the place to be, and most activity is on 43 meters, but there’s still a fair bit elsewhere. Old Time Radio on 6770 AM really sticks out.

If you’re interested in hearing pirates, the best ways to keep up to date on what is being heard is via the HFUnderground.com message board, as well as the real time Rocket Chat. Rather than finding out about a transmission after it is over, you can tune in while it is still on the air. Also visit our Facebook group.

And of course, your loggings and other posts on the HF Underground are most welcome! This is how we find out what stations are being heard.

Shortwave Pirate Radio 2018 – A Year In Review

To gauge shortwave pirate radio activity in 2018, I analyzed the Shortwave Pirate loggings forum of the HF Underground (http://www.hfunderground.com). A computer script parsed the message thread titles, as well as the timestamps of the messages. This information was used to produce some statistics about the level of pirate radio activity. Of course, as Mark Twain has written: “There are three kinds of lies: lies, damned lies, and statistics.” A fourth might be pirate logging message titles. Don’t expect all the numbers to exactly add up. Still, let’s see what we can learn.

There were 12,785 messages posted to 2,216 unique threads. Activity levels are essentially flat, down slightly from 2017, but still at historically high levels. Back in the 1990s, it was not uncommon for an entire month to go by with only a handful of pirate stations logged. If you want to know when the “golden age” of shortwave pirate radio was, I would say it is right now.

Ideally, each thread represents an individual pirate station transmission. Also ideally, each message posted to a thread represents one logging. In reality, there is some error involved. Let’s dive in.

First, we can look at the transmission mode used:

AM leads USB, with the other modes much less often used.

Next, we can see how much activity there is for each day of the week:

As expected, weekends are by far the most active, but there’s still pirates to be found during the weekdays.

We can also look at the number of logging threads per month, to gauge activity:

There was a bit of a late summer / fall slump, but a very active holiday season.

We might be interested in knowing the best time of the day to try to hear a pirate station. Here’s a plot of the start times of the logged broadcasts, binned
by UTC hour of the day:

Most activity is in the evening as expected. But there’s still a fair amount of morning/afternoon activity. Not much in the wee overnight hours.

Here’s a graph showing the number of broadcasts per day of the year that were logged:

Finally some graphs of logging threads per frequency:

And zoomed in vertically to see the less commonly used frequencies:

6925 is the place to be, and most activity is on 43 meters, but there’s still a fair bit elsewhere. Old Time Radio on 6770 AM really sticks out.

If you’re interested in hearing pirates, the best ways to keep up to date on what is being heard is via the HFUnderground.com message board, as well as the real time Rocket Chat. Rather than finding out about a transmission after it is over, you can tune in while it is still on the air. Also visit our Facebook group.

And of course, your loggings and other posts on the HF Underground are most welcome! This is how we find out what stations are being heard.

Shortwave Pirate Radio 2017 – A Year In Review

To gauge shortwave pirate radio activity in 2017, I analyzed the Shortwave Pirate loggings forum of the HF Underground (http://www.hfunderground.com). A computer script parsed the message thread titles, as well as the timestamps of the messages. This information was used to produce some statistics about the level of pirate radio activity. Of course, as Mark Twain has written: “There are three kinds of lies: lies, damned lies, and statistics.” A fourth might be pirate logging message titles. Don’t expect all the numbers to exactly add up. Still, let’s see what we can learn.

There were 13,903 messages posted to 2,550 unique threads. Activity levels are essentially flat, but still at historically high levels. Back in the 1990s, it was not uncommon for an entire month to go by with only a handful of pirate stations logged. If you want to know when the “golden age” of shortwave pirate radio was, I would say it is right now.

Ideally, each thread represents an individual pirate station transmission. Also ideally, each message posted to a thread represents one logging. In reality, there is some error involved. Let’s dive in.

First, we can look at the transmission mode used:

AM and USB are tied for first place, with everything else essentially noise.

Next, we can see how much activity there is for each day of the week:

As one might expect, Saturday and Sunday are the big winners, with Friday in third place. But don’t give up on weekday listening! About a third of all transmissions are on a Monday through Thursday.

We can also look at the number of logging threads per month, to gauge activity:

Not much of a summer slump as in past years, activity is relatively constant throughout the year.

We might be interested in knowing the best time of the day to try to hear a pirate station. Here’s a plot of the start times of the logged broadcasts, binned
by UTC hour of the day:

Peak activity in the evening hours is clearly evident, but there is still a good amount of morning and afternoon activity, and low amounts at random overnight hours.

Here’s a graph showing the number of broadcasts per day of the year that were logged:


Looks like the peak was Labor Day weekend?

Finally some graphs of logging threads per frequency:

And zoomed in vertically to see the less commonly used frequencies:

6925 is still the big winner, and 43 meters overall is where most activity resides, but there’s still lots of pirates to be found elsewhere.

If you’re interested in hearing pirates, the best ways to keep up to date on what is being heard is via the HFUnderground.com message board, as well as the real time Rocket Chat. Rather than finding out about a transmission after it is over, you can tune in while it is still on the air. Also visit our Facebook group.

And of course, your loggings and other posts on the HF Underground are most welcome! This is how we find out what stations are being heard.

Winter 2020-2021 Snowfall

High atop Parr’s Ridge in northern Carroll County, MD at about 800 ft elevation.

October Total: 0.0″

Monday November 2, 2020
Snow flurries.

November Total: 0.0″

Tuesday December 1, 2020
Snow flurries.

Wednesday December 9, 2020
Snow flurries.

Monday December 14, 2020
Rain to snow, 1.0″ accumulation.

Wednesday December 16, 2020
Snow then sleet, measured 8.0″ accumulation the next morning.

Friday December 18, 2020
0.3″ dusting of snow.

Friday December 25, 2020
1.57″ of rain and then snow flurries, no accumulation.

December Total: 9.3″

Tuesday January 26, 2021
0.5″ of snow.

January Total: 0.5″

Sunday January 31, 2021 – Tuesday February 2, 2021
10.0″ of snow.

Wednesday February 3, 2021
0.25″ of snow.

Friday February 5, 2021
0.25″ of snow.

Sunday February 7, 2021
3.0″ of snow.

Thursday February 11, 2021
3.0″ of snow.

Thursday February 18, 2021
4.5″ of snow.

Friday February 19, 2021
0.5″ of snow.

Monday February 22, 2021
4.0″ of snow.

Saturday February 27, 2021
0.7″ of snow.

February Total: 26.2″

Tuesday March 16, 2021
Sleet in the morning, no accumulation.

March Total: 0″

Thursday April 1, 2021
0.1″ of graupel.

Friday April 2, 2021
0.1″ of snow.

Thursday April 22, 2021
Snow flurries.

April Total: 0.2″

Season Total: 36.2″

Z80 Emulation on an Arduino, Part 2 – Running MSBASIC

The goal of this project was to get MSBASIC running in an emulated Z80 processor on an Arduino, with no external hardware/components required. Here’s what it looks like when running:

I went with the Arduino Due as it has 96K of RAM, more than enough for a Z80, as well as 512K flash, and a 32-bit ARM core microcontroller running at 84 MHz. Note that the Due uses 3.3V I/O, not 5V as many of the older Arduino boards. Although this will actually be useful for me down the road…

The Due has four serial ports, including two available on USB connectors, the programming port and the native port. I’m using the native port as the terminal interface for the emulated Z80.

For the Z80 emulation I went with z80emu

For MSBASIC itself I went to Grant Searle’s fabulous site, Grant’s 7-chip Z80 computer in particular, and grabbed his ROM files and assembly files.

There’s source code for both a simple monitor that live at 0000H as well as MSBASIC itself which starts at 0150H:
intmini.asm
basic.asm

Also included are the Intel Hex files for both as well as a combined ROM file:
BASIC.HEX
INTMINI.HEX
ROM.HEX

I decided to use the source files and assemble them myself with the asmx multi-CPU assembler, that way I could make changes if I needed to.

I then wrote my own simple little program to take the resulting object code (.bin file) and convert it into Arduino source code that defined a 8K array of PROGMEM prog_uint8_t bytes, which looks like:

const static prog_uint8_t rom_bytes[] PROGMEM = {
0xF3,0xC3,0xB8,0x00,0xFF,0xFF,0xFF,0xFF,0xC3,0x9F,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,
0xC3,0x74,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0xAA,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0x00,0xF5,0xE5,0xDB,0x80,0xE6,0x01,
0x28,0x2D,0xDB,0x81,0xF5,0x3A,0x43,0x20,0xFE,0x3F,0x20,0x03,0xF1,0x18,0x20,0x2A,
....
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

This was then added to my Arduino project as another file, rom.h. When the emulator starts up, it’s copied to the memory array used by the emulator for memory access in the 8K 0000-01FF range where the ROM lives. I have another 64K memory array for RAM, right now the lower 8K is never access, but eventually I’ll add the ability for the Z80 to swap out the ROM and swap it in, for a full 64K of RAM (via an IO port access), once I get CP/M running, which is another project.

I have some benchmarking code that estimates the effective CPU speed. It adds some overhead, but even with that I get about 7.4 MHz, which is actually pretty close to ideal for a “real” Z80.

Now my code:

The Z80 sketch itself, which gets everything going:


extern "C"{
#include "MyZ80Emulation.h"
};

#include "rom.h"

#include

void setup() {
Serial.begin(9600);

Serial.println("Serial Open");

SerialUSB.begin(9600);
SerialUSB.println("Terminal Open");

pinMode(LED_BUILTIN, OUTPUT);

int i;

Serial.println("Copy ROM");
for (i=0; i<8192; i++) InitEmulationRom(i,pgm_read_byte_near(rom_bytes+i) ); Serial.println("InitEmulation"); InitEmulation(); } void loop() { digitalWrite(LED_BUILTIN, HIGH); EmulateInstructions(); digitalWrite(LED_BUILTIN, LOW); while (SerialUSB.available()>0)
{
int ch;
ch=SerialUSB.read();
if (ch==127) ch=8; // handle delete key
AddToInputBuf(ch);
}

InterruptZ80IfNeeded();
}

void my_putchar(int c)
{
SerialUSB.write(c);
}

MyZ80Emulation.c which interfaces with the actual emulation code:

//
// MyZ80Emulation.c
//
//

#include "MyZ80Emulation.h"

#include
#include
#include "zextest.h"

#define Z80_CPU_SPEED 4000000 // In Hz.
#define CYCLES_PER_STEP (Z80_CPU_SPEED / 40) // let's do 100k cycles
#define MAXIMUM_STRING_LENGTH 100

ZEXTEST context;

void InitEmulationRom(int address, int data)
{
context.rom[address] = data;
}

void InitEmulation(void)
{
context.is_done = 0;
Z80Reset(&context.state);
context.state.pc = 0x0;
}

void EmulateInstructions(void)
{
double totalCycles, totalTime, khz;
unsigned long time1,time2;

time1=micros();
totalCycles += Z80Emulate(&context.state, CYCLES_PER_STEP, &context);
time2=micros();

return; // uncomment if we want to time the system

if (time2>time1) // ignore case where the microseconds timer wrapped around
{
totalTime=time2-time1;
if (totalTime>0) khz = 1000.0 * totalCycles / totalTime; else khz=0;
printf("totalCycles: %6d totalTime: %6d %6d kHz \n",(int)totalCycles,(int)totalTime,(int)khz);
}

}

// Handle user terminal input, characters stored in a circular buffer

inputBuf[256];
inputBufInPtr=0;
inputBufOutPtr=0;

void AddToInputBuf(int c)
{
inputBuf[inputBufInPtr]=c;
inputBufInPtr++;
}

void InterruptZ80IfNeeded(void)
{
if (inputBufInPtr==inputBufOutPtr) return; //only interrupt if there is a received character in the ACIA
int cycles;
cycles=Z80Interrupt (&context.state, 0x38, &context); // interrupt Z80
}

// Emulate 8650 ACIA, port input
int SystemCallPortIn(ZEXTEST *context, int port)
{
int inputReady=0;

if (inputBufInPtr != inputBufOutPtr) inputReady=1;

if (port==0x80) return (0x02+inputReady); // ACIA status register, always ready to transmit, inputReady decdes if we have an input character

if (port==0x81)
{
if (!inputReady) return (inputBuf[inputBufOutPtr]); // no new data, send last character anyway
char c;
c=inputBuf[inputBufOutPtr];
inputBufOutPtr++;
return c;
}

printf("SystemCallPortIn %04x\n", port); // if not handled above, display this diagnostic message

return 0;
}

// Emulate 8650 ACIA, port output
void SystemCallPortOut(ZEXTEST *context, int port, int x)
{
if (port==0x81) // UART write a byte
{
my_putchar(x);
return;
}

if (port==0x80) // ACIA write control register, we never need to handle this
{
return;
}

printf("SystemCallPortOut %04x %02x\n", port, x); // if not handled above, display this diagnostic message

}

\

MyZ80Emulation.h the header for the above:

//
// MyZ80Emulation.h
//
//

#ifndef MyZ80Emulation_h
#define MyZ80Emulation_h

#include

void SetFuncton(int (*f)(void));

void InitEmulationRom(int address, int data);
void InitEmulation(void);
void EmulateInstructions(void);
void my_putchar(int c);
void AddToInputBuf(int c);
void InterruptZ80IfNeeded(void);

#endif /* MyZ80Emulation_h */

Generating VGA video with Verilog

I’ve started work on an FPGA based Z80 computer. I wanted to generate the video in the FPGA as well, turns out VGA is fairly easy to generate. There’s numerous websites that describe the timing and parameters of the various VGA modes, and how VGA works.

This project is also my Verilog learning experience, so pardon any horrible code.

In a nutshell, for basic VGA you need a total of 5 digital output lines. One for horizontal sync, one for vertical, and one each for the red, green, and blue video signals. The RGB signals are actually analog, but for my purposes implemented as digital, either on or off. That allows a total of eight colors, including white and black. For now the text is only color. To produce additional colors, the RGB lines can be driven with a D/A converter, which could be as simple as a resistor ladder circuit.

These analog voltages need to be limited to under 1 volt. The FPGA I/O outputs are 3.3 volts so a simple resistor and diode circuit was used for each line. Here’s the circuit, as you can see it is quite simple. Virtually any reasonably fast diode can be used:

I decided to use the standard 640 x 480 60 Hz mode, as it would be more than adequate for my goal of displaying 25 lines of 80 characters.

Each character is displayed as a 8 by 16 pixel matrix, resulting in 640 x 400 pixels, the rest of the screen is not used.

The design was implemented on a RioRand EP2C5T144 Altera Cyclone II FPGA Mini Development Board available at Amazon for $19.99. What a deal.

I used the free version of Altera’s Quartus II software package.

Video memory is a 2K byte dual ported RAM, organized in a linear fashion, using 2000 bytes.

The character generator ROM is a 1K ROM, storing 8 rows of 8 pixels for each of the 128 ASCII characters. Each row is displayed twice, for a total of 16 rows. As of now the high bit of the stored ASCII value in video memory is not used, I plan on eventually using it to implement a low-res color graphics mode, a la the Apple ][.

The RioRand-EP2C5T144 FPGA dev board has a 50 MHz oscillator signal as a clock input. I implemented a 4x PLL to produce an internal 200 MHz clock. While the 50 MHz clock is adequate for 640×480 video, the faster clock will allow higher resolution video modes down the road.

A state machine is used to generate the video. A frame of video actually has 525 scan lines, it starts with 10 “front porch” lines (essentially all black video lines), then 2 lines of vertical sync, followed by 33 more “back porch” lines.
Front porch and back porch are old terms from the original NTSC analog TV system developed in the 1940s. You’ll see that totals 45 lines, leaving 480 lines of actual video.

Each video line has 800 pixels (as far as timing is concerned). There’s a front porch of 16 pixels, 96 pixels of horizontal sync, 48 pixels of a back porch, then 640 pixels of actual video content. At a 200 MHz clock, each pixel is 8 clock cycles.

Prior to the display of a pixel, the video RAM is read. The lower 7 bits of the byte, which is the ASCII value of the character to be displayed, is used along with 3 bits of the video line, to form a 10 bit address into the character generator.

Since each line of a character is displayed twice, bits [3:1[ and not [2:0] of the video line are used. If I was willing to dedicate 2K to the character ROM, I could display 16 rows of pixels for each character.

The resulting VGA video, the video RAM was pre-loaded with data using the Altera MegaWizard option to do so from an Intel Hex file.

Verilog Code:


module vga1
	(
	clock_in,
	
	red,
	green,
	blue,
	hsync,
	vsync
	);


// these are placeholders for when we hook up a CPU later
reg [15:0] addressWriteVideoRam=16'b0;
reg [7:0] dataInWriteVideoRam;
wire [7:0] dataOutReadVideoRam;
reg writeEnableWriteVideoRam=1'b0;
reg writeVideoRamClock;


// VGA video generator, undocumented for now. Good luck. 
	
input clock_in; // 50 MHz input clock

// RGB outputs
output reg red;
output reg green;
output reg blue;

// horizontal and vertical sync outputs
output reg hsync;
output reg vsync;

wire pllClock;
pll my_pll (clock_in, pllClock); // 200 MHz clock from the 50 MHz board clock


reg	[9:0]  char_rom_address;
wire	[7:0]  char_rom_output;
reg char_rom_clock;
reg [7:0] char_rom_data_byte;

reg pixel;
reg [15:0] clockCounter; // 200 MHz clock
reg [15:0] pixelCounter; // 25 MHz pixel clock
	
reg video_inclock;	// video RAM clock
reg video_wren; // not used yet
reg [7:0] video_data; // not used yet

// 1K x 8 bit video character ROM, 8 lines of 8 pixels for 128 characters, high ASCII bit not used
char_rom my_char_rom(char_rom_address, char_rom_clock, char_rom_output);

// 2K video dual port RAM for 25 lines of 80 characters	
video_ram_dp the_video_ram(.address_a (video_display_address[10:0]), .data_a(video_data), .clock_a(video_inclock), .wren_a(video_wren), .q_a(video_data_byte) ,
	.address_b(addressWriteVideoRam[10:0]), .data_b(dataInWriteVideoRam), .clock_b(writeVideoRamClock), .wren_b(writeEnableWriteVideoRam), .q_b(dataOutReadVideoRam)  );

	
reg [15:0] video_display_address;
wire [7:0] video_data_byte;

reg [15:0] horzCounter=16'd0;
reg [15:0] lineCounter=16'd0;


// VGA640x480x60_200mhz clock
parameter pixel_rate=8;
parameter horz_front_porch=16*pixel_rate;  
parameter horz_sync=96*pixel_rate;  		
parameter horz_back_porch=48*pixel_rate;
parameter horz_line=800*pixel_rate;
parameter vert_front_porch=10;
parameter vert_sync=2;
parameter vert_back_porch=33;
parameter vert_frame=525;
parameter horz_sync_polarity = 1'b0;
parameter vert_sync_polarity = 1'b0;
parameter first_video_line=49; // first line of video
parameter number_of_video_lines=400; // 25 ASCII lines of 16 pixels each is 400 video lines



always @(negedge pllClock)
	begin
	char_rom_clock<=horzCounter[0];
			
end
	
always @(posedge pllClock)
	begin

	clockCounter<=clockCounter+1'b1;
	if (clockCounter[2:0]==7) pixelCounter<=pixelCounter+1'b1;

	if (pixelCounter[2:0]==7) begin
		case (clockCounter[2:0])
//		0 : not used
//		1 : not used
		3 : char_rom_address<={video_data_byte[6:0],lineCounter[3:1]}; // high 7 bits of charactor ROM address is the ASCII character, low 3 bits video line counter, we display each line twice
		4 : char_rom_data_byte<=char_rom_output; // latch the character ROM data
//		5 : not used
		6 : video_inclock<=0;	// clock video for next ASCII character
		7 : video_inclock<=1;
		endcase
	end
	
	if (horzCounter==0)	begin  // set video to black
		red<=1'b0;
		green<=1'b0;
		blue<=1'b0;
		clockCounter<=0;
		
		end
		
	if (horzCounter==horz_front_porch)	hsync<=horz_sync_polarity;
	if (horzCounter==(horz_front_porch+horz_sync))	hsync<=!horz_sync_polarity;

	if ( (lineCounter>=(vert_front_porch+vert_sync+vert_back_porch+first_video_line)) && (lineCounter<=(vert_front_porch+vert_sync+vert_back_porch+first_video_line+number_of_video_lines)) )  begin // video frame time

		if ((pixelCounter[2:0]==6) && (clockCounter[2:0]==7)) video_display_address<=video_display_address+1'b1;


		if (horzCounter==(horz_front_porch+horz_sync+horz_back_porch))	begin
			pixelCounter<=0; // start of video line
			end
			
		if (horzCounter>=(horz_front_porch+horz_sync+horz_back_porch))	begin // video line
			
			case (pixelCounter[2:0])
			0 : pixel=char_rom_data_byte[0];
			1 : pixel=char_rom_data_byte[1];
			2 : pixel=char_rom_data_byte[2];
			3 : pixel=char_rom_data_byte[3];
			4 : pixel=char_rom_data_byte[4];
			5 : pixel=char_rom_data_byte[5];
			6 : pixel=char_rom_data_byte[6];
			7 : pixel=char_rom_data_byte[7];
			endcase
			
			// set RGB outputs
			red<=pixel;
			green<=pixel;
			blue<=pixel;
			
			end  // video line time
			
	end // video frame time

	horzCounter <= horzCounter + 16'd1;
	if (horzCounter==horz_line) begin // end of scan line, set video to black
		red<=1'b0;
		green<=1'b0;
		blue<=1'b0;

		horzCounter<=0;
		lineCounter<=lineCounter+1'b1;
		
		if (lineCounter>=(vert_front_porch+vert_sync+vert_back_porch)) begin // video frame time
			if (lineCounter[3:0]!=4'd15) video_display_address<=video_display_address-8'd100; else video_display_address<=video_display_address-8'd20;  // 80 chars back to beginning of line
		end
		
		if (lineCounter==vert_front_porch) vsync<=vert_sync_polarity;
		if (lineCounter==(vert_front_porch+vert_sync)) vsync<=!vert_sync_polarity;
		
		if (lineCounter==vert_frame) begin	// end of the video frame, start over
			video_display_address<=466;		// offset so we start reading video data at the correct address
			lineCounter<=0;
			
			end
			
		end
	
	
	end

	
	
	
endmodule

Z80 Emulation

My goal is to built a Z80 system along the lines of some of the early CP/M machines. A long long time ago in a far away former life, I worked in industrial controls, and some of the systems were Z80 based. So let’s see how much I still remember.

To get things started, I decided to first go down the emulator route before building any real hardware. I grabbed a copy of z80emu and got it running in xCode in an hour or so. It came with some text ROM files that exercise the emulation, to make sure everything is working correctly.

I found this site: Z80 Monitor Type Operating System and SBC where the author build a very simple Z80 system (Z80, RAM, ROM, 8251 UART).
So for the next step, I got that ROM working in the emulator, and modified the code to route UART output to the stdout. So far so good. Then I kludged something together to read input from XCode’s debug terminal, which also worked. Yay.

Then changing gears a but I wanted to experiment accessing a SRAM chip. I connected a 32Kx8 SRAM to an Arduino Mega 2560 and verified I could write and then read back correctly from several memory locations. This was not emulating a Z80 or
anything, just testing I/O from the Arduino.