mirror of
https://github.com/im-tomu/fomu-workshop.git
synced 2024-09-20 03:10:12 +00:00
add vhdl/blink
This commit is contained in:
parent
2776953012
commit
21bcde2bd3
10
.github/tests.sh
vendored
10
.github/tests.sh
vendored
@ -7,6 +7,16 @@ echo "TOOLCHAIN_PATH: $TOOLCHAIN_PATH"
|
||||
|
||||
export PATH=$TOOLCHAIN_PATH/bin:$PATH
|
||||
|
||||
echo '::group::VHDL Blink example'
|
||||
(
|
||||
|
||||
set -x
|
||||
cd vhdl/blink
|
||||
make FOMU_REV=pvt
|
||||
file blink.dfu
|
||||
)
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::RISC-V C Example'
|
||||
(
|
||||
set -x
|
||||
|
@ -42,6 +42,8 @@ The contents of this workshop is published at [workshop.fomu.im](https://worksho
|
||||
CPU section of the workshop](https://workshop.fomu.im/en/latest/riscv.html).
|
||||
- [verilog](./verilog) - The files required for the [Verilog on Fomu section
|
||||
of the workshop](https://workshop.fomu.im/en/latest/verilog.html).
|
||||
- [vhdl](./vhdl) - The files required for the [VHDL on Fomu section
|
||||
of the workshop](https://workshop.fomu.im/en/latest/vhdl.html).
|
||||
|
||||
# Development
|
||||
|
||||
|
32
docs/hdl.rst
32
docs/hdl.rst
@ -5,10 +5,40 @@ The two most common **H**\ ardware **D**\ escription **L**\ anguages are
|
||||
Verilog and VHDL.
|
||||
|
||||
.. NOTE:: The pre-built toolchain we are releasing supports Verilog only.
|
||||
However, `GHDL <https://github.com/ghdl>`_ might be used as a VHDL frontend
|
||||
However, `GHDL <https://github.com/ghdl>`_ can be usable as a VHDL frontend
|
||||
for Yosys. See `ghdl-yosys-plugin <https://github.com/ghdl/ghdl-yosys-plugin>`_.
|
||||
|
||||
When writing HDL, a tool called ``yosys`` is used to convert the
|
||||
human readable verilog into a netlist representation, this is called
|
||||
*synthesis*. Once we have the netlist representation, a tool called
|
||||
``nextpnr`` performs an operation called *place and route* (P&R) which
|
||||
makes it something that will actually run on the FPGA. This is all
|
||||
done for you using the ``Makefiles`` in the subdirectories of ``verilog``
|
||||
or ``vhdl``.
|
||||
|
||||
A big feature of ``nextpnr`` over its predecessor, is the fact that
|
||||
it is timing-driven. This means that a design will be generated with
|
||||
a given clock domain guaranteed to perform fast enough.
|
||||
|
||||
When the ``make`` command runs ``nextpnr-ice40`` you will see something
|
||||
similar included in the output:
|
||||
|
||||
::
|
||||
|
||||
Info: Max frequency for clock 'clk': 73.26 MHz (PASS at 12.00 MHz)
|
||||
|
||||
This output example shows that we could run ``clk`` at up to 73.26
|
||||
MHz and it would still be stable (even though we only requested 12.00
|
||||
MHz). Note that there is some variation between designs depending on
|
||||
how the placer and router decided to lay things out, so your exact
|
||||
frequency numbers might be different from the ones shown in the code
|
||||
blocks of this documentation.
|
||||
|
||||
Languages and generators
|
||||
========================
|
||||
|
||||
.. toctree::
|
||||
|
||||
verilog
|
||||
vhdl
|
||||
migen
|
||||
|
@ -11,8 +11,7 @@ number so you get an on/off pattern.
|
||||
|
||||
Enter the ``verilog/blink`` directory and build the demo by using ``make``:
|
||||
|
||||
**Make sure you set the ``FOMU_REV`` value to match your hardware! See
|
||||
the Required Hardware section.**
|
||||
**Make sure you set the** ``FOMU_REV`` **value to match your hardware!** See :ref:`required-hardware`.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
@ -62,30 +61,6 @@ You can then load ``blink.dfu`` onto Fomu by using the same ``dfu-util -D``
|
||||
command we’ve been using so far. You should see a blinking pattern of
|
||||
varying color on your Fomu, indicating your bitstream was successfully loaded.
|
||||
|
||||
When writing HDL, a tool called ``yosys`` is used to convert the
|
||||
human readable verilog into a netlist representation, this is called
|
||||
synthesis. Once we have the netlist representation a tool called
|
||||
``nextpnr`` performs an operation called “place and route” which
|
||||
makes it something that will actually run on the FPGA. This is all
|
||||
done for you using the ``Makefile`` in the ``verilog/blink``
|
||||
directory.
|
||||
|
||||
A big feature of ``nextpnr`` over its predecessor, is the fact that
|
||||
it is timing-driven. This means that a design will be generated with
|
||||
a given clock domain guaranteed to perform fast enough.
|
||||
|
||||
When the ``make`` command runs ``nextpnr-ice40`` you will see something
|
||||
similar included in the output:
|
||||
|
||||
::
|
||||
|
||||
Info: Max frequency for clock 'clk': 73.26 MHz (PASS at 12.00 MHz)
|
||||
|
||||
This output example shows that we could run ``clk`` at up to 73.26
|
||||
MHz and it would still be stable, even though we only requested 12.00
|
||||
MHz. Note that there is some variation between designs depending on
|
||||
how the placer and router decided to lay things out, so your exact
|
||||
frequency numbers might be different.
|
||||
|
||||
Reading Input
|
||||
^^^^^^^^^^^^^
|
||||
|
67
docs/vhdl.rst
Normal file
67
docs/vhdl.rst
Normal file
@ -0,0 +1,67 @@
|
||||
VHDL on Fomu
|
||||
------------
|
||||
|
||||
.. HINT:: Component declarations for instantiating hard cores (such as the
|
||||
ones in ``sb_ice40_components.vhd``) are found in the installation of
|
||||
`iCEcube2 <http://www.latticesemi.com/iCEcube2>`_.
|
||||
|
||||
|
||||
“Hello world!” - Blink a LED
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The canonical “Hello, world!” of hardware is to blink a LED. The
|
||||
directory ``vhdl/blink`` contains a VHDL example of a blink
|
||||
project. This takes the 48 MHz clock and divides it down by a large
|
||||
number so you get an on/off pattern.
|
||||
|
||||
Enter the ``vhdl/blink`` directory and build the demo by using ``make``:
|
||||
|
||||
**Make sure you set the** ``FOMU_REV`` **value to match your hardware!** See :ref:`required-hardware`.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ make FOMU_REV=$FOMU_REV
|
||||
...
|
||||
Info: Max frequency for clock 'clk': 70.39 MHz (PASS at 12.00 MHz)
|
||||
|
||||
Info: Max delay posedge clk -> <async>: 3.15 ns
|
||||
|
||||
Info: Slack histogram:
|
||||
Info: legend: * represents 1 endpoint(s)
|
||||
Info: + represents [1,1) endpoint(s)
|
||||
Info: [ 69127, 69680) |**
|
||||
Info: [ 69680, 70233) |**
|
||||
Info: [ 70233, 70786) |
|
||||
Info: [ 70786, 71339) |**
|
||||
Info: [ 71339, 71892) |**
|
||||
Info: [ 71892, 72445) |**
|
||||
Info: [ 72445, 72998) |**
|
||||
Info: [ 72998, 73551) |
|
||||
Info: [ 73551, 74104) |**
|
||||
Info: [ 74104, 74657) |**
|
||||
Info: [ 74657, 75210) |**
|
||||
Info: [ 75210, 75763) |**
|
||||
Info: [ 75763, 76316) |
|
||||
Info: [ 76316, 76869) |**
|
||||
Info: [ 76869, 77422) |**
|
||||
Info: [ 77422, 77975) |**
|
||||
Info: [ 77975, 78528) |
|
||||
Info: [ 78528, 79081) |***************************
|
||||
Info: [ 79081, 79634) |**
|
||||
Info: [ 79634, 80187) |***
|
||||
22 warnings, 0 errors
|
||||
docker run --rm -v //t/fomu/fomu-workshop/vhdl/blink/../..://src -w //src/vhdl/blink ghdl/synth:icestorm icepack blink.asc blink.bit
|
||||
cp blink.bit blink.dfu
|
||||
dfu-suffix -v 1209 -p 70b1 -a blink.dfu
|
||||
dfu-suffix (dfu-util) 0.9
|
||||
|
||||
Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Suffix successfully added to file
|
||||
$
|
||||
|
||||
You can then load ``blink.dfu`` onto Fomu by using ``make load`` or the same
|
||||
``dfu-util -D`` command we’ve been using so far. You should see a blinking pattern of
|
||||
varying color on your Fomu, indicating your bitstream was successfully loaded.
|
76
vhdl/blink/Makefile
Normal file
76
vhdl/blink/Makefile
Normal file
@ -0,0 +1,76 @@
|
||||
# Different Fomu hardware revisions are wired differently and thus
|
||||
# require different configurations for yosys and nextpnr.
|
||||
# Configuration is performed by setting the environment variable FOMU_REV accordingly.
|
||||
ifeq ($(FOMU_REV),evt1)
|
||||
YOSYSFLAGS?= -D EVT=1
|
||||
PNRFLAGS ?= --up5k --package sg48 --pcf ../../pcf/fomu-evt2.pcf
|
||||
else ifeq ($(FOMU_REV),evt2)
|
||||
YOSYSFLAGS?= -D EVT=1
|
||||
PNRFLAGS ?= --up5k --package sg48 --pcf ../../pcf/fomu-evt2.pcf
|
||||
else ifeq ($(FOMU_REV),evt3)
|
||||
YOSYSFLAGS?= -D EVT=1
|
||||
PNRFLAGS ?= --up5k --package sg48 --pcf ../../pcf/fomu-evt3.pcf
|
||||
else ifeq ($(FOMU_REV),hacker)
|
||||
YOSYSFLAGS?= -D HACKER=1
|
||||
PNRFLAGS ?= --up5k --package uwg30 --pcf ../../pcf/fomu-hacker.pcf
|
||||
else ifeq ($(FOMU_REV),pvt)
|
||||
YOSYSFLAGS?= -D PVT=1
|
||||
PNRFLAGS ?= --up5k --package uwg30 --pcf ../../pcf/fomu-pvt.pcf
|
||||
else
|
||||
$(error Unrecognized FOMU_REV value. must be "evt1", "evt2", "evt3", "pvt", or "hacker")
|
||||
endif
|
||||
|
||||
VHDL_SYN_FILES = ../sb_ice40_components.vhd blink.vhd
|
||||
|
||||
GHDL_FLAGS += --std=08
|
||||
GHDL ?= ghdl
|
||||
GHDLSYNTH ?= ghdl
|
||||
YOSYS ?= yosys
|
||||
NEXTPNR ?= nextpnr-ice40
|
||||
ICEPACK ?= icepack
|
||||
|
||||
# Default target: run all required targets to build the DFU image.
|
||||
all: blink.dfu
|
||||
@true
|
||||
|
||||
.DEFAULT: all
|
||||
|
||||
# Use *Yosys* to generate the synthesized netlist.
|
||||
# This is called the **synthesis** and **tech mapping** step.
|
||||
blink.json: $(VHDL_SYN_FILES)
|
||||
$(YOSYS) $(YOSYSFLAGS) \
|
||||
-p \
|
||||
"$(GHDLSYNTH) $(GHDL_FLAGS) $^ -e; \
|
||||
synth_ice40 \
|
||||
-top Fomu_Blink \
|
||||
-json $@" 2>&1 | tee yosys-report.txt
|
||||
|
||||
# Use **nextpnr** to generate the FPGA configuration.
|
||||
# This is called the **place** and **route** step.
|
||||
blink.asc: blink.json
|
||||
$(NEXTPNR) \
|
||||
$(PNRFLAGS) \
|
||||
--json $< \
|
||||
--asc $@
|
||||
|
||||
# Use icepack to convert the FPGA configuration into a "bitstream" loadable onto the FPGA.
|
||||
# This is called the bitstream generation step.
|
||||
blink.bit: blink.asc
|
||||
$(ICEPACK) $< $@
|
||||
|
||||
# Use dfu-suffix to generate the DFU image from the FPGA bitstream.
|
||||
blink.dfu: blink.bit
|
||||
cp $< $@
|
||||
dfu-suffix -v 1209 -p 70b1 -a $@
|
||||
|
||||
# Use df-util to load the DFU image onto the Fomu.
|
||||
load: blink.dfu
|
||||
dfu-util -D $<
|
||||
|
||||
.PHONY: load
|
||||
|
||||
# Cleanup the generated files.
|
||||
clean:
|
||||
rm -fr *.cf *.json *-report.txt *.asc *.bit *.dfu
|
||||
|
||||
.PHONY: clean
|
10
vhdl/blink/README.md
Normal file
10
vhdl/blink/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Minimal VHDL Example
|
||||
|
||||
A minimal VHDL example which simply blinks the RGB LEDs at different
|
||||
frequencies.
|
||||
|
||||
## Using
|
||||
|
||||
Type `make` to build the DFU image.
|
||||
Type `make load` to load the DFU image onto the Fomu board.
|
||||
Type `make clean` to remove all the generated files.
|
80
vhdl/blink/blink.vhd
Normal file
80
vhdl/blink/blink.vhd
Normal file
@ -0,0 +1,80 @@
|
||||
library ieee;
|
||||
context ieee.ieee_std_context;
|
||||
|
||||
use work.components.all;
|
||||
|
||||
entity Fomu_Blink is
|
||||
port (
|
||||
-- 48MHz Clock input
|
||||
clki: in std_logic;
|
||||
|
||||
-- LED outputs
|
||||
rgb0: out std_logic;
|
||||
rgb1: out std_logic;
|
||||
rgb2: out std_logic;
|
||||
|
||||
-- USB Pins (which should be statically driven if not being used)
|
||||
usb_dp: out std_logic;
|
||||
usb_dn: out std_logic;
|
||||
usb_dp_pu: out std_logic
|
||||
);
|
||||
end;
|
||||
|
||||
architecture arch of Fomu_Blink is
|
||||
|
||||
signal clk: std_logic;
|
||||
signal counter: unsigned(27 downto 0) := (others=>'0');
|
||||
|
||||
begin
|
||||
|
||||
-- Assign USB pins to "0" so as to disconnect Fomu from
|
||||
-- the host system. Otherwise it would try to talk to
|
||||
-- us over USB, which wouldn't work since we have no stack.
|
||||
usb_dp <= '0';
|
||||
usb_dn <= '0';
|
||||
usb_dp_pu <= '0';
|
||||
|
||||
-- Connect to system clock (with buffering)
|
||||
clk_gb: SB_GB
|
||||
port map (
|
||||
USER_SIGNAL_TO_GLOBAL_BUFFER => clki,
|
||||
GLOBAL_BUFFER_OUTPUT => clk
|
||||
);
|
||||
|
||||
-- Use counter logic to divide system clock. The clock is 48 MHz,
|
||||
-- so we divide it down by 2^28.
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
counter <= counter + 1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Instantiate iCE40 LED driver hard logic, connecting up
|
||||
-- counter state and LEDs.
|
||||
--
|
||||
-- Note that it's possible to drive the LEDs directly,
|
||||
-- however that is not current-limited and results in
|
||||
-- overvolting the red LED.
|
||||
--
|
||||
-- See also:
|
||||
-- https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/IK/ICE40LEDDriverUsageGuide.ashx?document_id=50668
|
||||
rgba_driver: SB_RGBA_DRV
|
||||
generic map (
|
||||
CURRENT_MODE => "0b1", -- half current
|
||||
RGB0_CURRENT => "0b000011", -- 4 mA
|
||||
RGB1_CURRENT => "0b000011", -- 4 mA
|
||||
RGB2_CURRENT => "0b000011" -- 4 mA
|
||||
)
|
||||
port map (
|
||||
CURREN => '1',
|
||||
RGBLEDEN => '1',
|
||||
RGB0PWM => counter(counter'left),
|
||||
RGB1PWM => counter(counter'left-1),
|
||||
RGB2PWM => counter(counter'left-2),
|
||||
RGB0 => rgb0,
|
||||
RGB1 => rgb1,
|
||||
RGB2 => rgb2
|
||||
);
|
||||
|
||||
end;
|
32
vhdl/sb_ice40_components.vhd
Normal file
32
vhdl/sb_ice40_components.vhd
Normal file
@ -0,0 +1,32 @@
|
||||
library ieee ;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
package components is
|
||||
|
||||
component SB_GB
|
||||
port(
|
||||
GLOBAL_BUFFER_OUTPUT : out std_logic;
|
||||
USER_SIGNAL_TO_GLOBAL_BUFFER : in std_logic
|
||||
);
|
||||
end component;
|
||||
|
||||
component SB_RGBA_DRV
|
||||
generic (
|
||||
CURRENT_MODE : string := "0b0";
|
||||
RGB0_CURRENT : string := "0b000000";
|
||||
RGB1_CURRENT : string := "0b000000";
|
||||
RGB2_CURRENT : string := "0b000000"
|
||||
);
|
||||
port (
|
||||
RGB0PWM : in std_logic;
|
||||
RGB1PWM : in std_logic;
|
||||
RGB2PWM : in std_logic;
|
||||
CURREN : in std_logic;
|
||||
RGBLEDEN : in std_logic;
|
||||
RGB0 : out std_logic;
|
||||
RGB1 : out std_logic;
|
||||
RGB2 : out std_logic
|
||||
);
|
||||
end component;
|
||||
|
||||
end components;
|
Loading…
Reference in New Issue
Block a user