<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>alrj.org</title><link href="https://www.alrj.org/" rel="alternate"></link><link href="https://www.alrj.org/feeds/all.atom.xml" rel="self"></link><id>https://www.alrj.org/</id><updated>2025-02-17T13:45:00+01:00</updated><entry><title>A DOS minesweeper in 256 bytes</title><link href="https://www.alrj.org/a-dos-minesweeper-in-256-bytes.html" rel="alternate"></link><published>2025-02-17T10:00:00+01:00</published><updated>2025-02-17T13:45:00+01:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2025-02-17:/a-dos-minesweeper-in-256-bytes.html</id><summary type="html">&lt;p&gt;&lt;a href="https://www.alrj.org/images/demo/msweep.png"&gt;&lt;img alt="Capture of a minesweeper game" src="https://www.alrj.org/images/demo/msweep_very_small.png#left"&gt;&lt;/a&gt;
&lt;strong&gt;Twenty-five years!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It has been twenty-five years since I last released a prod at a demoparty,
according to Demozoo (not that I have release many...). But this
year, finally, I submitted a small minesweeper game at the 
&lt;a href="https://lovebyte.party/"&gt;Lovebyte 2025 demoparty&lt;/a&gt;.
Sadly, there was no nanogame competition this year and games …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.alrj.org/images/demo/msweep.png"&gt;&lt;img alt="Capture of a minesweeper game" src="https://www.alrj.org/images/demo/msweep_very_small.png#left"&gt;&lt;/a&gt;
&lt;strong&gt;Twenty-five years!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It has been twenty-five years since I last released a prod at a demoparty,
according to Demozoo (not that I have release many...). But this
year, finally, I submitted a small minesweeper game at the 
&lt;a href="https://lovebyte.party/"&gt;Lovebyte 2025 demoparty&lt;/a&gt;.
Sadly, there was no nanogame competition this year and games were only
showcased, but judging from the reactions in the chat people seemed to
like it, which is absolutely wonderful!&lt;/p&gt;
&lt;h2&gt;What is it?&lt;/h2&gt;
&lt;p&gt;It is a game of &lt;a href="https://en.wikipedia.org/wiki/Minesweeper_(video_game)"&gt;minesweeper&lt;/a&gt;,
for DOS. It runs in Dosbox and in Dosbox-X, it also runs on my 486 under
MS-DOS 6.22 and FreeDOS 1.3, and it even runs in a DOS window under Win98
on my K6-III.&lt;/p&gt;
&lt;p&gt;It presents as a .COM executable file, and &lt;em&gt;the entire game is 256 bytes&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;What does it features?&lt;/h2&gt;
&lt;p&gt;It runs in VGA graphics mode 13h so that the mouse pointer can be an actual
arrow. Also, this gives the opportunity to use a nicer color palette.&lt;/p&gt;
&lt;p&gt;The digits indicating the amount of nearby mines are colored based on their
value, and right-click can be used to flag a cell.&lt;/p&gt;
&lt;p&gt;Full eight-way flood reveal is implemented to automatically reveal entire
zones where adjacent cells have zero nearby mine.&lt;/p&gt;
&lt;p&gt;Try it by yourself right here:&lt;/p&gt;
&lt;p&gt;&lt;link rel="stylesheet" href="https://www.alrj.org/downloads/static/msweep-js-dos.css"&gt;&lt;/p&gt;
&lt;script src="https://v8.js-dos.com/latest/js-dos.js"&gt;&lt;/script&gt;
&lt;div id="dos" style="width: 640px; height: 400px; background: lightgrey;"&gt;
&lt;/div&gt;
&lt;script type="text/javascript"&gt;
  Dos(document.getElementById("dos"), {
  url: "/downloads/static/msweep-release.jsdos",
  imageRendering: "smooth",
  kiosk: true,
  autoStart: false,
});
&lt;/script&gt;

&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;p&gt;Of course there are limitations. What did you expect, this is a 256 bytes game!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The map generation is not delayed, so you might end up dying on your very first
    click.&lt;/li&gt;
&lt;li&gt;There is no tri-state flagging, where you could put a question mark on a cell.&lt;/li&gt;
&lt;li&gt;No middle-click either that would allow to reveal all neighbours of a cell
    that has all its nearby mines already flagged.&lt;/li&gt;
&lt;li&gt;Map size is fixed. You can change the amount of mines, but this is done by
    editing the value in source code and recompiling.&lt;/li&gt;
&lt;li&gt;The only way to exit the game is to win or lose it. And to know if you won or
    if you lost, when you get back to the DOS prompt, you need to check the last
    cell you clicked. If it shows a mine, then you lost ;-)&lt;/li&gt;
&lt;li&gt;The video mode is not restored on exit, but on the other hand this leaves the
    finished game on screen so you can tell if you won or not.&lt;/li&gt;
&lt;li&gt;The presence of the mouse driver is not checked. I must admit I haven't tested
    that and I don't know how you'd exit the game without a working mouse.
    Apologies if that gets you stuck when trying to play on a real computer.&lt;/li&gt;
&lt;li&gt;When you lose a game, there's no visual clue of wrongly placed flags and 
    unflagged mines.&lt;/li&gt;
