VT52 on the TinyFPGA BX


Just wanted to share this project I’ve been working on for the last month. It’s a VT52 terminal emulator on a TinyFPGA BX, implemented in pure Verilog with no soft processor. I have it connected to an old monitor and keyboard and running as a serial terminal on my linux box.

Code, screenshots & some more info on github


Nice - cool project!


And works on my Debian! :grin:


Nice to see someone try it out! Let me know if you find any issues.

Btw, how did you set it up in Debian? I had to create a system.d service because just running agetty myself from the console wouldn’t set the controlling terminal, so I had no job control and emacs wouldn’t run (I could run vim and do basic terminal stuff though).


Hi Andres, thanks for this project!

I have yet to test the complete terminal, I am looking for an old PS/2 keyboard.
(It would be interesting to try USB keyboards in the future … :wink:)

But yes, I also used systemd for getty.
In Debian it is easy to use, you just have to activate it and start the service.

If anyone wants to try, my completed process was the following:

  1. Clone repository from github:

git clone https://github.com/AndresNavarro82/vt52-fpga.git

  1. Modify the PCF file to use other pins already connected to my VGA connector.
  2. Synthesize and upload the bitstream on the TinyFPGA-BX.
  3. If you need, skip bootloader sending byte 0x00.

echo -n -e ‘\x0’ > /dev/ttyACM0

  1. Test VGA console display with a simple:

echo hello > /dev/ttyACM0

  1. Active service getty in ttyACM0.

systemctl enable serial-getty@ttyACM0.service

  1. And start service.

systemctl start serial-getty@ttyACM0.service

And that’s it …:grin:
When I have the PS/2 keyboard, I will try to login and test the terminal completely, but for the moment it looks very good, Andres … thanks again!.


I’ve managed to flash vt52 alongside picosoc to my BX. I instantiated both in a “container” module in a separate file. Is there a way to connect the vt52 uart to the picosoc uart? I tried assigning usb_p to ser_rx and etc, but this did not work. This is my first tinyfpga project, so I’m a little lost haha!


In vt52 project you have a usb-uart bridge. This module get two external signals (pin_usb_p and pin_usb_n) and converts in a input byte (from keyboard) or output byte (to monitor VGA), in scheme:

In PicoSoC you have a simple UART (https://github.com/cliffordwolf/picorv32/blob/master/picosoc/simpleuart.v) inside of it. This module get two external signals (ser_tx and ser_rx) and converts into 32bits word and push over its System Bus,

But this signals are not the same protocol, you can not assign pin_usb_p to ser_rx (it’s a crazy!!). If you want to used UART of PicoSoc you need “deserialize” this byte with another module:

This module must get byte output and deserialize to ser_rx and get byte input and deserialize over ser_tx.

Or directly not use UART inside PicoSoC and push bytes (input and output) from bridge usb-uart directly in its System Bus, using custom blocks.



This is a great answer. I just wanted to add a couple of things:

  • For implementing a uart (that would replace the usb_uart module in vt52.v) something like this uart should work (I just found it, didn’t test it yet). I may incorporate something like that in the repo because it is also useful for boards that use an external serial<->usb bridge. When you do this you have to make sure the baud rate of both uarts coincide. This is the easiest I think.
  • Additionally if you still want the serial communication from PicoSoc to the PC, then you can also consider adding another serial port to the PicoSoc, one for the terminal, one for the pc. You could even use the usb uart for the PicoSoc<->PC port.
  • If you do away with the usb_uart you can have just one clock running @25.175Mhz. Again, I will probably add this over the weekend for boards such as the IceStick (if it fits after removing the usb)
  • The disadvantage of using two uarts (one in vt52 one in the soc) is that you are unnecessarily converting to serial and back using logic resources and limiting speed, the advantage is that they are more decoupled and you can run then with totally different clocks
  • The alternative as juanmard suggested is implementing a custom interface as a Memory mapped user peripherals. This is pretty simple, but for that you would need to run everything @25.175Mhz (or do clock domain crossing which is not for beginners)

@yeahboi feel free to post a link to the repo and I could take a look at it if you want.


Yeah I did something similar, but wrote the serial service myself. It was probably there in Ubuntu too and I just needed to enable it… probably overcomplicated things here.
Didn’t know about sending the zero to skip the bootloader, I was just doing “tinyprog -b”. I wanted to research this, great to know it’s that simple.
As for the usb keyboard, while I don’t have it in my immediate roadmap is something I would like to explore, after trying the serial<->usb. I still need some practice with Verilog to feel confident, especially with testing.


It isn’t pretty, but here you go! Thanks for the help, this community is awesome.


I can see that you used the serialize/deserialize aproach with AXI protocol… :wink:
I’ll try it if I found a PS/2 to test. Did you test it in an TinyFPGA-BX? :blush:


Yes, and it does not entirely work yet! I believe I may have connected the UART between the vt52 and the picosoc incorrectly, as I didn’t assign them to new wires made inside the main verilog file (which, according to this stack exchange (https://stackoverflow.com/questions/1704989/how-to-wire-two-modules-in-verilog), is apparantly standard practice). Let me know if you have more luck with it, I am dedicated to this cause lol.


fancy fonts! thanks for sharing this project. very cool


Well I finally had some time today to look this over. It now works, picosoc (with half the usual RAM), with the serial port connected to the vt52 (@9600bps, vga & ps/2 ports). It has a little loop that shows 4 different messages on the top of the screen, changing every 5 secs or so. It uses 85% ofl block rams & logic on the tinyfpga. I sent you a pull request on github. This is just a quick hack, it could be a lot cleaner, but I wanted to modify your code as little as possible. I didn’t try the keyboard, but it should work ok.

I feel like maybe you got a little over your head tackling this? There were a lot of little things I found. Take your time to go over the commit, and feel free to ask questions, but I’ll point a couple of things from the top of my head.

  • I took out all the usb module, there’s no need for it now (but you could try to add a second serial port to the SOC, but you would be cutting it pretty close with block rams & logic. Now that the vt52 doesn’t uses usb you could eliminate the 48Mhz clock now and run all the vt52 @25Mhz or so, but I will do that more cleanly in the vt52-fpga repo over the weekend.
  • I moved the uart instantiation to the vt52.v file, replacing the usb_uart. I changed to ports of this module, taking out usb & adding rx & tx. I think this is cleaner but your idea of connecting the ready, data & valid signals was ok.
  • I eliminated your riscv-vt52.v file. You were instantiating the soc without any of the flash and memory interfaces. Instead of that I just instantiated the vt52 module in hardware.v and made that the top module instead. I added ports for video & ps/2 there.
  • You weren’t telling yosys your top module, you need to use the -top option unless your top module is called “top”. In your code, only the vt52 was being compiled (because the module in vt52 was named top, I changed it now)
  • I restored the original hardware.pcf, with all tinyfpga bx pin definitions. In hardware.v I followed the convention in that file and used those names when instantiating the vt52 module.

Please try it out and tell me if it works for you too


Woah, that is awesome! I wasn’t expecting that much help, thank you very much, sir! Yes indeed, this is my first verilog project and I am absolutely in over my head, I am very much throwing myself in the deepend as a web developer/audio electronics guy who is interested in low level digital logic. I am comfortable with boolean logic, and verilog makes sense to me, but workflows and syntax are 100% new to me. My main educational resources have been this community and the fpga4fun website. Once again, I appreciate you taking the time to carefully show where some changes need to be made. I will give you a report on if/how it works on my hardware after my shift at work is done. Cheers!