Added PLL for ARTY

This commit is contained in:
Bruno Levy
2021-07-20 23:10:48 +02:00
parent e69b77bce0
commit ef5346d77f
9 changed files with 369 additions and 36 deletions

View File

@@ -15,7 +15,7 @@ set_property IOSTANDARD LVCMOS33 [get_ports {D4}]
# Clock constraints
create_clock -period 10.0 [get_ports {pclk}]
## Pmod Header JA
# Pmod Header JA
set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { oled_RST }]; #IO_0_15 Sch=ja[1]
set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { ledmtx_CLK }]; #IO_L4P_T0_15 Sch=ja[2]
set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { ledmtx_CS }]; #IO_L4N_T0_15 Sch=ja[3]
@@ -24,3 +24,10 @@ set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { oled_D
set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { oled_CS }]; #IO_L10P_T1_AD11P_15 Sch=ja[8]
set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { oled_CLK }]; #IO_L10N_T1_AD11N_15 Sch=ja[9]
set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { oled_DIN }]; #IO_25_15 Sch=ja[10]
# UART
#set_property LOC D10 [get_ports TXD]
#set_property IOSTANDARD LVCMOS33 [get_ports TXD]
#set_property LOC A9 [get_ports RXD]
#set_property IOSTANDARD LVCMOS33 [get_ports RXD]

View File

@@ -1,3 +1,7 @@
PARTNAME=xc7a35tcsg324-1
DEVICE=xc7a50t_test
BITSTREAM_DEVICE=artix7
ARTY: ARTY.firmware_config ARTY.synth ARTY.prog
ARTY.synth:
@@ -5,12 +9,13 @@ ARTY.synth:
cd build/arty_35 && ln -sf ../../RTL .
cd build/arty_35 && ln -sf ../../BOARDS .
cd build/arty_35 && ln -sf ../../FIRMWARE .
cd build/arty_35 && symbiflow_synth -t $(PROJECTNAME) -v BOARDS/arty_defs.v $(VERILOGS) -d artix7 -p xc7a35tcsg324-1 -x BOARDS/arty.xdc 2>&1 > /dev/null
cd build/arty_35 && symbiflow_pack -e $(PROJECTNAME).eblif -d xc7a50t_test 2>&1 > /dev/null
cd build/arty_35 && symbiflow_place -e $(PROJECTNAME).eblif -d xc7a50t_test -n $(PROJECTNAME).net -P xc7a35tcsg324-1 2>&1 > /dev/null
cd build/arty_35 && symbiflow_route -e $(PROJECTNAME).eblif -d xc7a50t_test 2>&1 > /dev/null
cd build/arty_35 && symbiflow_write_fasm -e $(PROJECTNAME).eblif -d xc7a50t_test
cd build/arty_35 && symbiflow_write_bitstream symbiflow_write_bitstream -d artix7 -f $(PROJECTNAME).fasm -p xc7a35tcsg324-1 -b $(PROJECTNAME).bit
cd build/arty_35 && symbiflow_synth -t $(PROJECTNAME) -v BOARDS/arty_defs.v $(VERILOGS) -d $(BITSTREAM_DEVICE) -p $(PARTNAME) \
-x BOARDS/arty.xdc 2>&1 > /dev/null
cd build/arty_35 && symbiflow_pack -e $(PROJECTNAME).eblif -d $(DEVICE) 2>&1 > /dev/null
cd build/arty_35 && symbiflow_place -e $(PROJECTNAME).eblif -d $(DEVICE) -n $(PROJECTNAME).net -P $(PARTNAME) 2>&1 > /dev/null
cd build/arty_35 && symbiflow_route -e $(PROJECTNAME).eblif -d $(DEVICE) 2>&1 > /dev/null
cd build/arty_35 && symbiflow_write_fasm -e $(PROJECTNAME).eblif -d $(DEVICE)
cd build/arty_35 && symbiflow_write_bitstream symbiflow_write_bitstream -d $(BITSTREAM_DEVICE) -f $(PROJECTNAME).fasm -p $(PARTNAME) -b $(PROJECTNAME).bit
ARTY.prog:
cd build/arty_35 && openocd -f $(HOME)/opt/symbiflow/xc7/conda/envs/xc7/share/openocd/scripts/board/digilent_arty.cfg -c "transport select jtag; init; pld load 0 $(PROJECTNAME).bit; exit"

View File