&lt;li&gt;There is no display of elapsed time or the number of mines left.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite these, I find the game totally playable, but I might be biased.&lt;/p&gt;
&lt;h2&gt;Download and externl links&lt;/h2&gt;
&lt;p&gt;You can &lt;a href="https://www.alrj.org/downloads/msweep.zip"&gt;download the game here&lt;/a&gt;. Source code
is included, of course, and you can do whatever you want with it.&lt;/p&gt;
&lt;p&gt;Entry is now created on &lt;a href="https://www.pouet.net/prod.php?which=103623"&gt;Pouët.net&lt;/a&gt;
and the &lt;a href="https://demozoo.org/productions/367556/"&gt;page on Demozoo&lt;/a&gt; is up, though
still a bit empty.&lt;/p&gt;</content><category term="Demoscene"></category><category term="Demoscene"></category></entry><entry><title>BB-88 runs Minix</title><link href="https://www.alrj.org/bb-88-runs-minix.html" rel="alternate"></link><published>2024-07-22T10:52:00+02:00</published><updated>2024-07-23T16:52:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2024-07-22:/bb-88-runs-minix.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This is a log entry about BB-88. See the &lt;a href="https://www.alrj.org/pages/bb-88.html"&gt;project page&lt;/a&gt; to know more about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Minix logo" src="https://www.alrj.org/images/bidule88/m4-8.png#left"&gt;
Running Minix on BB-88 was certainly not part of my goals when I started this project, but
at some point, seeing how I could get MS-DOS running, I thought I should at least give …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This is a log entry about BB-88. See the &lt;a href="https://www.alrj.org/pages/bb-88.html"&gt;project page&lt;/a&gt; to know more about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Minix logo" src="https://www.alrj.org/images/bidule88/m4-8.png#left"&gt;
Running Minix on BB-88 was certainly not part of my goals when I started this project, but
at some point, seeing how I could get MS-DOS running, I thought I should at least give it a try.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/bidule88/minix/BB-88-Minix-full.jpg"&gt;&lt;img alt="Freshly booted Minix on BB-88" src="https://www.alrj.org/images/bidule88/minix/BB-88-Minix-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, although Minix can run in the very limited amount of memory a 8088 can address, that's
not exactly the ideal setup, and there are limitation. Thankfully, most shortcomings are
covered in the FAQ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://minix1.woodhull.com/faq/minix640k.html"&gt;Using Minix in 640K RAM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://minix1.woodhull.com/faq/smallmem.html"&gt;Minix on a 512K PC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Minix Installation&lt;/h2&gt;
&lt;p&gt;Without a floppy disk interface, the only way for me to install Minix was to transfer an
existing system onto a Compact Flash. My first tentatives to install it inside a QEMU virtual
machine did not go well because of &lt;a href="https://gitlab.com/qemu-project/qemu/-/issues/1522"&gt;this bug in the floppy drive emulation in
QEMU&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is where the disk images of &lt;a href="https://github.com/davidgiven/minix2/"&gt;Minix QD&lt;/a&gt; prepared
by David Given came to the rescue. I went straight to the Minix 1.7 image and didn't even
bother playing with the Minix 2.0 one. I booted it in QEMU with the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/usr/bin/qemu-system-i386&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-monitor&lt;span class="w"&gt; &lt;/span&gt;stdio&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;486&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-k&lt;span class="w"&gt; &lt;/span&gt;fr-be&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-machine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;accel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kvm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-hda&lt;span class="w"&gt; &lt;/span&gt;/path/to/minix-qd-1.7-hd-64MB-test.img&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-boot&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;once&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;a,menu&lt;span class="o"&gt;=&lt;/span&gt;off&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-net&lt;span class="w"&gt; &lt;/span&gt;nic&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-net&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-rtc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;localtime&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Minix QD 1.7.5&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That allowed me to have a quick look at the content of the image, then I transfered it to a
new Compact Flash and started BB-88. At this stage, I spent an insane amount of time chasing
red herrings, trying to get it past the bootloader. In the end, all these issues were caused
by not only one, but two defective Compact Flash cards! Once I switched to a known good
Trancend one, the MBR executed fine, the partition boot sector executed fine and loaded the
monitor, that I could interrupt by pressing ESCape.&lt;/p&gt;
&lt;h2&gt;Booting Minix&lt;/h2&gt;
&lt;p&gt;I needed to be able to interrupt the monitor to change the boot parameters. The Compact Flash
might be IDE compatible, it is at a non-standard base address, and it uses what's referred to as
the '&lt;a href="https://www.minuszerodegrees.net/xtide/XT-IDE%20-%20Hi-speed%20mode.htm"&gt;Chuck mod&lt;/a&gt;'.
This is a change that improves the performance of the IDE interface on an 8-bit bus, but the
software needs to be adapted accordingly. Instead of making all the changes in the &lt;code&gt;at_wini&lt;/code&gt;
driver in Minix, I instructed Minix to use the BIOS functions to access the disk.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;gt;hd=bios
&amp;gt;boot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It looked like it was able to start, but after the initial loading, the screen would stay
desperately empty.&lt;/p&gt;
&lt;p&gt;Back in the VM, I edited &lt;code&gt;/etc/ttytab&lt;/code&gt; to enable the console on the serial line so that I
could get a shell, then re-imaged the Compact Flash and booted BB-88 again, this time to be
greeted with a login prompt in Minicom! I got Minix running on my breadboard computer!&lt;/p&gt;
&lt;p&gt;Armed with my serial console, I quickly found the cause of the black screen: my BIOS wasn't
setting the I/O port address of the CRTC in the BIOS Data Area. Minix's console driver uses
this to determine whether the console is color (CGA) or monochrome (MDA) when there's no EGA or
VGA adapter. Once the firmware was fixed, the console came to life and worked beautifully.&lt;/p&gt;
&lt;h2&gt;Some improvements and a new font&lt;/h2&gt;
&lt;p&gt;With the system running, it was time to play with it and take advantage of BB-88's hardware.&lt;/p&gt;
&lt;p&gt;The first, simple, change was to make a Belgian keymap. That was reasonably straightforward.&lt;/p&gt;
&lt;p&gt;The second modification was to make the console use a slightly different video mode, showing
30 lines of text in 640x480 instead of the 25 lines shown in 640x400. It was a good warm-up
for the next step, and I had to rebuild and reboot on the new kernel quite a few times before
I got it working correctly.&lt;/p&gt;
&lt;p&gt;Then, building upon that freshly acquired knowledge, I decided to adapt and improve the
&lt;code&gt;loadfont&lt;/code&gt; program. This required modifications in &lt;code&gt;console.c&lt;/code&gt; and &lt;code&gt;tty.c&lt;/code&gt; part of the kernel.
To avoid interfering with the existing code for the more standard video adapters, the boot
parameter '&lt;code&gt;video&lt;/code&gt;' must be set explicitely to '&lt;code&gt;bbga&lt;/code&gt;'. This is handled in &lt;code&gt;glo.h&lt;/code&gt; and
&lt;code&gt;start.c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In BB-88, the character generation ROM is actually a RAM, mapped in memory at address 0xA0000.
Four different fonts can be stored in memory, each in its bank, and two bits of the Mode
Register are used to select the active bank. My version of the &lt;code&gt;loadfont&lt;/code&gt; program leaves the
default font untouched in bank 0 and uploads the new font in bank 2. This ensures an easy way
back to a readable console in case the loaded font is all garbled.&lt;/p&gt;
&lt;p&gt;But the new feature I like the most is that it also reprograms the CRTC to adjust the display
to the height of the new font. With this 12x8 font, I now get 40 lines of text instead of the
classic 25 lines. I also had to implement the actual support for the change of geometry of the
console, making sure the &lt;code&gt;tty&lt;/code&gt;'s &lt;code&gt;winsize&lt;/code&gt; structure was correctly updated every time a new
font was loaded.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/bidule88/minix/Minix-console-80x40-full.jpg"&gt;&lt;img alt="The file console.c from the Minix kernel, opened in vi, displayed on BB-88 with a custom
font, in all its 40 lines glory" src="https://www.alrj.org/images/bidule88/minix/Minix-console-80x40-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can &lt;a href="https://www.alrj.org/downloads/BB88SANS.F12"&gt;download the font&lt;/a&gt; if you like it. This is a
text-mode font that you can open in Fontraption.&lt;/p&gt;
&lt;p&gt;I now have a nice Minix environment that I can use on BB-88, in addition to MS-DOS. So,
what's next?&lt;/p&gt;</content><category term="Electronics"></category><category term="Bidule88"></category><category term="BB-88"></category></entry><entry><title>Experiments in VGA colors</title><link href="https://www.alrj.org/experiments-in-vga-colors.html" rel="alternate"></link><published>2024-06-20T17:52:00+02:00</published><updated>2024-06-20T17:52:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2024-06-20:/experiments-in-vga-colors.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This is a log entry about BB-88. See the &lt;a href="https://www.alrj.org/pages/bb-88.html"&gt;project page&lt;/a&gt; to know more about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now that the VGA RAMDAC has been removed from the VGA signal generation circuit, I need to find
a way to output the correct levels for the red, green and blue outputs. The idea …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This is a log entry about BB-88. See the &lt;a href="https://www.alrj.org/pages/bb-88.html"&gt;project page&lt;/a&gt; to know more about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now that the VGA RAMDAC has been removed from the VGA signal generation circuit, I need to find
a way to output the correct levels for the red, green and blue outputs. The idea here is to get
the same colors than the first 16 colors of the official VGA palette. These colors are very close
to the CGA and base EGA palettes as well (with a grain of salt, see &lt;a href="https://int10h.org/blog/2022/06/ibm-5153-color-true-cga-palette/"&gt;this article about the true
color values of the CGA palette on int10h.org&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;My goal is to get something close to what they describe as the canonical mapping, with intensity
levels of 0x00, 0x55, 0xAA and 0xFF.&lt;br&gt;
&lt;img alt="The desired 16-color palette" src="https://www.alrj.org/images/bidule88/vga-rgbi/Desired_RGBI_palette.png"&gt;&lt;/p&gt;
&lt;p&gt;Fortunately, the translation from a color index to the actual color is reasonably straightforward.
Out of the 4-bit color value, bits 0, 1 and 2 each refer to blue, green and red; then bit 3 means
"hi-intensity", for a lighter, brighter color. The brown color is a special case, but I'll get to
it later.&lt;/p&gt;
&lt;h2&gt;Output signal&lt;/h2&gt;
&lt;p&gt;The full scale for VGA is from 0.0V for black to 0.7V output for full bright color channel,
with a 75Ω termination inside the monitor.&lt;/p&gt;
&lt;p&gt;Considering that 0xFF translates to 0.7V, we can assume that 0xAA is 0.47V and 0x55 is 0.23V.
All that is left to do is to find a nice driver chip and figure out the right resistors combination
that will result in the correct voltage being applied.&lt;/p&gt;
&lt;p&gt;It's worth noting that the current resulting from sourcing 0.7V into 75Ω is close to 10mA&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;,
which cannot be achieved with many LS or CMOS IC families. With this in mind, I've decided to
use the 74&lt;strong&gt;AC&lt;/strong&gt;244, an octal buffer with strong drivers, capable of more than 20mA per output,
which should be plenty. The fact that it is actually split in two, with an Output Enable pin
for each half is also a big advantage, as we'll see.&lt;/p&gt;
&lt;h2&gt;Output circuit&lt;/h2&gt;
&lt;p&gt;At first, I struggled a lot trying to find the correct combination of resistors, but it became
way easier when I realized that instead of using the input value of 0V or 5V, I could also use
the tri-state nature of the buffer's output. After some quick fiddling, I finally had something
working in the simulator&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The base for the output circuit of each channel would look like this (thus repeated three
times, for red, green and blue):
&lt;img alt="Output circuit for red and blue" src="https://www.alrj.org/images/bidule88/vga-rgbi/BB-88_vga_new_RB.png"&gt;&lt;/p&gt;
&lt;p&gt;For the first half of the palette, where the Intensity bit is not set, only the 487Ω
and 150Ω resistors are used. The resulting voltage going out into the monitor will be around
0.46V, very close to the intended level.&lt;/p&gt;
&lt;p&gt;When the intensity bit is set, the 820Ω resistor comes into play and brings the signal up to
the desired 0.7V for full brightness, or to 0.26V when only the Intensity bit set, which is
close enough to the desired 0.23V.&lt;br&gt;
When Intensity is not active, the buffer is disabled, leaving the 820Ω resistor floating,
having no effect at all.&lt;/p&gt;
&lt;h2&gt;Brown correction circuit&lt;/h2&gt;
&lt;p&gt;This is already very nice, but one color of that palette is not exactly the one we want: at
the moment, color 6 looks more like what's often called "olive", or "dark yellow", instead
of brown.&lt;br&gt;
&lt;img alt="The 16-color palette without brown correction" src="https://www.alrj.org/images/bidule88/vga-rgbi/Base_RGBI_palette.png"&gt;&lt;/p&gt;
&lt;p&gt;An additionnal circuit is thus needed to reduce the level of green for color 6, to get a more
reddish tint. I did it with a resistor pulling the green signal down, activated by a 74AC139
selector.&lt;/p&gt;
&lt;p&gt;Here is the adapted schematics for the green channel:&lt;br&gt;
&lt;img alt="Output circuit for green" src="https://www.alrj.org/images/bidule88/vga-rgbi/BB-88_vga_new_G.png"&gt;&lt;/p&gt;
&lt;p&gt;There is no need to check if we're currently in active display state here because we're just pulling
to 0V anyway, so we can get away with half a 74AC139.&lt;/p&gt;
&lt;h2&gt;Actual result&lt;/h2&gt;
&lt;p&gt;I only had to wait a few days for the components to be delivered, and then, as is often the case,
life got busy for several months. Until now...&lt;/p&gt;
&lt;p&gt;I first built the circuit on a separate breadboard, just to test with the multimeter that the outputs
acted as expected when I played with the inputs. It was also the opportunity to assign the physical slots
of the ICs to keep the connections short and simple. The layout looks promising, it should need only
minimal rework.&lt;br&gt;
&lt;a href="https://www.alrj.org/images/bidule88/vga-rgbi/proto-full.jpg"&gt;&lt;img alt="Prototype circuit" src="https://www.alrj.org/images/bidule88/vga-rgbi/proto-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, how does it perform? To test it in situation, I just put it next to BB-88's main circuit and connected
it with long wires, bypassing the crude temporary DAC.&lt;br&gt;
&lt;a href="https://www.alrj.org/images/bidule88/vga-rgbi/test-full.jpg"&gt;&lt;img alt="Testing the circuit" src="https://www.alrj.org/images/bidule88/vga-rgbi/test-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The colors on the LCD are showing just as expected, although there is a slight vertical banding, mostly
in the bright colors.&lt;br&gt;
&lt;a href="https://www.alrj.org/images/bidule88/vga-rgbi/LCD-banding-full.jpg"&gt;&lt;img alt="Result on the LCD" src="https://www.alrj.org/images/bidule88/vga-rgbi/LCD-banding-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here's a close-up view that better shows the banding:&lt;br&gt;
&lt;img alt="close-up of the banding on the LCD" src="https://www.alrj.org/images/bidule88/vga-rgbi/LCD-banding-closeup.jpg"&gt;&lt;/p&gt;
&lt;p&gt;On the other hand, the result on the CRT is excellent!&lt;br&gt;
The text looks sharp, and there are no jailbars, no shadows and very little echo!&lt;br&gt;
&lt;a href="https://www.alrj.org/images/bidule88/vga-rgbi/CRT1-full.jpg"&gt;&lt;img alt="Colored text on the CRT" src="https://www.alrj.org/images/bidule88/vga-rgbi/CRT1-small.jpg"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.alrj.org/images/bidule88/vga-rgbi/CRT2-full.jpg"&gt;&lt;img alt="Result on the CRT" src="https://www.alrj.org/images/bidule88/vga-rgbi/CRT2-small.jpg"&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;p&gt;I'm super happy with the result!&lt;/p&gt;
&lt;p&gt;That's how the circuit now looks like on the breadboard:&lt;br&gt;
&lt;a href="https://www.alrj.org/images/bidule88/vga-rgbi/output-stage-full.jpg"&gt;&lt;img alt="VGA output stage circuit on breadboard" src="https://www.alrj.org/images/bidule88/vga-rgbi/output-stage-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I had to be creative to squeeze it in the available space, by using (and sometimes abusing) free gates
on various ICs already present in the build, but that was really worth it. Because that also means I 
won't have to remove the OPL2 section! And I just found out yesterday that you can find small
DC-to-DC modules that convert a single 5V supply into a dual ±12V output, which is exactly what I'm missing
since I replaced the ATX power supply with a Meanwell one!&lt;/p&gt;
&lt;h2&gt;Full schematic&lt;/h2&gt;
&lt;p&gt;I thought I'd publish the full schematic of the prototype output stage for reference (click the image for a
larger version), because I think it might be of use to anyone wanting to convert a 4-bit RGBI to analog VGA
levels:&lt;br&gt;
&lt;a href="https://www.alrj.org/images/bidule88/vga-rgbi/vgaout-full.png"&gt;&lt;img alt="VGA output stage" src="https://www.alrj.org/images/bidule88/vga-rgbi/vgaout-small.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the circuit as it is implemented also uses the remaining half 244 buffer to try
and get the timing slightly more consistent between the channels, but I reckon it shouldn't make
any visible difference in practice.&lt;br&gt;
I also used one of the available NAND gates as an inverter in the prototype instead of adding another chip.&lt;/p&gt;
&lt;p&gt;And yes, I'm aware that the output impedance does not match the monitor's input impedance, but that
doesn't seem to be much of an issue.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;I = U/R = 0.7V/75Ω = 9.33mA&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;I've been using KTechLab for this, despite some annoying shortcomings.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Electronics"></category><category term="Bidule88"></category><category term="BB-88"></category></entry><entry><title>A PS/2 adapter box for the HP 715/80</title><link href="https://www.alrj.org/a-ps2-adapter-box-for-the-hp-71580.html" rel="alternate"></link><published>2024-05-06T22:20:00+02:00</published><updated>2024-05-06T22:20:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2024-05-06:/a-ps2-adapter-box-for-the-hp-71580.html</id><summary type="html">&lt;p&gt;The HP 715/80 workstation has an unusual port for input devices that
requires the use of an adapter box: the HP HIL A4022-62005. This module
sells at an &lt;strong&gt;insane&lt;/strong&gt; price, even without its cable, so the only reasonable
thing to do was to make one myself.&lt;/p&gt;
&lt;p&gt;At the back …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The HP 715/80 workstation has an unusual port for input devices that
requires the use of an adapter box: the HP HIL A4022-62005. This module
sells at an &lt;strong&gt;insane&lt;/strong&gt; price, even without its cable, so the only reasonable
thing to do was to make one myself.&lt;/p&gt;
&lt;p&gt;At the back of the station is a socket for a modular connector, much like a
network plug, but with 10 pins instead of 8.&lt;br&gt;
&lt;a href="https://www.alrj.org/images/retrocomputing/10P10C-PS2-HIL.jpg"&gt;&lt;img alt="10-pins connector" src="https://www.alrj.org/images/retrocomputing/10P10C-PS2-HIL-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you look closely, you can see that it is also keyed on the left, certainly
to prevent anyone plugging a network cable in there.&lt;/p&gt;
&lt;p&gt;Thanks to nater1217 on the VCFed forum, &lt;a href="https://forum.vcfed.org/index.php?threads/hp-715-100-10-pin-keyboard-and-mouse-pinout.1242185/#post-1372294"&gt;the pinout is 
known!&lt;/a&gt;
and has also been submitted to &lt;a href="https://old.pinouts.ru/InputCables/HP_9000_715-100_10-pin_mo_pinout.shtml"&gt;pinouts.ru&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many thanks also to Anders Gustafsson for sharing his &lt;a href="http://www.dalton.ax/hpkbd/hil/"&gt;Adventures with HP HIL&lt;/a&gt;,
especially for the part numbers of compatible connectors.&lt;/p&gt;
&lt;p&gt;The good news is that, in addition to HP HIL, PS/2 keyboard and PS/2 mouse signals
are both directly available on this connector, and the adapter box doesn't need any
logic. This was confirmed with a quick prototype on breadboard:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/retrocomputing/HP-PS2-Breadboard.jpg"&gt;&lt;img alt="HP PS/2 on breadboard" src="https://www.alrj.org/images/retrocomputing/HP-PS2-Breadboard-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now I know it's working, but I'd rather have all that in a nice box, so I designed
a PCB that would fit in a small 10cm by 6cm box.&lt;/p&gt;
&lt;p&gt;The schematic is extremely simple:&lt;br&gt;
&lt;a href="https://www.alrj.org/images/retrocomputing/hp-ps2.sch.pdf"&gt;&lt;img alt="Adapter schematics" src="https://www.alrj.org/images/retrocomputing/hp-ps2-schematics.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And the PCB isn't very complex either:&lt;br&gt;
&lt;a href="https://www.alrj.org/images/retrocomputing/hp-ps2-board-top.png"&gt;&lt;img alt="Adapter PCB" src="https://www.alrj.org/images/retrocomputing/hp-ps2-board-top-640.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that I have included the HIL connector, but I give absolutely no guarantee that
it will work, this is entirely untested and the order of the pins could very well be
swapped! Use it at your own risk.&lt;/p&gt;
&lt;p&gt;The gerber files were then sent to JLCPCB and the printed circuit boards arrived after
a few days.
&lt;a href="https://www.alrj.org/images/retrocomputing/hp-ps2-pcbs.jpg"&gt;&lt;img alt="Adapter PCB" src="https://www.alrj.org/images/retrocomputing/hp-ps2-pcbs-640.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Assembly was straightforward. In hindsight, I wish I'd used a right angle pin header
instead of soldering the wires directly to the board, but I don't have any in stock.
Well, I have ordered some, and I can always change it later. (The box is too small for
vertical pin header).&lt;/p&gt;
&lt;p&gt;The cable I used comes from a PS/2 extension cord and has only 6 conductors (plus
shielding, that I didn't use); that's just enough to get the two PS/2 connections
working!&lt;/p&gt;
&lt;p&gt;The two holes are used to firmly secure the cable with a zip-tie.&lt;/p&gt;
&lt;p&gt;Enjoy a few more pictures of the circuit assembled and put in its box.
&lt;a href="https://www.alrj.org/images/retrocomputing/hp-ps2-pcb-assembled.jpg"&gt;&lt;img alt="The PCB assembled" src="https://www.alrj.org/images/retrocomputing/hp-ps2-pcb-assembled-640.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/retrocomputing/hp-ps2-in-box.jpg"&gt;&lt;img alt="The PCB in its box" src="https://www.alrj.org/images/retrocomputing/hp-ps2-in-box-640.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/retrocomputing/hp-ps2-box.jpg"&gt;&lt;img alt="The PCB box closed" src="https://www.alrj.org/images/retrocomputing/hp-ps2-box-640.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The schematic was made with &lt;a href="https://github.com/lepton-eda/lepton-eda"&gt;Lepton EDA&lt;/a&gt;
and the PCB with &lt;a href="http://repo.hu/projects/pcb-rnd/"&gt;pcb-rnd&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;You can download an &lt;a href="https://www.alrj.org/downloads/HP-PS2.tar.gz"&gt;archive of the sources of the project&lt;/a&gt;
or go to the &lt;a href="https://framagit.org/alrj/hp-ps2"&gt;project page on framagit&lt;/a&gt;.&lt;/p&gt;</content><category term="Retrocomputing"></category><category term="Retrocomputing"></category><category term="Electronics"></category></entry><entry><title>BB-88 stability issues</title><link href="https://www.alrj.org/bb-88-stability-issues.html" rel="alternate"></link><published>2024-01-07T15:39:00+01:00</published><updated>2024-01-07T15:39:00+01:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2024-01-07:/bb-88-stability-issues.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This is a log entry about BB-88. See the &lt;a href="https://www.alrj.org/pages/bb-88.html"&gt;project page&lt;/a&gt; to know more about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When I was building BB-88, it was sitting on my electronics bench, right below the roof window.
And as you may suspect, it rained on it a few times, especially during summer when I …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This is a log entry about BB-88. See the &lt;a href="https://www.alrj.org/pages/bb-88.html"&gt;project page&lt;/a&gt; to know more about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When I was building BB-88, it was sitting on my electronics bench, right below the roof window.
And as you may suspect, it rained on it a few times, especially during summer when I tend to leave
the window open. I don't know for sure if it's the main reason, but with time, the breadboard
computer has become quite unreliable.&lt;/p&gt;
&lt;p&gt;I've sprayed contact cleaner everywhere and tried to play with all the wires, hoping they would
make better contact. I have also brushed the legs of all the ICs with a fiberglass pen, but with
very little success.&lt;/p&gt;
&lt;p&gt;Something else that I have noticed is that the ATX power supply I've been using doesn't seem able
to regulate correctly with a load this light. Asides from the OPL2 "sound card" that needs ±12V,
the entire computer runs on 5V, and it gets loaded to a mere 1.3A. When unloaded, the power supply
gives a very neat 5.02V but it drops down to about 4.7V when powering BB-88. I have tried loading
the other rails with biggish resistors: 4Ω on the 3.3V and 2.5Ω on 12V, but unfortunately it didn't
help the 5V rail. Testing with two other power supplies showed an even larger drop on the 5V line.&lt;/p&gt;
&lt;p&gt;Another part that causes a lot of problems is the palette RAMDAC. Sometimes it works, but most of
the time the output is very noisy and the colors aren't setup correctly. Then if I replace the chip
with another one from my components stash, it sometimes works for some time, or fails with different
bad colors. This could indicate a component failure, but the behaviour seems to be consistent with two
different brands (IMS and Analog Device). I do not exclude the possibility that I'm doing something
wrong with the chips.&lt;/p&gt;
&lt;h2&gt;Hardware simplification&lt;/h2&gt;
&lt;p&gt;All these issues developed over time, and now that I know that I could build it, I'd rather make
the computer more stable, at the expense of features that I don't actually use.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/bidule88/ep04/PSU-full.jpg"&gt;&lt;img alt="BB-88's new power supply" src="https://www.alrj.org/images/bidule88/ep04/PSU-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first modification I made was to replace the ATX power supply with a small 5V MeanWell power
supply&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;. That alone made the computer much more stable, but it also means that the OPL2 sound
section is no longer powered, as ±12V is no longer available. Ripping this section apart later
on will give room to make a more advanced color video output circuit, but for now let's keep
things simple.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/bidule88/ep04/RAMDAC-full.jpg"&gt;&lt;img alt="The VGA palette RAM DAC goes out" src="https://www.alrj.org/images/bidule88/ep04/RAMDAC-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the VGA palette DAC that must go away to be replaced with a &lt;strong&gt;very&lt;/strong&gt; crude circuit that
converts the RGBI (Red, Green, Blue and Intensity) signals to VGA levels. This is far from perfect,
and isn't even consistent across monitors.&lt;/p&gt;
&lt;p&gt;I used the circuit from &lt;a href="http://boginjr.com/electronics/rad/rgbi/"&gt;http://boginjr.com/electronics/rad/rgbi/&lt;/a&gt;
but I adapted the resistors' values in order to try and get a slightly better image quality
(although with very limited success, as seen below). Please don't mind the flying wires, this
is only a temporary setup.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/bidule88/ep04/CRUDEDAC-full.jpg"&gt;&lt;img alt="Crude DAC comes in" src="https://www.alrj.org/images/bidule88/ep04/CRUDEDAC-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The LCD shows lavish bright colors with very strong jailbars (that don't render well in the
picture, but believe me, this is disgusting to look at).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/bidule88/ep04/LCD-full.jpg"&gt;&lt;img alt="Crude DAC output on LCD" src="https://www.alrj.org/images/bidule88/ep04/LCD-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When driving the CRT, it seems like the intensity has nearly no effect on primary colors (pure
red, green or blue), a little effect on colors that mix two channels (cyan, purple and yellow),
and full effect on light gray, that uses all three. Dark gray is barely visible.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/bidule88/ep04/CRT-full.jpg"&gt;&lt;img alt="Crude DAC output on CRT" src="https://www.alrj.org/images/bidule88/ep04/CRT-small.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the picture of the CRT, above, doesn't render the colors very well either. It is
much darker in reality, and the yellow actually looks like a dirty dark yellow, not at all
like this nice brown color.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The system is now very stable. I haven't experienced a single freeze or failed boot since I
changed the power supply, even in Turbo mode.&lt;/p&gt;
&lt;p&gt;The colors are seriously off, but at least they do show up on screen! With the randomly
failing RAMDACs, that was never a given.&lt;/p&gt;
&lt;p&gt;Next step, I intend to remove the OPL2 section and replace it with a more robust VGA output,
if possible with the correction circuit for brown color!&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Exact reference is Model RS-25-5, rated for 5 Amps.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Electronics"></category><category term="Bidule88"></category><category term="BB-88"></category></entry><entry><title>A word on function calls and returns</title><link href="https://www.alrj.org/a-word-on-function-calls-and-returns.html" rel="alternate"></link><published>2023-04-04T00:00:00+02:00</published><updated>2023-04-04T00:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2023-04-04:/a-word-on-function-calls-and-returns.html</id><summary type="html">&lt;p&gt;If you've read my &lt;a href="https://www.alrj.org/control-hazards-with-jumps-and-branches.html"&gt;previous post&lt;/a&gt;
about control hazards, you may have noticed that I talked about branches and
jumps, but did not write a single word about function call or return instructions.
This omission may be a bit surprising if you are not familiar with RISC-V or
architectures with …&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you've read my &lt;a href="https://www.alrj.org/control-hazards-with-jumps-and-branches.html"&gt;previous post&lt;/a&gt;
about control hazards, you may have noticed that I talked about branches and
jumps, but did not write a single word about function call or return instructions.
This omission may be a bit surprising if you are not familiar with RISC-V or
architectures with a similar instruction set.&lt;/p&gt;
&lt;p&gt;The reason is that &lt;code&gt;JAL&lt;/code&gt; (jump and link) and &lt;code&gt;JALR&lt;/code&gt; (jump and link register)
already cover these use-cases, because both of them can store the address of
the instruction following the jump (&lt;code&gt;PC+4&lt;/code&gt;) into the destination register.
The register &lt;code&gt;x0&lt;/code&gt; can be used as the destination when that return address is
not needed. Remember, &lt;code&gt;x0&lt;/code&gt; is the zero register, it is always equal to zero
and writes to it are always discarded.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;start:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;jal&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="no"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;somewhere&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;; direct jump, discard return address&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="na"&gt;...&lt;/span&gt;

&lt;span class="nl"&gt;somewhere:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;jal&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="no"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;f&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;; call function f, save return address into x1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="na"&gt;...&lt;/span&gt;

&lt;span class="nl"&gt;f:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="na"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;jalr&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="no"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;; Return to the address x1 (and no offset)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But seriously, don't you find that a bit... unreadable?&lt;/p&gt;
&lt;p&gt;The convention set by the proposed ABI is to use register &lt;code&gt;x1&lt;/code&gt; as the return
address, this register being refered to as &lt;code&gt;ra&lt;/code&gt;.
There are also pseudo-instructions that the programmer can use to take 
advantage of these conventions.&lt;/p&gt;
&lt;p&gt;The same code using pseudo-instructions and register alias would look like
this. Note that it is 100% equivalent to the snippet above and expands to the
exact same instructions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;start:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;j&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="no"&gt;somewhere&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;; unconditional direct jump&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="na"&gt;...&lt;/span&gt;

&lt;span class="nl"&gt;somewhere:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;jal&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="no"&gt;ra&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;f&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;; call function f&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="na"&gt;...&lt;/span&gt;

&lt;span class="nl"&gt;f:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="na"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;ret&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="c1"&gt;; Return from subroutine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using a register instead of the stack to store the return address (as is the
case in the x86 family, for instance) has several advantages.&lt;/p&gt;
&lt;p&gt;First, it simplifies the design of the processor a lot, keeping it true to the
Load/Store architecture.&lt;/p&gt;
&lt;p&gt;Second, it can make the code more efficient, as it is now up to the subroutine
to determine if the return address needs to be pushed onto the stack, or if it
can simply be left in a register when there are no nested calls. Especially in
our case, where the &lt;strong&gt;Fetch&lt;/strong&gt; and &lt;strong&gt;Memory&lt;/strong&gt; units cannot both access the RAM 
during the same cycle.&lt;/p&gt;
&lt;p&gt;Finally, although the convention is to use &lt;code&gt;x1&lt;/code&gt;, nothing stops you from using
any other register to save the return address. The official specification even
suggests using &lt;code&gt;x5&lt;/code&gt; as an alternate return address for &lt;a href="https://en.wikipedia.org/wiki/Millicode"&gt;millicode
routine&lt;/a&gt; calls to common prologue and
epilogue code for functions. Of course, the subroutine that is called must also
know which register has been used, in order to return to the correct address!&lt;/p&gt;
&lt;p&gt;Now you know why I didn't mention &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;ret&lt;/code&gt; in the previous article:
they are actually just plain jumps.&lt;/p&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>Control hazards with jumps and branches</title><link href="https://www.alrj.org/control-hazards-with-jumps-and-branches.html" rel="alternate"></link><published>2023-04-03T00:00:00+02:00</published><updated>2023-04-03T00:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2023-04-03:/control-hazards-with-jumps-and-branches.html</id><summary type="html">&lt;p&gt;I've talked about the data hazards in a previous installment, now let's talk 
about control hazards.
A control hazard is when we need to find the destination of a jump or a branch
and can't fetch any new instruction until this destination is known.&lt;/p&gt;
&lt;p&gt;When a branch instruction is fetched …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I've talked about the data hazards in a previous installment, now let's talk 
about control hazards.
A control hazard is when we need to find the destination of a jump or a branch
and can't fetch any new instruction until this destination is known.&lt;/p&gt;
&lt;p&gt;When a branch instruction is fetched, it must then be decoded in the second
cycle before the condition can be evaluated in the &lt;strong&gt;Execute&lt;/strong&gt; stage during the
third cycle. Only then can the CPU determine the new value for the &lt;code&gt;PC&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The same happens with jump instructions: the destination of a &lt;code&gt;JAL&lt;/code&gt;
instruction is the sum of the current &lt;code&gt;PC&lt;/code&gt; and an immediate value, the
destination of a &lt;code&gt;JALR&lt;/code&gt; instruction is the sum of a general purpose register
and an immediate value. In both cases, this addition can only be performed
after the instruction has been decoded.&lt;/p&gt;
&lt;p&gt;But if the instruction is a jump or if it is a branch that must be taken, it
means that the previous stages of the pipeline contain instructions that should
not be executed. The processor needs to have a way to abort them before they
reach any point where they could commit a change in the state of the machine.
This operation is called "Flushing" the pipeline.&lt;/p&gt;
&lt;p&gt;The signal for that is generated when the instruction moves from the 
&lt;strong&gt;Execute&lt;/strong&gt; stage to the &lt;strong&gt;Mem&lt;/strong&gt; stage.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Flush signal" src="https://www.alrj.org/images/riscv/Flush_reg.png"&gt;&lt;/p&gt;
&lt;p&gt;If the instruction is a jump or a branch that is taken, the signal &lt;code&gt;Flush@EX&lt;/code&gt;
is active during the first half of the cycle, and is used to clear all the 
pipeline registers in previous stages &lt;code&gt;IF/ID&lt;/code&gt; and &lt;code&gt;ID/EX&lt;/code&gt;.
&lt;code&gt;phi2&lt;/code&gt; is the complement of the clock signal. It goes high when the clock goes
low, and in this case it is used to reset the flip-flop that sends the flush
signal in the middle of the cycle. We don't want this signal to stay active
for too long, or we would risk clearing the next instruction when it is
fetched if the timing gets too tight!&lt;/p&gt;
&lt;p&gt;In the case of a branch instruction that is not taken, the processor simply
does nothing and continues as if it was a &lt;code&gt;NOP&lt;/code&gt; instruction.&lt;/p&gt;
&lt;h2&gt;Anything else ?&lt;/h2&gt;
&lt;p&gt;I have only mentionned jumps and branches here, but there will be other reasons
for the flow of instructions to be interrupted: interrupts, exceptions (maybe),
breakpoints, and system calls, also known in the RISC-V world as &lt;em&gt;environment 
calls&lt;/em&gt;. But these need the introduction of another bit of hardware in the
processor, the Control and Status Registers (CSRs). &lt;/p&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>I want a hardware multiplier</title><link href="https://www.alrj.org/i-want-a-hardware-multiplier.html" rel="alternate"></link><published>2022-07-05T00:00:00+02:00</published><updated>2022-07-05T00:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2022-07-05:/i-want-a-hardware-multiplier.html</id><summary type="html">&lt;p&gt;I'm currently working on the data multiplexer, the part that comes between
the CPU and the memory and is responsible for putting the right byte at the
right place, but I can't stop thinking about what comes next.&lt;/p&gt;
&lt;p&gt;And let me tell you, there's still quite a lot of development …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm currently working on the data multiplexer, the part that comes between
the CPU and the memory and is responsible for putting the right byte at the
right place, but I can't stop thinking about what comes next.&lt;/p&gt;
&lt;p&gt;And let me tell you, there's still quite a lot of development to do and many
topics to cover!&lt;/p&gt;
&lt;p&gt;The next article will probably be about branches and jumps, leaving out
everything related to exceptions and interrupts handling for the moment.&lt;/p&gt;
&lt;p&gt;On the development side, and in no particular order, there's waiting for
slower memory or IO device, actual memory mapping, CSR's and all the &lt;em&gt;system&lt;/em&gt;
instructions, exceptions and interrupts, global reset circuitry, ...&lt;br&gt;
And then the peripherals.&lt;/p&gt;
&lt;p&gt;There is also one thing that may come much later in the project but that I
don't want to rule out: a hardware multiplier. (And while at it, why not put a
division unit along with it? But that is another story.)&lt;/p&gt;
&lt;p&gt;In any case, there's just &lt;em&gt;no way&lt;/em&gt; that it will run in a single cycle, so it will
require some sort of mechanism to freeze the pipeline at the &lt;strong&gt;Execute&lt;/strong&gt; stage
while the "MulDiv" unit does its job. I expect this mechanism to be very similar 
to what I'll have to implement for the slow memory access anyway.&lt;/p&gt;
&lt;p&gt;Regarding the multiplier itself, chances are that I will go for simplicity and
do the slowish shift-add method because all the other ways I know are just too
expensive to build with discrete gates at 32 bits.&lt;/p&gt;
&lt;p&gt;And before you ask, no, I will not go out of order. The instruction following a
&lt;code&gt;mul&lt;/code&gt; will have to wait in the &lt;strong&gt;Decode&lt;/strong&gt; stage!&lt;/p&gt;
&lt;p&gt;Now, honestly, wouldn't it be very sad to have to draw the Mandelbrot set using
only software multiplication?&lt;/p&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>Of data hazards, bypasses and stalls</title><link href="https://www.alrj.org/of-data-hazards-bypasses-and-stalls.html" rel="alternate"></link><published>2022-06-28T00:00:00+02:00</published><updated>2025-01-24T00:00:00+01:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2022-06-28:/of-data-hazards-bypasses-and-stalls.html</id><summary type="html">&lt;p&gt;Remember that a data hazard occurs when an instruction waits for the result of
a previous instruction. &lt;/p&gt;
&lt;p&gt;In the following example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t1&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;; a0  ←  t0 + t1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t2&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;; a1  ←  a0 - t2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the &lt;code&gt;add&lt;/code&gt; instruction stores the result into register &lt;code&gt;a0&lt;/code&gt; when it reaches the
&lt;strong&gt;Writeback&lt;/strong&gt; stage …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Remember that a data hazard occurs when an instruction waits for the result of
a previous instruction. &lt;/p&gt;
&lt;p&gt;In the following example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t1&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;; a0  ←  t0 + t1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t2&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;; a1  ←  a0 - t2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the &lt;code&gt;add&lt;/code&gt; instruction stores the result into register &lt;code&gt;a0&lt;/code&gt; when it reaches the
&lt;strong&gt;Writeback&lt;/strong&gt; stage at clock cycle 5,&lt;br&gt;
but the &lt;code&gt;sub&lt;/code&gt; instruction wants to read &lt;code&gt;a0&lt;/code&gt; when it reaches the stage &lt;strong&gt;Decode&lt;/strong&gt;
in clock cycle 3.&lt;br&gt;
Of course, at cycle 3, the result of the first instruction has not been written
into the register file yet.&lt;/p&gt;
&lt;p&gt;Instead of waiting two cycle for the value to be available, we could instead
create a shortcut, a way for the second instruction to get the value of &lt;code&gt;a0&lt;/code&gt;
directly out of a subsequent stage of the pipeline. In other words, a &lt;em&gt;bypass&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In practice, it's not just one bypass that we need but several of them!&lt;/p&gt;
&lt;h2&gt;The forwarding unit&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;Execute&lt;/strong&gt; stage needs to know the correct value for both &lt;code&gt;rs1&lt;/code&gt; and &lt;code&gt;rs2&lt;/code&gt;
and each of them can come from three different sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The register file. That's the canonical source for the value, no bypass is
   used.&lt;/li&gt;