@@ -7,6 +7,8 @@
/*******************************************************************/
int __errno;
typedef int BOOL;
static inline float max(float x, float y) { return x>y?x:y; }

View File

@@ -1,8 +1,5 @@
// Default femtosoc configuration file for IceStick
`define PASSTHROUGH_PLL
/************************* Devices **********************************************************************************/
`define NRV_IO_LEDS // Mapped IO, LEDs D1,D2,D3,D4 (D5 is used to display errors)
@@ -13,12 +10,12 @@
/************************* Processor configuration *******************************************************************/
`define NRV_FREQ 100 // Frequency in MHz, cannot be changed (100 MHz)
`define NRV_FREQ 50 // Frequency in MHz, needs to be a divider or a multiple of 100
`define NRV_FEMTORV32_QUARK // RV32I (for now, use this one, because my version of symbiflow cannot uses DSPs on ARTY)
//`define NRV_FEMTORV32_QUARK // RV32I (for now, use this one, because my version of symbiflow cannot uses DSPs on ARTY)
//`define NRV_FEMTORV32_TACHYON // RV32I
//`define NRV_FEMTORV32_ELECTRON // RV32IM
//`define NRV_FEMTORV32_GRACILIS // RV32IMC, IRQ
`define NRV_FEMTORV32_GRACILIS // RV32IMC, IRQ
`define NRV_RESET_ADDR 0 // The address the processor jumps to on reset

View File