&lt;li&gt;The output of the previous instruction. This means the value is present in
   the &lt;code&gt;EX/MEM&lt;/code&gt; pipeline register, which is equivalent to say that it comes from 
   the &lt;strong&gt;Memory&lt;/strong&gt; stage.&lt;/li&gt;
&lt;li&gt;The output of the instruction before that. In this case, the value is in the
   &lt;code&gt;MEM/WB&lt;/code&gt; pipeline register, or in the &lt;strong&gt;Writeback&lt;/strong&gt; stage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any instruction before that will have had the time to go through the &lt;strong&gt;Writeback&lt;/strong&gt;
stage.&lt;/p&gt;
&lt;p&gt;Here is how we determine the correct source for the value of &lt;code&gt;rs1&lt;/code&gt;:&lt;br&gt;
&lt;img alt="rs1 EX forwarding" src="https://www.alrj.org/images/riscv/rs1_forwarding_EX.png"&gt;&lt;/p&gt;
&lt;p&gt;The forwarding unit is always active, it does not care whether the register is
actually needed by the ALU operation or not.&lt;/p&gt;
&lt;p&gt;The logic is not very complex. First, a comparison is made between the the
source register number and the destination register number of the previous two
instructions (the one in &lt;strong&gt;MEM&lt;/strong&gt; and the one in &lt;strong&gt;WB&lt;/strong&gt;). Then it is also checked
that these previous two instructions do actually want to write a value back.
A &lt;code&gt;store&lt;/code&gt; instruction, for instance, does not write anything back in the
register file, so cannot be the source of a bypass.&lt;/p&gt;
&lt;p&gt;After these two tests, we know if &lt;code&gt;rs1&lt;/code&gt; is present in &lt;strong&gt;MEM&lt;/strong&gt; or in &lt;strong&gt;WB&lt;/strong&gt; (or
both), and it is only a question of priority to know where we want to take it
from. Highest priority is &lt;strong&gt;MEM&lt;/strong&gt;, then if not present there, try to take it
from &lt;strong&gt;WB&lt;/strong&gt;, and otherwise default back to what was fetched from the register
file.&lt;/p&gt;
&lt;p&gt;The logic is exactly the same for &lt;code&gt;rs2&lt;/code&gt;:&lt;br&gt;
&lt;img alt="rs2 EX forwarding" src="https://www.alrj.org/images/riscv/rs2_forwarding_EX.png"&gt;&lt;/p&gt;
&lt;p&gt;There is another place where a bypass is required, it's in the &lt;strong&gt;Memory&lt;/strong&gt; stage.
When a &lt;code&gt;load&lt;/code&gt; into a register is immediately followed by a &lt;code&gt;store&lt;/code&gt; of the
same register, this value must be forwarded as well.&lt;/p&gt;
&lt;p&gt;&lt;img alt="rs2 MEM forwarding" src="https://www.alrj.org/images/riscv/rs2_forwarding_MEM.png"&gt;&lt;/p&gt;
&lt;h2&gt;The bypasses&lt;/h2&gt;
&lt;p&gt;All right, we have all those signals coming out of the forwarding unit, but
what do we do with them?&lt;/p&gt;
&lt;p&gt;We wire the bypasses, of course!&lt;/p&gt;
&lt;p&gt;The first bypasses are the ones in the &lt;strong&gt;EX&lt;/strong&gt; stage, and they look like this:&lt;br&gt;
&lt;img alt="EX bypasses" src="https://www.alrj.org/images/riscv/EX_bypasses.png"&gt;&lt;/p&gt;
&lt;p&gt;The selection signals will enable only one buffer for each of &lt;code&gt;rs1&lt;/code&gt; and &lt;code&gt;rs2&lt;/code&gt;,
so that the correct value can be sent to the ALU or further down the pipeline.&lt;/p&gt;
&lt;p&gt;In the &lt;strong&gt;Mem&lt;/strong&gt; stage, it's the same principle, only simpler because there is
only one register and two sources:&lt;br&gt;
&lt;img alt="MEM bypasses" src="https://www.alrj.org/images/riscv/MEM_bypasses.png"&gt;&lt;/p&gt;
&lt;h2&gt;The stall logic unit&lt;/h2&gt;
&lt;p&gt;There's one situation where we cannot rely just on a bypass, though, it's the
use of a register by the ALU in an instruction directly following a &lt;code&gt;load&lt;/code&gt;. 
The second instruction needs to wait for the value to be loaded from memory,
and for that it needs to be stalled.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Load stall" src="https://www.alrj.org/images/riscv/Load_stall.png"&gt;&lt;/p&gt;
&lt;p&gt;We stall if the ALU wants, as one of its input, the content of a register that
would come from the previous instruction, and that previous instruction is a
&lt;code&gt;load&lt;/code&gt;. All the other cases are covered by the bypasses we just implemented 
above!&lt;/p&gt;
&lt;h2&gt;The stall mechanism&lt;/h2&gt;
&lt;p&gt;Let's keep things simple for now and consider that a memory access can always
be done in one cycle. As a consequence, the instruction present in the &lt;strong&gt;EX&lt;/strong&gt;
stage cannot advance and must stay in there, while the &lt;code&gt;load&lt;/code&gt; instruction in
&lt;strong&gt;MEM&lt;/strong&gt; stage moves to the &lt;strong&gt;WB&lt;/strong&gt; stage. That leaves a &lt;em&gt;bubble&lt;/em&gt; between them.&lt;/p&gt;
&lt;p&gt;If the instruction in &lt;strong&gt;EX&lt;/strong&gt; cannot advance, neither can thoses in the previous
stages &lt;strong&gt;Decode&lt;/strong&gt; and &lt;strong&gt;Fetch&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;On all the pipeline registers between &lt;strong&gt;EX&lt;/strong&gt; and &lt;strong&gt;Mem&lt;/strong&gt;, a stall signal
will prevent a new value to be clocked in by disabling the &lt;code&gt;Write Enable&lt;/code&gt; input:&lt;br&gt;
&lt;img alt="EX stall" src="https://www.alrj.org/images/riscv/EX_Stall.png"&gt;&lt;/p&gt;
&lt;p&gt;The same signal is applied to the other pipeline registers in &lt;code&gt;ID/EX&lt;/code&gt; and 
&lt;code&gt;IF/ID&lt;/code&gt;, as well as to the fetch unit so that the &lt;code&gt;PC&lt;/code&gt; does not get incremented.&lt;/p&gt;
&lt;p&gt;There is just one pipeline register that we need to treat differently: the
register that conveys the actual instruction's actions from &lt;strong&gt;EX&lt;/strong&gt; to
&lt;strong&gt;MEM&lt;/strong&gt;, that one must be cleared to become a &lt;code&gt;nop&lt;/code&gt;, our bubble.&lt;/p&gt;
&lt;p&gt;&lt;img alt="EX bubble" src="https://www.alrj.org/images/riscv/EX_Bubble.png"&gt;&lt;/p&gt;
&lt;p&gt;This concludes the part on how the data hazards will be handled in Astorisc. Stay 
tuned for the next part where we'll tackle the control hazards induced by the
jumps and branch operations.&lt;/p&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>Astorisc: The simulation begins</title><link href="https://www.alrj.org/astorisc-the-simulation-begins.html" rel="alternate"></link><published>2022-05-09T00:00:00+02:00</published><updated>2022-05-09T18:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2022-05-09:/astorisc-the-simulation-begins.html</id><summary type="html">&lt;p&gt;These last few weeks, I've been working on implementing the CPU in
&lt;a href="https://github.com/hneemann/Digital"&gt;Digital&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My initial intention was to stay as close as possible to what will be the
actual implementation, but in practice, it may not have been a good idea,
because it didn't always play well with the simulation …&lt;/p&gt;</summary><content type="html">&lt;p&gt;These last few weeks, I've been working on implementing the CPU in
&lt;a href="https://github.com/hneemann/Digital"&gt;Digital&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My initial intention was to stay as close as possible to what will be the
actual implementation, but in practice, it may not have been a good idea,
because it didn't always play well with the simulation. Most of the time,
when trying to start the simulation, Digital would complain that more than
one output was active on a wire, causing a short circuit in the shifter unit.&lt;/p&gt;
&lt;p&gt;The problem went away when I switched from pairs of buffer driven by two 
complementary signals to plain old multiplexers. For the physical 
implementation of the processor, selection between two possible values will
likely be implemented using the following logic:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Selector out of buffers" src="https://www.alrj.org/images/riscv/Selector_using_buffers.png"&gt;&lt;/p&gt;
&lt;p&gt;When the &lt;em&gt;Sel&lt;/em&gt; input is low, the buffer for the &lt;em&gt;A&lt;/em&gt; input is active, while the
buffer for &lt;em&gt;B&lt;/em&gt; is kept in high impedance (meaning its outputs are like 
disconnected). When &lt;em&gt;Sel&lt;/em&gt; is brought high, it's the opposite, and the output
is equal to the value on the &lt;em&gt;B&lt;/em&gt; input.&lt;/p&gt;
&lt;p&gt;But for the moment, the simulation will use multiplexers, like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Selector out of mux" src="https://www.alrj.org/images/riscv/Selector_using_mux.png"&gt;&lt;/p&gt;
&lt;p&gt;When &lt;em&gt;Sel&lt;/em&gt; is low (0), the &lt;em&gt;Output&lt;/em&gt; mimics &lt;em&gt;A&lt;/em&gt;. When it's high, the &lt;em&gt;Output&lt;/em&gt;
mimics &lt;em&gt;B&lt;/em&gt;. Technically, this is equivalent and will work just like the one
above.&lt;/p&gt;
&lt;h1&gt;Running the first program&lt;/h1&gt;
&lt;p&gt;Here's how our processor looks like right now (click to enlarge).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/riscv/Astorisc_first_run.png"&gt;&lt;img alt="Astorisc" src="https://www.alrj.org/images/riscv/thumb-Astorisc_first_run.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Fetch&lt;/em&gt;, &lt;em&gt;Instruction Decode&lt;/em&gt;, &lt;em&gt;Execute&lt;/em&gt;, &lt;em&gt;Memory&lt;/em&gt;, and &lt;em&gt;Writeback&lt;/em&gt; stages
appear clearly separated with the pipeline registers in cyan between them.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Decode&lt;/em&gt; logic outputs a whole bunch of simple signals that will tell the
next stages what action they must take.&lt;/p&gt;
&lt;p&gt;On the top will be our control logic, currently very primitive. On the bottom 
will come the RAM and I/O access, for now only represented by a single RAM, not
even ready to handle byte or half-word access.&lt;/p&gt;
&lt;p&gt;As you can see, there's no bypasses and forwarding unit yet, and no stall/flush
control logic. So how can we make our first program work? Simply by inserting
&lt;strong&gt;nop&lt;/strong&gt; instructions in our program where the processor would have needed to
wait for a value to be available, or where it would have needed to flush the
pipeline (to discard the instructions right after a jmp or a branch). By 
definition, &lt;strong&gt;nop&lt;/strong&gt;s do nothing, and there is no harm to execute them even if
they come from the wrong wode path.&lt;/p&gt;
&lt;p&gt;This allowed me to run the following program that computes the Fibonacci
series until the result gets above 1000:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;_start:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;li&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="c1"&gt;; start with first number = 1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;li&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="c1"&gt;; and second number = 1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;li&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="c1"&gt;; Useless, but we&amp;#39;ll store the result in a3&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;li&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;; Set our upper limit&lt;/span&gt;

&lt;span class="nl"&gt;fib:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;nop&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="c1"&gt;; the next value in the sequence is&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a2&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;;  the first number + the second number&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a2&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;; new first number is the old second one&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;nop&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a3&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;; new second number is the computed value&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;bltu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;a5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;fib&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;; loop if we are not yet at 1000&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;nop&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;nop&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;nop&lt;/span&gt;


&lt;span class="nl"&gt;_end:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;_end&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;; endless loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Maybe there are too many &lt;strong&gt;nop&lt;/strong&gt;s, but who cares? It runs... And soon, it
will run without all those pesky &lt;strong&gt;nop&lt;/strong&gt;s!&lt;/p&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>Just a few components ordered</title><link href="https://www.alrj.org/just-a-few-components-ordered.html" rel="alternate"></link><published>2022-04-14T00:00:00+02:00</published><updated>2022-04-14T18:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2022-04-14:/just-a-few-components-ordered.html</id><summary type="html">&lt;p&gt;I had some components to buy at Mouser for an unrelated project, but my order 
wasn't going to reach 50€ and I wouldn't get free shipping...&lt;/p&gt;
&lt;p&gt;So I added a few of nearly every logic gate from the AUC family in the basket.
These are like the usual &lt;em&gt;74 LS …&lt;/em&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;I had some components to buy at Mouser for an unrelated project, but my order 
wasn't going to reach 50€ and I wouldn't get free shipping...&lt;/p&gt;
&lt;p&gt;So I added a few of nearly every logic gate from the AUC family in the basket.
These are like the usual &lt;em&gt;74 LS&lt;/em&gt; or &lt;em&gt;74 HC&lt;/em&gt; family but they can work at very
low voltage and are &lt;strong&gt;super fast&lt;/strong&gt; ! They aren't cheap, though, so I ended up
with an order waaay above 50€. Well, that's the price to pay for starting the
actual R&amp;amp;D.&lt;/p&gt;
&lt;p&gt;These logic gates exist in traditional 4 gates per package, or 6 gates for the
inverters, but also in &lt;em&gt;Little Logic&lt;/em&gt; that offer just a single or a double
gate per package. This is what I ordered, because it makes prototyping much
easier. But what did I get exaclty?&lt;/p&gt;
&lt;h1&gt;SN74 AUC 2G 00 DCU&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;SN74&lt;/em&gt; is the typical prefix for these types of logic gates (there are other
groups that we'll ignore here).&lt;br&gt;
&lt;em&gt;AUC&lt;/em&gt; is the Advanced Ultra-low-voltage CMOS family. It works from 0.8V to 
2.7V and its inputs tolerate a signal up to 3.6V.&lt;br&gt;
&lt;em&gt;2G&lt;/em&gt; means it packs two gates,&lt;br&gt;
&lt;em&gt;00&lt;/em&gt; is the code for the NAND function,&lt;br&gt;
&lt;em&gt;DCU&lt;/em&gt; represents the physical package. It's pretty small, about 2mm x 3mm
with the leads.&lt;/p&gt;
&lt;p&gt;It means these are dual NAND gates.&lt;/p&gt;
&lt;p&gt;&lt;img alt="sn74auc2g00dcu package" src="https://www.alrj.org/images/riscv/AUC/2G__DCU.png"&gt;
&lt;img alt="sn74auc2g00dcu logic diagram" src="https://www.alrj.org/images/riscv/AUC/2G00.png"&gt;&lt;/p&gt;
&lt;h1&gt;SN74 AUC 2G 02 DCU&lt;/h1&gt;
&lt;p&gt;These look a lot like the ones above, but they are dual NOR gates.&lt;/p&gt;
&lt;p&gt;&lt;img alt="sn74auc2g02dcu package" src="https://www.alrj.org/images/riscv/AUC/2G__DCU.png"&gt;
&lt;img alt="sn74auc2g02dcu logic diagram" src="https://www.alrj.org/images/riscv/AUC/2G02.png"&gt;&lt;/p&gt;
&lt;h1&gt;SN74 AUC 2G 04 DBV&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;04&lt;/em&gt; is the numeric code for the inverter,&lt;br&gt;
&lt;em&gt;DBV&lt;/em&gt; is another package. That makes sense because inverters have only one
input, not two, so only six pins are needed to pack two of them.&lt;/p&gt;
&lt;p&gt;&lt;img alt="sn74auc2g04dbv package" src="https://www.alrj.org/images/riscv/AUC/2G04DBV.png"&gt;
&lt;img alt="sn74auc2g04dbv logic diagram" src="https://www.alrj.org/images/riscv/AUC/2G04.png"&gt;&lt;/p&gt;
&lt;h1&gt;SN74 AUC 2G 08 DCU&lt;/h1&gt;
&lt;p&gt;We are back with some &lt;em&gt;DCU&lt;/em&gt; packages, and &lt;em&gt;08&lt;/em&gt; is the code for AND gates.&lt;/p&gt;
&lt;p&gt;&lt;img alt="sn74auc2g08dcu package" src="https://www.alrj.org/images/riscv/AUC/2G__DCU.png"&gt;
&lt;img alt="sn74auc2g08dcu logic diagram" src="https://www.alrj.org/images/riscv/AUC/2G08.png"&gt;&lt;/p&gt;
&lt;h1&gt;SN74 AUC 2G 32 DCU&lt;/h1&gt;
&lt;p&gt;You know the drill. Here, &lt;em&gt;32&lt;/em&gt; means OR gates.&lt;/p&gt;
&lt;p&gt;&lt;img alt="sn74auc2g32dcu package" src="https://www.alrj.org/images/riscv/AUC/2G__DCU.png"&gt;
&lt;img alt="sn74auc2g32dcu logic diagram" src="https://www.alrj.org/images/riscv/AUC/2G32.png"&gt;&lt;/p&gt;
&lt;h1&gt;SN74 AUC 2G 86 DCU&lt;/h1&gt;
&lt;p&gt;And here is the last classic logic gates: the XOR gate, represented by
the &lt;em&gt;86&lt;/em&gt; code.&lt;/p&gt;
&lt;p&gt;&lt;img alt="sn74auc2g86dcu package" src="https://www.alrj.org/images/riscv/AUC/2G__DCU.png"&gt;
&lt;img alt="sn74auc2g86dcu logic diagram" src="https://www.alrj.org/images/riscv/AUC/2G86.png"&gt;&lt;/p&gt;
&lt;h1&gt;SN74 AUC 2G 53 DCU&lt;/h1&gt;
&lt;p&gt;Now, here is something new ! This is the famous analog FET switch that will
help us build various higher level blocks like the adder.&lt;br&gt;
Here's how the datasheets presents it:&lt;/p&gt;
&lt;p&gt;&lt;img alt="sn74auc2g53dcu package" src="https://www.alrj.org/images/riscv/AUC/2G53DCU.png"&gt;
&lt;img alt="sn74auc2g53dcu logic diagram" src="https://www.alrj.org/images/riscv/AUC/2G53.png"&gt;&lt;/p&gt;
&lt;p&gt;Admittedly, that logic diagram looks a bit more complex. Here's what it does.&lt;/p&gt;
&lt;p&gt;It connects &lt;strong&gt;COM&lt;/strong&gt; with either &lt;strong&gt;Y1&lt;/strong&gt; or &lt;strong&gt;Y2&lt;/strong&gt;, depending on the input &lt;strong&gt;A&lt;/strong&gt;.
Unless the input &lt;strong&gt;INH&lt;/strong&gt; is high, in which case &lt;strong&gt;COM&lt;/strong&gt; is not connected to 
anything (both switches are open).&lt;/p&gt;
&lt;p&gt;The key point is that the connection between &lt;strong&gt;COM&lt;/strong&gt; and &lt;strong&gt;Yn&lt;/strong&gt; is really just
like a switch, meaning the &lt;em&gt;propagation delay&lt;/em&gt; is very, very short. While it
can take up to 2.2 ns to switch from one &lt;strong&gt;Y&lt;/strong&gt; to the other, or to enable or
disable the switch, it can transmit a signal in less than 0.1 ns !&lt;/p&gt;
&lt;p&gt;This is the property that will help us build very fast &lt;em&gt;chains&lt;/em&gt;, or ripple,
as we have in adders or in AND gates with a lot of inputs.&lt;/p&gt;
&lt;h1&gt;SN74 AUC 1G 74 DCU&lt;/h1&gt;
&lt;p&gt;Only one gate in this package, as can be seen from the &lt;em&gt;1G&lt;/em&gt; part of the name.&lt;br&gt;
&lt;em&gt;74&lt;/em&gt; is the code for a D-Flip-Flop. &lt;/p&gt;
&lt;p&gt;&lt;img alt="sn74auc1g74dcu package" src="https://www.alrj.org/images/riscv/AUC/1G74DCU.png"&gt;&lt;/p&gt;
&lt;p&gt;There's no reason to include the logic diagram for the flip-flop. I also won't
explain how it works, I'm sure many people have already done so.&lt;/p&gt;
&lt;h1&gt;SN74 AUC 16 244 DGG&lt;/h1&gt;
&lt;p&gt;The &lt;em&gt;244&lt;/em&gt; is nothing more than a buffer, or a driver, whose outputs can be
disconnected (tri-stated).&lt;br&gt;
&lt;em&gt;16&lt;/em&gt; because that device is 16 bits.&lt;br&gt;
&lt;em&gt;DGG&lt;/em&gt; is the largest package available for this device, but don't be fooled.
The leads pitch is a mere 0.5 mm.&lt;/p&gt;
&lt;h1&gt;SN74 ALVCH 16 823 DGG&lt;/h1&gt;
&lt;p&gt;Here, we change family for a &lt;em&gt;ALVCH&lt;/em&gt; device, for Advanced Low Voltage CMOS with
Hold. This can work with slightly higher voltage than the AUC, up to 3.6V. This
can be useful to drive the lines a bit stronger, for instance from board to
board.&lt;br&gt;
Be aware that &lt;em&gt;16&lt;/em&gt; is a trap, this part is actually 18 bits!&lt;br&gt;
The &lt;em&gt;823&lt;/em&gt; is a bus interface Flip-flop, with three usefull features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3-state outputs,&lt;/li&gt;
&lt;li&gt;a &lt;em&gt;clock enable&lt;/em&gt; pin, that can be used to prevent clocking in a new input 
   value,&lt;/li&gt;
&lt;li&gt;an asynchronous &lt;em&gt;clear&lt;/em&gt; pin, that set all outputs low independently of the
   clock.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm pretty sure various parts of our processor will make use of one or the
other of the last two feature.&lt;/p&gt;
&lt;h1&gt;That's all&lt;/h1&gt;
&lt;p&gt;That's all the parts I've ordered this time, unless we count the thousand 100 nF
capacitors, and a mere hundred 10 nF ones :)&lt;br&gt;
These are 0402 in imperial, or 1005 in metric. That means they are 1mm long by
0.5mm wide. This is the smallest size I have ever soldered by hand, and the
experience wasn't too painful.&lt;/p&gt;
&lt;h1&gt;Notes&lt;/h1&gt;
&lt;p&gt;The diagrams in this article have been copied from their respective datasheets
and are © Texas Instruments Incorporated.
The logic diagram for the dual XOR gate has been edited from the dual OR gate.&lt;/p&gt;
&lt;p&gt;Links to the datasheets of the gates described above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc2g00.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc2g00.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc2g02.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc2g02.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc2g04.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc2g04.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc2g08.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc2g08.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc2g32.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc2g32.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc2g86.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc2g86.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc2g53.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc2g53.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc1g74.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc1g74.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74auc16244.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74auc16244.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ti.com/lit/ds/symlink/sn74alvch16823.pdf"&gt;https://www.ti.com/lit/ds/symlink/sn74alvch16823.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>Astorisc: Building blocks and components</title><link href="https://www.alrj.org/astorisc-building-blocks-and-components.html" rel="alternate"></link><published>2022-03-29T00:00:00+02:00</published><updated>2022-03-29T18:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2022-03-29:/astorisc-building-blocks-and-components.html</id><summary type="html">&lt;p&gt;Throughout the entire processor, there are a few basic building blocks that will
be used in various places. Let's have a look at some of them.&lt;/p&gt;
&lt;h1&gt;Registers&lt;/h1&gt;
&lt;p&gt;By far, the block that we'll use the most is the register. Not only in the
register file, but also between each stage …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Throughout the entire processor, there are a few basic building blocks that will
be used in various places. Let's have a look at some of them.&lt;/p&gt;
&lt;h1&gt;Registers&lt;/h1&gt;
&lt;p&gt;By far, the block that we'll use the most is the register. Not only in the
register file, but also between each stage of the pipeline. &lt;/p&gt;
&lt;p&gt;Typically implemented
with D-Flip-Flops, a register has &lt;em&gt;input&lt;/em&gt; pins, &lt;em&gt;output&lt;/em&gt; pins, a &lt;em&gt;clock&lt;/em&gt;
line and an &lt;em&gt;output enable&lt;/em&gt; line.&lt;br&gt;
When the &lt;em&gt;clock&lt;/em&gt; transitions from one state (let's say low) to the other
(high), the device "saves" the inputs internally in its flip-flops and provides
the same values on its outputs.&lt;br&gt;
The &lt;em&gt;output enable&lt;/em&gt; line can be used to put the output in high-impedence
mode, which effectively disconnects the outputs without affecting the internal
operation of the flip-flops inside the device.&lt;/p&gt;
&lt;p&gt;Some components also have a &lt;em&gt;clock enable&lt;/em&gt; line. When not active, the
&lt;em&gt;clock&lt;/em&gt; transitions have no effect and the internal flip-flops do not change.
This could prove usefull in the register-file for instance, where only one
register (at most) needs to be written to during the &lt;strong&gt;Writeback&lt;/strong&gt; stage.&lt;/p&gt;
&lt;p&gt;Some other devices have a synchronous or asynchronous &lt;em&gt;clear&lt;/em&gt; signal, to set
all the flip-flops at zero (low level). &lt;em&gt;Synchronous&lt;/em&gt; means that it only
happens on the clock transition, &lt;em&gt;asynchronous&lt;/em&gt; means that the effect is
immediate. Maybe that could be used to "kill" instructions when flushing the
pipeline: set the entire decoded instruction to just a bunch of zeros.&lt;/p&gt;
&lt;p&gt;Constructing a register is fairly easy: there are components that do exactly
that already. They will often be only 8 or 16 bits wide, which is too small for
our 32 bits register, but it is only a matter of using one of them for the low
half-word (bits 0 to 15), another for the high half-word (bits 16 to 31), and
tying together the clock and other control lines.&lt;/p&gt;
&lt;h1&gt;Adders&lt;/h1&gt;
&lt;p&gt;We will need at least three 32 bits adders in our processor.
Well, the first will only ever compute PC+4 in the &lt;strong&gt;Fetch&lt;/strong&gt; stage, so that
one could be implemented as a 30 bits incrementer. We'll see later how an 
incrementer can be constructed using a simplified version of the adder.&lt;/p&gt;
&lt;p&gt;The second one is part of the ALU, in the &lt;strong&gt;Execute&lt;/strong&gt; stage. That one needs
to do substractions and signed arithmetic as well, so might need some poking
at its inputs, depending on the function we want it to perform.&lt;br&gt;
Quick reminder: in order to subtract in two's-complement, we just need to 
bitwise invert the second operand and set the carry-in to 1.&lt;/p&gt;
&lt;p&gt;The third adder is found in the same stage, but its role will be solely to
compute the next PC in case of a jump or a branch. Branches and the &lt;code&gt;jal&lt;/code&gt;
instruction will compute PC + some offset, while &lt;code&gt;jalr&lt;/code&gt; needs an arbitrary
base register + the offset.&lt;/p&gt;
&lt;p&gt;All these will be constructed following the &lt;a href="http://forum.6502.org/viewtopic.php?f=4&amp;amp;t=6282#p78246"&gt;"FET-switch adder" idea that
emerged from the 6502 forums&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For speed consideration, we may end up implementing a carry-select stage.&lt;/p&gt;
&lt;p&gt;I was also pondering about implementing the &lt;code&gt;jal&lt;/code&gt; instruction during the 
&lt;strong&gt;Decode&lt;/strong&gt; stage (using a fourth adder), since that one does only require PC 
and an immediate offset, and no source register. I then ditched this idea, 
though, because it will be &lt;em&gt;incredibly&lt;/em&gt; easier to do all our jumps, branches 
and interrupts all at the same stage! Trust me, we don't want to take a shortcut
here.&lt;/p&gt;
&lt;h1&gt;Comparators&lt;/h1&gt;
&lt;p&gt;The ALU will need what I'd call a full arithmetic comparator, capable of doing
magnitude comparisons for both signed and unsigned integers. In the Risc-V ISA,
the branch comparisons are either equal, not equal, less than, or greater or 
equal. There is also the "set if less than" family of instructions that need to
do signed and unsigned comparisons.&lt;/p&gt;
&lt;p&gt;Many other comparators, as far as I can imagine at this point, will be binary
equality comparators, most of them in the &lt;strong&gt;Decode&lt;/strong&gt; stage where they will be
matched against parts of the instruction to make the decoded signals.&lt;/p&gt;
&lt;p&gt;More equality comparators will be needed in the forwarding logic. These would 
only be 5-bit, comparing the destination register of the first instruction with
one of the source registers of the next instructions to determine if a bypass
needs to be activated.&lt;/p&gt;
&lt;p&gt;Also, equality comparators will likely be used to determine which memory or IO
space is active, based on the address.&lt;/p&gt;
&lt;p&gt;Here again, the comparator can be built with FET-switches for the speed. We will
also see how smaller comparators can be cascaded to build one that is 32 bit
wide.&lt;/p&gt;
&lt;h1&gt;Decoders/selectors&lt;/h1&gt;
&lt;p&gt;Selectors (or decoders) take a binary number as their input to set a single one
of their outputs to a given state. A typical example for this function is the
classic 3-to-8 decoder, the 74LVC138, that has 3 inputs and 8 outputs.
In order to be cascaded to build wider selectors, these devices often have one
or more &lt;em&gt;enable&lt;/em&gt; pins. For instance, the 74LVC138 has three of them, one
active high and two active low.&lt;/p&gt;
&lt;p&gt;Astorisc will need a few 5-to-32 selectors in the register file, and will also
need some yet undetermined selectors in the RAM modules, to access the right
chips.&lt;/p&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>Astorisc: The pipeline stages and hazards</title><link href="https://www.alrj.org/astorisc-the-pipeline-stages-and-hazards.html" rel="alternate"></link><published>2022-01-18T00:00:00+01:00</published><updated>2022-01-18T16:40:00+01:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2022-01-18:/astorisc-the-pipeline-stages-and-hazards.html</id><summary type="html">&lt;p&gt;I would like to go more into detail about each stage of the pipeline, what
they do and how they work. I know I said in the previous installment that I
would not go into the details of hazards, but it looks like I will need it
to document my …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I would like to go more into detail about each stage of the pipeline, what
they do and how they work. I know I said in the previous installment that I
would not go into the details of hazards, but it looks like I will need it
to document my choices in the processor architecture. So let's start with that.&lt;/p&gt;
&lt;h1&gt;Pipeline hazards&lt;/h1&gt;
&lt;p&gt;Inside our pipeline, the instructions interact with each other.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An instruction may need a resource currently used by another instruction.&lt;br&gt;
   → structural hazard&lt;/li&gt;
&lt;li&gt;An instruction may depend on the result value of a previous instruction.&lt;br&gt;
   → data hazard&lt;/li&gt;
&lt;li&gt;An instruction may depend on the calculation of a new address for the
   Program Counter (jumps and branches),&lt;br&gt;
   → control hazard&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Structural hazards&lt;/h2&gt;
&lt;p&gt;The most prominent structural hazard in our implementation is the access to the
memory. To resolve it, whenever an instruction wants to load or store data into
memory during the &lt;strong&gt;Mem&lt;/strong&gt; stage, we have to tell the &lt;strong&gt;Fetch&lt;/strong&gt; stage that it can
not get the next instruction from memory during this cycle and has to stall.&lt;/p&gt;
&lt;p&gt;This type of hazard could also be solved by using dual-ported RAM, so that both
&lt;strong&gt;Mem&lt;/strong&gt; and &lt;strong&gt;Fetch&lt;/strong&gt; stages have concurrent access to the memory, but the price
for several megabytes of dual-ported RAM is simply prohibitive.&lt;/p&gt;
&lt;p&gt;Another way to resolve this hazard, often used in microcontrollers, is to have
different, dedicated memory spaces: one for the instructions and another one
for the data. This is perfect fine when the program running is well defined
beforehands, but not really appropriate in the case of a general purpose
processor that needs to load the programs into memory on demand.&lt;br&gt;
Interestingly enough, modern processors do actually use a similar approach, by
using distinct caches for instructions and data.&lt;/p&gt;
&lt;h2&gt;Data hazards&lt;/h2&gt;
&lt;p&gt;Data hazards occur when an instruction needs as one of its input the result
of a previous instruction that has not gone through the &lt;strong&gt;Writeback&lt;/strong&gt; stage yet.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  addi r4, r0, 30
  addi r5, r4, -12
  addi r6, r4, 25
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the second instruction enters the &lt;strong&gt;Decode&lt;/strong&gt; stage, where it will also
read the values of the source registers, the value of the register &lt;code&gt;r4&lt;/code&gt; has not
been updated yet inside the register file. Two solutions exist to resolve this
type of hazard:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Wait (stall) until the register file has been updated, or&lt;/li&gt;
&lt;li&gt;Bypass the register file: if the result is available from one of the
     pipeline registers, get it directly from there.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In our example above, as soon as the first instruction has gone through the
&lt;strong&gt;Execute&lt;/strong&gt; stage, the resulting value for &lt;code&gt;r4&lt;/code&gt; is available in the next
pipeline register. One clock cycle later it is present in the &lt;strong&gt;Writeback&lt;/strong&gt;
register, then after half a clock (more on this later) it gets written to
the register file. If we were to stall the pipeline, that would induce a
penalty of two clock cycles.&lt;/p&gt;
&lt;p&gt;Similarly, the third instruction also depends on the result of the first one.
If we were to wait for the correct value to be present in the register file for
&lt;code&gt;r4&lt;/code&gt;, only one clock cycle would be needed, though, because the other one was
spent executing the middle instruction. But just as we did for the second
instruction, we could use a bypass and forward the correct value directly from
the &lt;strong&gt;Memory&lt;/strong&gt; stage.&lt;/p&gt;
&lt;p&gt;For any instruction after that one, the value for &lt;code&gt;r4&lt;/code&gt; would be present in the
register file and there would be no hazard.&lt;/p&gt;
&lt;p&gt;But does that mean all data hazards are covered with these two bypasses ? Now,
consider the following example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  lb   r7, 10(r8)
  addi r8, r7, 42
  xori r9, r7, -1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this situation, the data for r7 will be available in one of the pipeline
registers only after the first instruction has completed the &lt;strong&gt;Memory&lt;/strong&gt; stage.
When we have a register dependency on a &lt;em&gt;load&lt;/em&gt; instruction, we have no choice
but stall the next instruction (&lt;code&gt;addi&lt;/code&gt; in this case) for one clock cycle.
After that, the correct value for &lt;code&gt;r7&lt;/code&gt; will be present in the &lt;strong&gt;Writeback&lt;/strong&gt;
register, from which it can be forwarded.&lt;/p&gt;
&lt;p&gt;The third instruction does not need to be stalled, and can make use of the
bypass from the &lt;strong&gt;Writeback&lt;/strong&gt; register.&lt;/p&gt;
&lt;h2&gt;Control hazards&lt;/h2&gt;
&lt;p&gt;Control hazards happen for jump and branch instructions because in either case,
we need the result of the &lt;strong&gt;Execute&lt;/strong&gt; stage in order to compute the new value
of the program counter.&lt;/p&gt;
&lt;p&gt;For conditional branches, the ALU has to do the comparison to know wether the
branch is taken or not. It means that in all situations, the target of a branch
instruction will only be known after the instruction has gone through the
&lt;strong&gt;Execute&lt;/strong&gt; stage.&lt;/p&gt;
&lt;p&gt;For jump (&lt;code&gt;jal&lt;/code&gt;) and jump register (&lt;code&gt;jalr&lt;/code&gt;), the ALU computes either the sum of
the PC and the offset or the sum of the PC and the register, respectively.&lt;/p&gt;
&lt;p&gt;Note: if the cycle time permits, and the hardware for an adder is fast
enough, we could consider the use of a dedicated adder inside the &lt;strong&gt;Decode&lt;/strong&gt;
stage of the pipeline. Remember however that our register file is updated during
the first half of our clock cycle, which means the register values are
guaranteed to be correct only during the second half of the cycle. 
For now, let's consider that we don't have the time to do it, and that the jump
target is indeed only known at the end of the &lt;strong&gt;Execute&lt;/strong&gt; stage.&lt;/p&gt;
&lt;p&gt;This means that in both jumps and taken branches, the two instructions that
were feeded into the pipeline now need to be killed, they do not correspond to
the correct codepath anymore.&lt;/p&gt;
&lt;h1&gt;Next time&lt;/h1&gt;
&lt;p&gt;I don't know yet what topic will be covered next time.
Actual components selection, building blocks, details of some pipeline stages, ...&lt;/p&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>Astorisc architecture overview: pipeline</title><link href="https://www.alrj.org/astorisc-architecture-overview-pipeline.html" rel="alternate"></link><published>2021-10-10T00:00:00+02:00</published><updated>2021-10-10T16:40:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2021-10-10:/astorisc-architecture-overview-pipeline.html</id><summary type="html">&lt;p&gt;This article is mostly a high-level overview of the Astorisc architecture,
do not expect implementation tricks and gory details in here. &lt;/p&gt;
&lt;p&gt;As I said in the presentation, I'd like to make Astorisc a pipelined processor.
But what does this actually mean? I could send you to the 
&lt;a href="https://en.wikipedia.org/wiki/Instruction_pipelining"&gt;article on Wikipedia …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;This article is mostly a high-level overview of the Astorisc architecture,
do not expect implementation tricks and gory details in here. &lt;/p&gt;
&lt;p&gt;As I said in the presentation, I'd like to make Astorisc a pipelined processor.
But what does this actually mean? I could send you to the 
&lt;a href="https://en.wikipedia.org/wiki/Instruction_pipelining"&gt;article on Wikipedia&lt;/a&gt;, but 
I may as well try and explain it myself.&lt;/p&gt;
&lt;p&gt;In a nutshell, pipelining will make the processor execute the instructions in a 
series of steps (or stages), each step running in a different unit, allowing 
processing multiple instructions in parallel. &lt;/p&gt;
&lt;p&gt;The pipeline in Astorisc will be the well documented canonical 5-stages 
pipeline, that is perfectly suitable for a RISC architecture:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Instruction Fetch&lt;/li&gt;
&lt;li&gt;Instruction Decode and register load&lt;/li&gt;
&lt;li&gt;Execute&lt;/li&gt;
&lt;li&gt;Memory access&lt;/li&gt;
&lt;li&gt;Register writeback&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;How the pipeline works&lt;/h1&gt;
&lt;p&gt;At each clock cycle, the instruction will advance to the next unit of the 
pipeline, keeping all the stages busy. At least, that's the theory. In practice,
there are situations where an instruction must be delayed until the resource it
needs becomes available.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Pipeline Principle" src="https://www.alrj.org/images/riscv/Pipeline_principle_resized.png"&gt;&lt;/p&gt;
&lt;p&gt;When the clock ticks, each intermediate register will store the result of the 
unit before it, and make it available to the next unit in the line, keeping 
its value stable until the next cycle.&lt;/p&gt;
&lt;h1&gt;The pipelined RISC-V datapath&lt;/h1&gt;
&lt;p&gt;Here is an extremely simplified datapath diagram for our pipelined RISC-V
processor. 
&lt;a href="https://www.alrj.org/images/riscv/Pipeline_summary.png"&gt;&lt;img alt="RISC-V datapath summay" src="https://www.alrj.org/images/riscv/Pipeline_summary_resized.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Pros and cons ?&lt;/h1&gt;
&lt;p&gt;The main advantage of a pipelined architecture is that each step, taken 
individually, is comparatively simpler and needs a much shorter amount of time to 
execute, meaning the processor can run at a higher clock speed.&lt;/p&gt;
&lt;p&gt;The downside is that the processor gets more complex, because of all the 
intermediate registers and the control logic.&lt;/p&gt;
&lt;h1&gt;Hazards&lt;/h1&gt;
&lt;p&gt;In a pipelined CPU, an instruction starts being executed before the previous one
is finished. That can cause problems, for instance when the second instruction
needs the result of the first one before it is actually available. Those 
problematic situations are called &lt;em&gt;hazards&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I will not go into the details of the various types of hazards, nor when 
or why they happen. Instead, I will shortly describe the solutions that I can
implement to resolve the issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stall&lt;/strong&gt;: This is probably the easier solution. When an instruction needs a 
   previous instruction's result that is not yet available, make it wait until
   it is. In some situations, there is just no way around it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bypass&lt;/strong&gt;: A more complex, but more efficient solution, is to provide
   an alternative path for the data to be routed immediately when it is 
   available. I intend to implement this &lt;em&gt;operand forwarding&lt;/em&gt; at least at
   the &lt;em&gt;Execute&lt;/em&gt; stage. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that I do not intend to implement out-of-order execution ;-)&lt;/p&gt;