@@ -36,6 +36,8 @@ endmodule
`include "pll_ecp5_evn.v"
`elsif FOMU
`include "pll_fomu.v"
`elsif ARTY
`include "pll_arty.v"
`endif
`endif

View File

@@ -0,0 +1,36 @@
module femtoPLL #(
parameter freq = 50
) (
input wire pclk,
output wire clk
);
wire clk_feedback;
wire clk_internal;
PLLE2_ADV #(
.BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW
.CLKFBOUT_MULT(8), // Multiply value for all CLKOUT (2-64)
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360-360)
.CLKIN1_PERIOD(10.0), // Input clock period in ns to ps resolution
.CLKOUT0_DIVIDE(8*100/freq),
.CLKOUT0_DUTY_CYCLE(0.5),
.CLKOUT0_PHASE(0.0),
.DIVCLK_DIVIDE(1), // Master division value , (1-56)
.REF_JITTER1(0.0), // Reference input jitter in UI (0.000-0.999)
.STARTUP_WAIT("FALSE") // Delayu DONE until PLL Locks, ("TRUE"/"FALSE")
) genclock(
.CLKOUT0(clk_internal),
.CLKFBOUT(clk_feedback), // 1-bit output, feedback clock
.CLKIN1(pclk),
.PWRDWN(1'b0),
.RST(1'b0),
.CLKFBIN(clk_feedback) // 1-bit input, feedback clock
);
BUFG bufg(
.I(clk_internal),
.O(clk)
);
endmodule

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 KiB

View File

@@ -1,39 +1,321 @@
Installing open-source tools for ARTIX-7 FPGAs
IceStick Tutorial
=================
![](Images/arty.jpg)
This tutorial will show you how to install FPGA development tools,
synthesize a RISC-V core, compile and install programs and run them
on a IceStick. This lets you experience FPGA design and RISC-V using
one of the cheapest FPGA devices (around $40).
Install open-source FPGA development toolchain
==============================================
Before starting, you will need to install the open-source FPGA
development toolchain (Yosys, NextPNR etc...), instructions to
do so are given [here](toolchain.md).
Step 1: Install symbiflow
=========================
To do that, a (custom) version of [symbiflow-magic](https://github.com/merledu/symbiflow-magic) is bundled with FemtoRV.
Symbiflow-magic is a makefile that downloads and configures a pre-compiled version of symbiflow for ARTIX-7.
The version bundled with FemtoRV fixes a couple of [issues](https://github.com/merledu/symbiflow-magic/issues/1).
(Optional) configure femtosoc and femtorv32
============================================
Edit `learn-fpga/FemtoRV/RTL/CONFIGS/arty_config.v`
This file lets you define what type of RISC-V processor you will
create.
The file `learn-fpga/FemtoRV/RTL/CONFIGS/arty_config.v`
also lets you select the device drivers present in the associated system-on-chip:
| Device | description | comment |
|------------------------|--------------------------------|-----------------------------------|
| `NRV_IO_LEDS` | 5 leds | keep it |
| `NRV_IO_UART` | serial connection through USB | keep it |
| `NRV_IO_SSD1351` | small OLED screen (128x128) | comment-out if you do not have it |
| `NRV_IO_SSD1331` | small OLED screen (96x64) | comment-out if you do not have it |
| `NRV_IO_MAX7219` | led matrix (10x10) | comment-out if you do not have it |
| `NRV_MAPPED_SPI_FLASH` | flash mapped in memory space | keep it |
We activate the LEDs (for visual debugging) and the UART (to talk with
the system through a terminal-over-USB connection). We use 64 Kbytes
of RAM. If you do not have an OLED screen or a led matrix screen, you
can comment out the corresponding lines in the file.
There are other options in the file. Normally you will not need to change them. If you want to know, they
are listed below:
| Option | Description |
|--------------------------|--------------------------------------------------------------------------------------|
| `NRV_FREQ` | Frequency of the processor in MHz (100 MHz on ARTY, cannot be changed) |
| `NRV_RAM` | Amount of RAM |
| `NRV_RESET_ADDR` | Address where to jump at startup and reset |
| `NRV_IO_HARDWARE_CONFIG` | Hardware register that can be queried by code to see configured devices |
| `NRV_RUN_FROM_SPI_FLASH` | Not supported for now on ARTY |
Compile firmware
================
```
$ cd learn-fpga/FemtoRV
$ make -f TOOLS/get_symbifow.mk
$ make ARTY.firmware_config
$ cd FIRMWARE/EXAMPLES
$ make hello.hex
```
The first time you run it, it will download RISC-V development tools (takes a while).
Synthethize and program
=======================
You can now synthesize the design and send it to
the device. Plug the device in a USB port, then:
```
$make ARTY
```
It will download and install several packages (takes a while...)
Step 2: post-install step
=========================
Add anaconda initialization to your shell startup file as follows:
Now, install a terminal emulator:
```
$ $HOME/opt/symbiflow/xc7/conda/bin/conda init $SHELL
$sudo apt-get install python3-serial
```
(or `sudo apt-get install screen`, both work).
To see the output, you need to connect to it (using the terminal emulator):
```
$make terminal
```
(if you installed `screen` instead of `python3-serial`, edit
`Makefile` before accordingly. You may need also to change there ttyUSBnnn).
If everything goes well, then your RISC-V core on the arty will
display a welcome message !
To exit, press `<ctrl> ]` (python-3-serial/miniterm), or `<ctrl> a` then '\\' (screen).
Examples with the serial terminal (UART)
========================================
The directories `FIRMWARE/EXAMPLES` and `FIRMWARE/ASM_EXAMPLES` contain programs in C and assembly
that you can run on the device. On the IceStick, only those that use 6K or less will work (list below).
To compile a program:
```
$cd FIRMWARE/EXAMPLES
$make hello.prog
```
Add the following line to your shell startup file (`.bashrc` if you use bash).
The `.prog` target generates the program and sends it to the device's SPI flash, using `iceprog`.
To see the result, use:
```
export PATH=/home/blevy/opt/symbiflow/xc7/install/bin/:$PATH
conda activate xc7
$cd ../..
$make terminal
```
Start a new terminal window. If everything went well, the prompt should start with `(xc7)`.
There are several C and assembly programs you can play with (list below). To learn more about RISC-V assembly,
see the [RISC-V specifications](https://riscv.org/technical/specifications/),
in particular the [instruction
set](file:///tmp/mozilla_blevy0/riscv-spec.pdf) and the [programmer's
manual](https://github.com/riscv/riscv-asm-manual/blob/master/riscv-asm.md).
Notes
=====
ASCII-art version of the Mandelbrot set, computed by a program in
assembly (`ASM_EXAMPLES/mandelbrot_terminal.S`)
![](Images/mandelbrot_terminal.gif)
I'm currently working on another procedure that compiles
Yosys/NextPNR/ProjectXRay directly from the up-to-date sources, because:
- This version of symbiflow does not seem to support DSPs
- Symbiflow includes a place-and-route tool that is not as efficient as nextPNR
| Program | Description |
|----------------------------------------|----------------------------------------------------------------|
| `ASM_EXAMPLES/blinker_shift.S` | the blinker program, using shifts |
| `ASM_EXAMPLES/blinker_wait.S` | the blinker program, using a delay loop |
| `ASM_EXAMPLES/test_serial.S` | reads characters from the serial over USB, and sends them back |
| `ASM_EXAMPLES/mandelbrot_terminal.S` | computes the Mandelbrot set and displays it in ASCII art |
| `EXAMPLES/hello.c` | displays a welcome message |
| `EXAMPLES/sieve.c` | computes prime numbers |
Examples with the LED matrix
============================
![](Images/LedMatrix_on_IceStick.jpg)
For more fun, you can add an 8x8 led matrix. It is cheap (less than
$1) and easy to find (just google search `max7219 8x8 led matrix`).
Make sure pin labels (CLK,CS,DIN,GND,VCC) correspond to the image, then
insert it in the J2 connector of the IceStik as shown on the image.
You can also build a [OysterPMOD](OysterPMOD.md) (with both a led
matrix and OLED screen using a single PMOD connector).
FemtoSOC configuration
----------------------
Now we need to activate hardware support for the led matrix (and
deactivate the UART). To do that, configure devices in `FemtoRV/RTL/CONFIGS/icestick_config.v` as follows:
```
...
`define NRV_IO_MAX7219 // Mapped IO, 8x8 led matrix
...
```
Then you need to re-synthethize and send the bitstream to the IceStick:
```
$make ICESTICK
```
![](Images/IceStick_hello.gif)
Now you can compile the `hello world` program
(`FIRMWARE/EXAMPLES/hello.c`). Edit it and uncomment the following line:
```
femtosoc_tty_init();
```
This line automatically redirects `printf()` to the configured device
(here the led matrix). Now compile the program and send it to the device:
```
$cd FIRMWARE/EXAMPLES
$make hello.prog
```
When the led matrix is configured, `printf()` is automatically
redirected to the scroller display routine. The `sieve.c` program will
also behave like that.
There are other examples that you can play with:
| Program | Description |
|----------------------------------------|----------------------------------------------------------------|
| `ASM_EXAMPLES/test_led_matrix.S` | display two images on the led matrix in ASM |
| `EXAMPLES/life_led_matrix.c` | Game of life on a 8x8 toroidal world |
If you want to write your own program: in C, you first need
to switch the display on using `MAX7219_init()`, then you can use
the function `MAX7219(col,data)` where `col` is the column index in 1..8
(and not 0..7 !!!), and data an 8-bit integer indicating which led
should be lit. Take a look at `FIRMWARE/EXAMPLES/life_led_matrix.c`
for reference.
Examples with the OLED screen
=============================
![](Images/SSD1351_on_IceStick.jpg)
With its 64 pixels, our led matrix is somewhat limited and lacks
colors... Let us generate more fancy graphics. For this, you will need a
_SSD1351 128x128 oled display_. It costs around $15 (there exists
cheaper screens, such as 240x240 IPS screens driven by the ST7789, but
they really do not look as good, and they are not compatible, believe me
the SSD1351 is worth the price). Make sure you get one of good quality
(if it costs less than $5 then I'd be suspicious, some users reported
failures with such low-cost versions). Got mine from Waveshare. Those
from Adafruit were reported to work as well.
These little screens need 7 wires. The good news is that no soldering
is needed, just get a 2x6 pins connector such as the one on the image,
connect the wires as shown to the connector, then the connector to the
IceStick. If the colors of the wires do not match, use the schematic
on the right to know wich wire goes where.
You can also build a [OysterPMOD](OysterPMOD.md) (with both a led
matrix and OLED screen using a single PMOD connector).
Now you need to reconfigure `icestick_config.v` as follows:
```
...
`define NRV_IO_SSD1351 // Mapped IO, 128x128x64K OLed screen
...
```
Then you need to re-synthethize and send the bitstream to the IceStick:
```
$make ICESTICK
```
Let us compile a test program:
```
$ cd FIRMWARE/EXAMPLES
$ make gfx_test.prog
```
If everything goes well, you will see an animated colored pattern on
the screen. Note that the text-mode demos (`hello.c` and `sieve.c`)
still work and now display text on the screen. There are other
programs that you can play with:
![](Images/IceStick_graphics.jpg)
_(The black diagonal stripes are due to display refresh, they are not visible normally)._
| Program | Description |
|----------------------------------------|----------------------------------------------------------------|
| `ASM_EXAMPLES/test_OLED.S` | displays an animated pattern. |
| `ASM_EXAMPLES/mandelbrot_OLED.S` | displays the Mandelbrot set. |
| `EXAMPLES/cube.c` | displays a rotating 3D cube. |
| `EXAMPLES/mandelbrot.c` | displays the Mandelbrot set (C version). |
| `EXAMPLES/riscv_logo.c` | a rotozoom with the RISCV logo (back to the 90's). |
| `EXAMPLES/spirograph.c` | rotating squares. |
| `EXAMPLES/gfx_test.c` | displays an animated pattern (C version). |
| `EXAMPLES/gfx_demo.c` | demo of graphics functions(old chaps, remember EGAVGA.bgi ?). |
| `EXAMPLES/test_font_OLED.c` | test font rendering. |
| `EXAMPLES/sysconfig.c` | displays femtosoc and femtorv configurations. |
The LIBFEMTORV32 library includes some basic font rendering, 2D polygon clipping and 2D polygon filling routines.
Everything fits in the available 6kbytes of memory !
Storing stuff on the SPI Flash
------------------------------
Is it all we can do with an IceStick ? No we can do more !
Let us see how to port a [Y2K demo called
ST-NICCC](http://www.pouet.net/prod.php?which=1251). Such 3D graphics
cannot be rendered in real time by our femto-machine
(and the 8 MHz 68000 of the Atari ST could not either !),
so it does render a precomputed stream of 2D
polygons stored in a file. The file weights 640Kb, and remember, we only
have 6Kb, so what can we do ? It would be possible to wire a SDCard
adapter and store the file there, but there is a much easier solution:
the IceStick stores the configuration of the FPGA in a flash memory, and
there is plenty of unused room in it: _if it does not fit in one chip,
we can overflow in the neighborhing chip !_. This flash memory is a tiny 8-legged
chip, that talks to the external world using a serial protocol (SPI).
In fact we are already using it ! It is where our programs are stored,
and FemtoRV32 directly executes them from there. We are also going to store
some data there.
Let us copy the data to the SPI flash:
```
$ iceprog -o 1M FIRMWARE/EXAMPLES/DATA/scene1.bin
```
This copies the data starting from a 1Mbytes offset (the lower
addresses are used to store the configuration of the FPGA and to store
our programs, so do not
overwrite them). The data file `scene1.bin` is the original one, taken
from the ST_NICCC demo.
Now you can compile the demo program and send it to the IceStick:
```
$ cd FIRMWARE/EXAMPLES
$ make ST_NICCC_spi_flash.prog
```
![](Images/ST_NICCC_on_IceStick.gif)
Can we do more with this tiny system ? Yes, we can do _raytracing_ !
```
$ cd FIRMWARE/EXAMPLES
$ make tinyraytracer.prog
```
It will display the classical shiny spheres and checkboard scene. It
takes around 20 minutes to do so, be patient ! This is because not only
our processor is not super fast, but also it does not have hardware
multiplication, and it executes floating point software routines from
the SPI Flash ! It would be faster to copy them in RAM, but they do
not fit (remember, we only have 6 KB of RAM).
For smaller programs, it is possible to fit a part of the routines in
RAM, take a look at `FIRMWARE/EXAMPLES/riscv_logo_2.c` (if you have both
the led matrix and SSD screen, it will tell you what it is doing). It
shows the effect of the magic keyword `RV32_FASTCODE`: this keyword is
expanded as an annotation, indicating to the linker that the
corresponding function should be copied in RAM instead of SPI Flash.
Since RAM is much faster to access than SPI Flash, you can do that for
some small functions that are called often. It is for instance the case
of some graphic functions, used by our version of the `ST_NICCC` demo.
However, the limits of our tiny system are quicky reached. If you want
to go further, an easy way is to get an ULX3S. It costs a bit more
($130) but it is worth the price (the on-board ECP5 FPGA is HUGE as
compared to the one of the IceStick). Now time to read the
[ULX3S tutorial](ULX3S.md) !
![](Images/ICE40HX1K_and_ECP5.png)
_To give you an idea, this image shows our core, installed on a
ICE40HX1K (that equips the IceStick) and on an ECP5 85K (that equips
the ULX3S). Plenty of room on the ULX3S !_

View File

@@ -48,3 +48,5 @@ https://reference.digilentinc.com/programmable-logic/arty/reference-manual
https://reference.digilentinc.com/programmable-logic/arty-a7/reference-manual
https://github.com/Digilent/digilent-xdc/blob/master/Arty-A7-35-Master.xdc
https://forum.digilentinc.com/topic/2438-pll-clocks-on-arty/