&lt;p&gt;There is also the question about accessing the memory that can happen at both
&lt;em&gt;Fetch&lt;/em&gt; and &lt;em&gt;Memory&lt;/em&gt; stages. Probably the easiest way to solve this issue will
be to deny the fetch when an instruction accesses the memory. This is a bit 
like a stall, although it happens at the very first stage of the pipeline, so
nothing actually stalls.&lt;/p&gt;
&lt;p&gt;For the jumps and branches that are taken, I will need a way to discard the 
instructions that have already been loaded into the pipeline but must not be
executed.&lt;/p&gt;
&lt;h1&gt;But how to do all that?&lt;/h1&gt;
&lt;p&gt;In future articles, I'd like to go into the details of some of the components
that I've shown as simple boxes in the diagram above. The ALU symbol may look
quite simple, but the reality far from that!&lt;/p&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>A RISC-V processor from logic circuits</title><link href="https://www.alrj.org/a-risc-v-processor-from-logic-circuits.html" rel="alternate"></link><published>2021-09-22T21:43:00+02:00</published><updated>2021-09-23T16:40:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2021-09-22:/a-risc-v-processor-from-logic-circuits.html</id><summary type="html">&lt;p&gt;&lt;img alt="RISC-V logo" src="https://www.alrj.org/images/riscv/riscv_252x40.png#left"&gt;
Now that &lt;a href="https://www.alrj.org/bb-88-is-the-new-bidule88.html"&gt;BB-88 is more or less complete&lt;/a&gt;, let me tell you about another project
that has been on my mind for a few years now: a homebrew computer featuring a RISC-V processor made of
74 series logic.&lt;/p&gt;
&lt;p&gt;There are already a few projects to make a RISC-V processor from …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="RISC-V logo" src="https://www.alrj.org/images/riscv/riscv_252x40.png#left"&gt;
Now that &lt;a href="https://www.alrj.org/bb-88-is-the-new-bidule88.html"&gt;BB-88 is more or less complete&lt;/a&gt;, let me tell you about another project
that has been on my mind for a few years now: a homebrew computer featuring a RISC-V processor made of
74 series logic.&lt;/p&gt;
&lt;p&gt;There are already a few projects to make a RISC-V processor from scratch in various stages of 
completion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first one I've heard of was &lt;a href="https://youtube.com/playlist?list=PLEeZWGE3PwbansoxKjjMKHQqS_2cm8i60"&gt;Robert Baruch's LMARV-1 (Learn Me A Risc V)&lt;/a&gt;, a series of youtube
   videos. The first iteration of the project apparently hit a hard stop at some point, but got &lt;a href="https://youtube.com/playlist?list=PLEeZWGE3PwbZTypHq00G-yEX8TEI95lw4"&gt;rebooted
   in late 2020&lt;/a&gt;.
   These videos cover many interesting topics like various ways to implement the register file, the ALU, etc.&lt;/li&gt;
&lt;li&gt;The second one was a project on Hackaday.io by Phil Wright: &lt;a href="https://hackaday.io/project/18491-worlds-first-32bit-homebrew-cpu"&gt;World's first 32bit Homebrew CPU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The latest one is the &lt;a href="https://hackaday.io/project/178826-pineapple-one"&gt;Pineapple ONE&lt;/a&gt;, by Filip Szkandera. 
   This is probably the most advanced of these projects, and perhaps the only one that can actually be used 
   to run some real code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, not a RISC-V, but close enough, there is the &lt;a href="https://fritzler-avr.de/spaceage2/index.htm"&gt;Spaceage 2&lt;/a&gt;,
a university project that implements the MIPS ISA.&lt;/p&gt;
&lt;p&gt;All of these projects aimed for different goals, and each one follows its own path, which 
make them all very interesting to study.&lt;/p&gt;
&lt;p&gt;I don't know if mine will ever see the light of day, not even speaking of being complete, but I'll try&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; 
to keep some notes about my research and progress here.&lt;/p&gt;
&lt;h1&gt;Goals&lt;/h1&gt;
&lt;p&gt;My main goal for this project is simple to state: &lt;strong&gt;make it as fast as I can!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At the moment, I envision a pipelined CPU running maybe at 30MHz with register forwarding 
between some stages of the pipeline to avoid stalls. The main path in the pipelined would
&lt;em&gt;not&lt;/em&gt; be microcoded, unlike most projects I've seen. That said, if I ever implement
hardware multiplication and division, they will take multiple cycles to execute and would
probably be microcoded.&lt;/p&gt;
&lt;p&gt;My second goal is to make it a Von Neuman architecture, where there is a single memory space
for both code (instructions) and data. This goes against the first goal because instructions
that need to access the memory will prevent the CPU from fetching the next instruction during 
the same clock cycle, but I reckon this is the price to pay for the flexibility of a "real"
computer.&lt;/p&gt;
&lt;p&gt;Finally, I'm not only thinking about the processor here, but also the peripherals and the way
they communicate together to make an actual computer. That means there will be some kind of bus,
probably like the ISA bus but wider, wait-states to cope with slower devices, etc.&lt;/p&gt;
&lt;h1&gt;How do we call it ?&lt;/h1&gt;
&lt;p&gt;Unless I find a better name in the future, I'm still undecided between &lt;em&gt;Astorisc&lt;/em&gt; and &lt;em&gt;Castorisc&lt;/em&gt;.
The first one is for &lt;em&gt;Alrj's take on RISC-V&lt;/em&gt; and is similar to the word &lt;em&gt;Asterisk&lt;/em&gt;.
The second one doesn't stand for anything, it only evolved from the first idea and could use a
castor as a logo.&lt;/p&gt;
&lt;p&gt;Sometimes, finding project names is even harder than finding hostnames.&lt;/p&gt;
&lt;h1&gt;Where does it happen ?&lt;/h1&gt;
&lt;p&gt;Right here! There will be a &lt;a href="https://www.alrj.org/pages/Astorisc.html"&gt;project page&lt;/a&gt; where I will hopelessly
try to organize my thoughts.&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;If you used to follow my defunct blog or even this very website in the past, you will
assume there is a fairly high probablility that I will stop publishing anything about the project 
very soon. and you may very well be right about it. We'll see...&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Electronics"></category><category term="RiscV"></category></entry><entry><title>BB-88 is the new Bidule88</title><link href="https://www.alrj.org/bb-88-is-the-new-bidule88.html" rel="alternate"></link><published>2021-09-22T18:17:00+02:00</published><updated>2024-01-07T15:40:00+01:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2021-09-22:/bb-88-is-the-new-bidule88.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This is a log entry about BB-88. See the &lt;a href="https://www.alrj.org/pages/bb-88.html"&gt;project page&lt;/a&gt; to know more about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Soon after my last post about Bidule88 in 2014, I realized that four breadboards would
definitely not be enough to complete the project. I quickly tore it down to restart from 
scratch, this time …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This is a log entry about BB-88. See the &lt;a href="https://www.alrj.org/pages/bb-88.html"&gt;project page&lt;/a&gt; to know more about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Soon after my last post about Bidule88 in 2014, I realized that four breadboards would
definitely not be enough to complete the project. I quickly tore it down to restart from 
scratch, this time on a much larger scale: two columns of seven breadboards each. &lt;/p&gt;
&lt;p&gt;This time it took me a bit longer, but again, the project reached a point where a
larger set of breadboards was needed. Two columns of seven breadboards next to each 
other were dedicated for the core of the computer and most of its extensions, 
while a third column separated from the first two by a few vertical bus lines was
reserved for the video display adapter alone. All together, they thus make for an
impressive total of 21 breadboards.&lt;/p&gt;
&lt;p&gt;That was also the opportunity to rename the project. Goodbye Bidule88, welcome BB-88, 
the BreadBoard 8088!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.alrj.org/images/bidule88/bb-88-overview.jpg"&gt;&lt;img alt="Overview of BB-88" src="https://www.alrj.org/images/bidule88/bb-88-overview_th.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="Electronics"></category><category term="Bidule88"></category><category term="BB-88"></category></entry><entry><title>Restoration of a Criko THD-16 drill press</title><link href="https://www.alrj.org/restoration-of-a-criko-thd-16-drill-press.html" rel="alternate"></link><published>2015-10-01T21:00:00+02:00</published><updated>2015-10-01T21:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2015-10-01:/restoration-of-a-criko-thd-16-drill-press.html</id><summary type="html">&lt;p&gt;I recently bought a Criko THD-16 drill press from 1992.
It is in good general shape, except for the quill pulley bearings that get
fairly noisy when I tension the belt. I thus decided to take everyhting apart,
clean it thoroughly, remove the rust, and replace all the bearings.
You …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently bought a Criko THD-16 drill press from 1992.
It is in good general shape, except for the quill pulley bearings that get
fairly noisy when I tension the belt. I thus decided to take everyhting apart,
clean it thoroughly, remove the rust, and replace all the bearings.
You know, just in case.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Criko THD-16" src="https://www.alrj.org/images/drill-press.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Some more details (in French, sorry) in &lt;a href="http://www.copaindescopeaux.fr/forum/les-outils-electriques/11662.html"&gt;my post on the forum of Copain des 
Copeaux&lt;/a&gt;.&lt;br/&gt;
Also, &lt;a href="https://oc.alrj.org/index.php/apps/galleryplus/s/oamKPYHYiJk3mdQ"&gt;more pictures available here&lt;/a&gt;.&lt;/p&gt;</content><category term="Woodworking"></category></entry><entry><title>An End-Grain Cutting Board</title><link href="https://www.alrj.org/an-end-grain-cutting-board.html" rel="alternate"></link><published>2015-10-01T20:00:00+02:00</published><updated>2015-10-01T20:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2015-10-01:/an-end-grain-cutting-board.html</id><summary type="html">&lt;p&gt;For my father's 60th birthday, I made an end-grain cutting board.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Cutting Board" src="https://www.alrj.org/images/cutting-board.jpg"&gt;&lt;/p&gt;
&lt;p&gt;It's made out of walnut and maple and took me some serious hours of work!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://oc.alrj.org/index.php/s/hSUP79AAIRsQOq0?"&gt;Pictures are here&lt;/a&gt; 
if you want to see the making of, but don't expect a real build log. Some steps are
unfortunately missing.&lt;/p&gt;
&lt;p&gt;And …&lt;/p&gt;</summary><content type="html">&lt;p&gt;For my father's 60th birthday, I made an end-grain cutting board.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Cutting Board" src="https://www.alrj.org/images/cutting-board.jpg"&gt;&lt;/p&gt;
&lt;p&gt;It's made out of walnut and maple and took me some serious hours of work!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://oc.alrj.org/index.php/s/hSUP79AAIRsQOq0?"&gt;Pictures are here&lt;/a&gt; 
if you want to see the making of, but don't expect a real build log. Some steps are
unfortunately missing.&lt;/p&gt;
&lt;p&gt;And in case you were wondering, yes, he liked it very much!&lt;/p&gt;</content><category term="Woodworking"></category></entry><entry><title>Parcels arrived</title><link href="https://www.alrj.org/parcels-arrived.html" rel="alternate"></link><published>2014-09-22T18:00:00+02:00</published><updated>2014-09-22T18:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2014-09-22:/parcels-arrived.html</id><summary type="html">&lt;p&gt;Today, two parcels arrived.&lt;/p&gt;
&lt;p&gt;The first one is a hard cover copy of &lt;a href="http://www.amazon.com/8088-Project-Book-Robert-Grossblatt/dp/0830631712"&gt;The 8088 Project 
Book&lt;/a&gt;
by Robert Grossblat. It seems that it is a reference on the subject, I'm eager
to start reading it. Stay tuned for more Bidule88 posts in the future!&lt;/p&gt;
&lt;p&gt;The second one is much …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today, two parcels arrived.&lt;/p&gt;
&lt;p&gt;The first one is a hard cover copy of &lt;a href="http://www.amazon.com/8088-Project-Book-Robert-Grossblatt/dp/0830631712"&gt;The 8088 Project 
Book&lt;/a&gt;
by Robert Grossblat. It seems that it is a reference on the subject, I'm eager
to start reading it. Stay tuned for more Bidule88 posts in the future!&lt;/p&gt;
&lt;p&gt;The second one is much lighter, it is a t-shirt from &lt;a href="http://www.qwertee.com"&gt;Qwertee&lt;/a&gt;
that is absolutely cute and geeky. I'll update this post with a picture as soon 
as I can.&lt;/p&gt;</content><category term="Misc"></category><category term="Blog"></category></entry><entry><title>Bidule88 Part 02: It runs!</title><link href="https://www.alrj.org/bidule88-part-02-it-runs.html" rel="alternate"></link><published>2014-09-18T21:40:00+02:00</published><updated>2014-09-18T21:40:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2014-09-18:/bidule88-part-02-it-runs.html</id><summary type="html">&lt;p&gt;First achievement with Bidule88: it is actually running some code that I've 
written and uploaded into its EEPROM!
Here is the result:&lt;/p&gt;
&lt;iframe width="560" height="315" src="//www.youtube.com/embed/4FY4HTCBTCo" 
frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;The parts are connected as described on &lt;a href="http://www.homebrew8088.com/"&gt;Homebrew8088&lt;/a&gt;
except that the EEPROM I used is bigger. Not that it is needed, though, the
code is only a few …&lt;/p&gt;</summary><content type="html">&lt;p&gt;First achievement with Bidule88: it is actually running some code that I've 
written and uploaded into its EEPROM!
Here is the result:&lt;/p&gt;
&lt;iframe width="560" height="315" src="//www.youtube.com/embed/4FY4HTCBTCo" 
frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;The parts are connected as described on &lt;a href="http://www.homebrew8088.com/"&gt;Homebrew8088&lt;/a&gt;
except that the EEPROM I used is bigger. Not that it is needed, though, the
code is only a few bytes... &lt;/p&gt;
&lt;p&gt;The 74hc373 on the left will latch the value written to &lt;em&gt;any&lt;/em&gt; I/O port, it
simply ignores the address.&lt;/p&gt;
&lt;p&gt;What surprised me was how few loops I had to do for a 1 second delay between
the counts. Clearly, that CPU isn't fast, and some instructions need a lot of 
cycles.&lt;/p&gt;
&lt;p&gt;&lt;a href="bidule88-03.md"&gt;Next time&lt;/a&gt; we will start playing with a small LCD. Having some
correct feedback will definitely ease debugging.&lt;/p&gt;</content><category term="Electronics"></category><category term="Bidule88"></category></entry><entry><title>Bidule88 Part 01: Introduction</title><link href="https://www.alrj.org/bidule88-part-01-introduction.html" rel="alternate"></link><published>2014-09-08T21:00:00+02:00</published><updated>2014-09-10T14:00:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2014-09-08:/bidule88-part-01-introduction.html</id><summary type="html">&lt;p&gt;Several months ago, while casually browsing the web from link to link, I ended up on the 
&lt;a href="http://quinndunki.com/blondihacks/?p=680"&gt;Veronica&lt;/a&gt; project page. I've played with
computers for some years now, but never thought I'd ever be able to actually 
&lt;em&gt;make&lt;/em&gt; one. That is, until I read Quinn's posts. Granted, she uses a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Several months ago, while casually browsing the web from link to link, I ended up on the 
&lt;a href="http://quinndunki.com/blondihacks/?p=680"&gt;Veronica&lt;/a&gt; project page. I've played with
computers for some years now, but never thought I'd ever be able to actually 
&lt;em&gt;make&lt;/em&gt; one. That is, until I read Quinn's posts. Granted, she uses a 6502 
instead of a 8088, but that can't be &lt;em&gt;that&lt;/em&gt; different, can it ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="NEC 8088 CPU" src="https://www.alrj.org/images/bidule88/ep01/CPU.jpg"&gt;&lt;/p&gt;
&lt;p&gt;So I started to think about it, and after having read a lot of documentation
and countless web pages, I was finaly confident that I could do... Well, that
I could do something that could be called a computer without stretching the 
definition too much. With that in mind, I went to Ebay and ordered components
from a dozen different sellers. The majority of them has now arrived but I'm 
still waiting for a few parcels to show up.&lt;/p&gt;
&lt;p&gt;These days, whenever I've got some free time, I go back to my breadboard, or 
cut and strip some left over twisted-pair network cable, and try to add another
element to the project. It is fairly clear in my mind where I'm heading to,
and the steps I need to make to get there are quite well defined. We'll see
how it turns out! In any case, that will be a nice opportunity to learn new 
things (new for me at least, as some of them were already pretty much obsolete 
10 years ago or more). &lt;/p&gt;
&lt;p&gt;As I forsee it, most of my design will be compatible with the original IBM PC, 
except for the graphics card, if I ever get that far. I don't rule out the
possibility that an off-the-shelf VGA adapter could be plugged in an ISA slot,
though.&lt;/p&gt;
&lt;p&gt;The &lt;a href="bidule88-02.md"&gt;next part&lt;/a&gt; will be about the components I (intend to) use
in this project.&lt;/p&gt;</content><category term="Electronics"></category><category term="Bidule88"></category></entry><entry><title>Carbonnades de dindonneau à la Kriek</title><link href="https://www.alrj.org/carbonnades-de-dindonneau-a-la-kriek.html" rel="alternate"></link><published>2010-02-08T22:07:00+01:00</published><updated>2021-09-10T15:20:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2010-02-08:/carbonnades-de-dindonneau-a-la-kriek.html</id><summary type="html">&lt;p&gt;&lt;em&gt;(Ceci est une republication d'un billet posté précédemment sur mon défunt blog)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Voilà la recette complète du plat que j'ai servi aux amis français (et au 
belge) pour le souper de la veille du &lt;a href="https://fosdem.org"&gt;FOSDEM&lt;/a&gt;. Oui, parce 
que chez nous, le repas du soir s'appelle le souper.&lt;/p&gt;
&lt;h2&gt;Ingrédients&lt;/h2&gt;
&lt;p&gt;Note: les …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;(Ceci est une republication d'un billet posté précédemment sur mon défunt blog)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Voilà la recette complète du plat que j'ai servi aux amis français (et au 
belge) pour le souper de la veille du &lt;a href="https://fosdem.org"&gt;FOSDEM&lt;/a&gt;. Oui, parce 
que chez nous, le repas du soir s'appelle le souper.&lt;/p&gt;
&lt;h2&gt;Ingrédients&lt;/h2&gt;
&lt;p&gt;Note: les ingrédients sont donnés pour trois personnes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;600g de carbonnades de dindonneau&lt;/li&gt;
&lt;li&gt;1 Kriek (Lindemans, 37cl)&lt;/li&gt;
&lt;li&gt;4 ou 5 échalottes, peuvent être remplacées par 2 oignons&lt;/li&gt;
&lt;li&gt;200g de chataignes cuites au feu&lt;/li&gt;
&lt;li&gt;1 grosse cuillère à soupe de gelée de pommes&lt;/li&gt;
&lt;li&gt;1 cuillère à soupe de farine&lt;/li&gt;
&lt;li&gt;3 pommes (Golden, qui tiennent à la cuisson)&lt;/li&gt;
&lt;li&gt;beurre&lt;/li&gt;
&lt;li&gt;thym, sel, poivre&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Préparation du plat&lt;/h2&gt;
&lt;p&gt;Couper les échalottes en morceau et les faire revenir dans la casserole avec la viande, 
sur un beau filet d'huile d'olive. Lorsque l'extérieur des morceaux de viande est cuit, 
ajouter la farine et faire encore revenir quelques minutes en mélangeant bien.&lt;/p&gt;
&lt;p&gt;Verser la Kriek et un peu d'eau (au pif, entre 5 et 15cl, je ne sais pas trop :p ). 
Ajouter le thym, saler et poivrer. Porter à ébullition, puis laisser mijoter 45 minutes.&lt;/p&gt;
&lt;p&gt;En fin de cuisson, ajouter la gelée de pomme et les chataignes. Si les chataignes sont 
emballées dans du plastique sous vide, il vaut mieux les chauffer au bain-marie préalablement. 
Dans le cas contraire, laisser mijoter pour qu'elles atteignent la bonne température.&lt;/p&gt;
&lt;p&gt;Peler et couper les pommes en douze quartiers. Faire dorer les quartiers à la poêle dans du beurre.&lt;/p&gt;
&lt;p&gt;Servir avec des pommes-de-terre fermes (charlottes, nicolas, ...) et bien sûr, une Kriek !&lt;/p&gt;
&lt;p&gt;Bon appétit.&lt;/p&gt;</content><category term="Food"></category></entry><entry><title>Une petite recette de pâtes pas du tout diététique</title><link href="https://www.alrj.org/une-petite-recette-de-pates-pas-du-tout-dietetique.html" rel="alternate"></link><published>2008-08-21T21:13:00+02:00</published><updated>2021-09-10T15:30:00+02:00</updated><author><name>Amand Tihon</name></author><id>tag:www.alrj.org,2008-08-21:/une-petite-recette-de-pates-pas-du-tout-dietetique.html</id><summary type="html">&lt;p&gt;&lt;em&gt;(Ceci est une republication d'un billet posté précédemment sur mon défunt blog)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Rien que le titre, ça donne envie, vous ne trouvez pas ?&lt;/p&gt;
&lt;p&gt;Pour la petite histoire, c'est une recette que j'ai goûtée au café/resto 
&lt;em&gt;le Onlywood&lt;/em&gt;, à Louvain-la-Neuve. J'ai tellement aimé que je me suis senti obligé 
d'en …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;(Ceci est une republication d'un billet posté précédemment sur mon défunt blog)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Rien que le titre, ça donne envie, vous ne trouvez pas ?&lt;/p&gt;
&lt;p&gt;Pour la petite histoire, c'est une recette que j'ai goûtée au café/resto 
&lt;em&gt;le Onlywood&lt;/em&gt;, à Louvain-la-Neuve. J'ai tellement aimé que je me suis senti obligé 
d'en manger aussi à la maison !&lt;/p&gt;
&lt;p&gt;En avant pour les ingrédients. Les quantités sont absolument approximative, 
et c'est donné pour une personne :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;100g de lardons allumette ;&lt;/li&gt;
&lt;li&gt;250ml de crème fraîche (ouais, par personne) ;&lt;/li&gt;
&lt;li&gt;une belle grosse cuillère à soupe de miel (liquide) ;&lt;/li&gt;
&lt;li&gt;vinaigre balsamique ;&lt;/li&gt;
&lt;li&gt;mozzarella râpée ;&lt;/li&gt;
&lt;li&gt;et bien sûr, des tagliatelles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans une poêle large, faire revenir les lardons à feu vif sans oublier de les tourner, 
jusqu'à ce qu'ils prennent une belle couleur foncée qui indique qu'ils sont prêts.&lt;/p&gt;
&lt;p&gt;Retirer tout liquide qu'ils auraient pu dégorger (ah! saleté de viande aux hormones 
pleine de flotte) et déglacer avec une grosse cuillère à café de vinaigre balsamique. 
Attention, surtout ne pas mettre trop de vinaigre, sinon il va sauvagement faire tourner 
la crème, et je vous assure que c'est mauvais (expérience n° 1... peu concluante). 
D'un autre coté, s'il y en a trop peu, ça ne colorera pas assez et ce sera moins joli.&lt;/p&gt;
&lt;p&gt;Ajouter la crème et le miel dans la poêle, bien mélanger le tout et faire réduire lentement, 
mais longtemps. Très longtemps. Vraiment longtemps. Jusqu'à obtention d'une sorte de pâte 
gluante, collante, plutôt bien colorée.&lt;/p&gt;
&lt;p&gt;Recouvrir de ce slime aux grumaux les tagliatelles que vous n'aurez bien sûr pas oublié de 
faire cuire pendant que ça réduisait sagement et couvrir avec la mozzarella râpée.&lt;/p&gt;
&lt;p&gt;Bon appétit, et bon régime !&lt;/p&gt;
&lt;p&gt;Ah, et si vous avez une idée pour une verdure capable d'accompagner un tel monstre, je suis 
tout ouïe. Généralement, après un truc pareil, je me sens juste la force d'avaler quelque 
chose comme une demi feuille de salade.&lt;/p&gt;</content><category term="Food"></category></entry></feed>