aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorMartin <hackfin@section5.ch>2020-02-14 20:15:22 +0100
committerGitHub <noreply@github.com>2020-02-14 20:15:22 +0100
commit27b14ac284407755a31aa644219948102730f179 (patch)
tree4b2f696cd4cd104705383467cb27fb711afcf2fd /examples
parentfe9f2c4eb258f9e4e20a60742750698b09c9ed4b (diff)
downloadghdl-yosys-plugin-27b14ac284407755a31aa644219948102730f179.tar.gz
ghdl-yosys-plugin-27b14ac284407755a31aa644219948102730f179.tar.bz2
ghdl-yosys-plugin-27b14ac284407755a31aa644219948102730f179.zip
Added ECP5 example for Lattice versa devkit (#85)
- LED blinky - Added support for vendor primitives - Workarounds in Verilog for BRAM and primitive wrapping - Docker support Makefiles - openocd support files
Diffstat (limited to 'examples')
-rw-r--r--examples/docker.mk17
-rw-r--r--examples/ecp5_versa/Makefile52
-rw-r--r--examples/ecp5_versa/fifobuf.vhdl244
-rw-r--r--examples/ecp5_versa/libram.vhdl202
-rw-r--r--examples/ecp5_versa/pll_mac.vhd86
-rw-r--r--examples/ecp5_versa/soc_iomap_pkg.vhdl116
-rw-r--r--examples/ecp5_versa/uart.vhdl175
-rw-r--r--examples/ecp5_versa/uart_rx.vhdl204
-rw-r--r--examples/ecp5_versa/uart_tx.vhdl125
-rw-r--r--examples/ecp5_versa/versa_ecp5.lpf122
-rw-r--r--examples/ecp5_versa/versa_ecp5_top.vhdl162
-rw-r--r--examples/ghdlsynth.mk34
12 files changed, 1539 insertions, 0 deletions
diff --git a/examples/docker.mk b/examples/docker.mk
new file mode 100644
index 0000000..dd9acc2
--- /dev/null
+++ b/examples/docker.mk
@@ -0,0 +1,17 @@
+# Use Docker images
+DOCKER=docker
+#DOCKER=podman
+#
+PWD = $(shell pwd)
+DOCKERARGS = run --rm -v $(PWD)/../..:/src \
+ -w /src/examples/$(notdir $(PWD))
+
+
+GHDL = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta ghdl
+GHDLSYNTH = ghdl
+YOSYS = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta yosys
+NEXTPNR = $(DOCKER) $(DOCKERARGS) ghdl/synth:nextpnr-ecp5 nextpnr-ecp5
+ECPPACK = $(DOCKER) $(DOCKERARGS) ghdl/synth:trellis ecppack
+OPENOCD = $(DOCKER) $(DOCKERARGS) --device /dev/bus/usb ghdl/synth:prog openocd
+
+
diff --git a/examples/ecp5_versa/Makefile b/examples/ecp5_versa/Makefile
new file mode 100644
index 0000000..6031055
--- /dev/null
+++ b/examples/ecp5_versa/Makefile
@@ -0,0 +1,52 @@
+LIB = ../../library
+
+GHDL ?= ghdl
+
+GHDL_FLAGS = -Plib
+
+CLK_FREQ = 25000000
+
+GHDL_GENERICS=-gCLK_FREQUENCY=$(CLK_FREQ)
+LPF = versa_ecp5.lpf
+PACKAGE = CABGA381
+NEXTPNR_FLAGS = --um5g-45k --freq 100
+NEXTPNR_FLAGS += --lpf-allow-unconstrained
+OPENOCD_JTAG_CONFIG = ../../openocd/ecp5-versa.cfg
+OPENOCD_DEVICE_CONFIG = ../../openocd/LFE5UM5G-45F.cfg
+
+WORKDIR = work
+# Files to synthesize:
+VHDL_SYN_FILES = versa_ecp5_top.vhdl pll_mac.vhd
+VHDL_SYN_FILES += soc_iomap_pkg.vhdl
+VHDL_SYN_FILES += uart.vhdl uart_tx.vhdl uart_rx.vhdl fifobuf.vhdl
+
+TOPLEVEL = versa_ecp5_top
+TOPLEVEL_PARAMETER = _$(CLK_FREQ)
+
+VERILOG_FILES = $(LIB)/wrapper/primitives.v
+VERILOG_FILES += $(LIB)/wrapper/wrapper.v
+VERILOG_FILES += $(LIB)/wrapper/bram.v
+
+SVFFILE = versa_ecp5_top.svf
+DEPENDENCIES = lib/ecp5um-std93.cf
+
+all: $(SVFFILE)
+
+include ../docker.mk
+include ../ghdlsynth.mk
+
+lib:
+ mkdir $@
+
+lib/ecp5um-std93.cf: $(LIB)/ecp5u/components.vhdl | lib
+ $(GHDL) -i --workdir=$(dir $@) --work=ecp5um \
+ $<
+
+pll_mac.vhd: $(DEPENDENCIES)
+
+prog: $(SVFFILE)
+ $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) \
+ -c "transport select jtag; init; svf $<; exit"
+
+clean:
+ rm -fr lib work *.json *.svf *.config *-report.txt
diff --git a/examples/ecp5_versa/fifobuf.vhdl b/examples/ecp5_versa/fifobuf.vhdl
new file mode 100644
index 0000000..4981c1d
--- /dev/null
+++ b/examples/ecp5_versa/fifobuf.vhdl
@@ -0,0 +1,244 @@
+--
+-- Configureable bit size I/O FIFO buffer
+--
+-- (c) 2010-2013, Martin Strubel <hackfin@section5.ch>
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity FifoBuffer is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ EXTRA_REGISTER : boolean := false;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ -- Write enable
+ wren : in std_logic;
+ idata : in unsigned(DATA_W-1 downto 0);
+ iready : out std_logic;
+ -- Data stream output:
+ odata : out unsigned(DATA_W-1 downto 0);
+ oready : out std_logic;
+ rden : in std_logic;
+ err : out std_logic;
+ reset : in std_logic;
+ clk : in std_logic
+ );
+end entity FifoBuffer;
+
+
+architecture behaviour of FifoBuffer is
+ constant FULL_COUNT : unsigned(ADDR_W-1 downto 0) := (others => '1');
+ constant ZERO_COUNT : unsigned(ADDR_W-1 downto 0) := (others => '0');
+
+ constant INACTIVE_WRITE_PORT :
+ unsigned(DATA_W-1 downto 0) := (others => '0');
+ signal iptr : unsigned(ADDR_W-1 downto 0) := ZERO_COUNT;
+ signal optr : unsigned(ADDR_W-1 downto 0) := ZERO_COUNT;
+ signal next_iptr : unsigned(ADDR_W-1 downto 0) := ZERO_COUNT;
+ signal next_optr : unsigned(ADDR_W-1 downto 0) := ZERO_COUNT;
+ signal over : std_logic := '0';
+
+ signal rdata : unsigned(DATA_W-1 downto 0);
+
+ type state_t is (S_IDLE, S_READY, S_FULL, S_ERROR);
+ -- GHDLSYNTH_QUIRK
+ -- Needs this initialized, otherwise gets 'optimized away'
+ signal state : state_t := S_IDLE;
+ -- If we don't initialize, yosys feels like it wants to recode.
+ -- signal state : state_t;
+
+ signal int_full : std_logic; -- Internal "full" flag
+ signal int_rden : std_logic;
+ signal int_rden_d : std_logic;
+ signal maybe_full : std_logic;
+ signal maybe_empty : std_logic;
+
+ signal dready : std_logic;
+
+ component bram_2psync is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ -- Port A
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0);
+ clk : in std_logic
+ );
+ end component bram_2psync;
+
+begin
+
+count:
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if reset = '1' then
+ optr <= ZERO_COUNT;
+ iptr <= ZERO_COUNT;
+ else
+ if wren = '1' then
+ iptr <= next_iptr;
+ end if;
+ if int_rden = '1' then
+ optr <= next_optr;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ next_iptr <= iptr + 1;
+ next_optr <= optr + 1;
+
+ -- These are ambiguous signals, need evaluation of wren/rden!
+ maybe_full <= '1' when optr = next_iptr else '0';
+ maybe_empty <= '1' when iptr = next_optr else '0';
+
+ dready <= '1' when state = S_READY or state = S_FULL else '0';
+
+fsm:
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if reset = '1' then
+ state <= S_IDLE;
+ else
+ case state is
+ when S_IDLE =>
+ if wren = '1' then
+ state <= S_READY;
+ else
+ state <= S_IDLE;
+ end if;
+ when S_READY =>
+ if wren = '1' then
+ -- We're just getting full
+ if maybe_full = '1' and int_rden = '0' then
+ state <= S_FULL;
+ end if;
+ -- We're just getting empty
+ elsif maybe_empty = '1' and int_rden = '1' then
+ state <= S_IDLE;
+ end if;
+ -- All other conditions: Remain S_READY
+ when S_FULL =>
+ if wren = '1' then
+ -- It is actually allowed to read and write
+ -- simultaneously while FULL.
+ if int_rden = '0' then
+ state <= S_ERROR;
+ else
+ state <= S_FULL;
+ end if;
+ elsif int_rden = '1' then
+ state <= S_READY;
+ else
+ state <= S_FULL;
+ end if;
+ when S_ERROR =>
+ end case;
+ end if;
+ end if;
+ end process;
+
+ over <= '1' when state = S_ERROR else '0';
+ err <= over;
+
+ram:
+ bram_2psync
+ generic map ( ADDR_W => ADDR_W, DATA_W => DATA_W,
+ SYN_RAMTYPE => SYN_RAMTYPE)
+ port map (
+ a_we => '0',
+ a_addr => optr,
+ a_write => INACTIVE_WRITE_PORT,
+ a_read => rdata,
+ b_we => wren,
+ b_addr => iptr,
+ b_write => idata,
+ b_read => open,
+ clk => clk
+ );
+
+
+-- This section appends a little pre-read unit to the FIFO
+-- to allow higher speed on most architectures.
+
+gen_register:
+ if EXTRA_REGISTER generate
+
+ int_rden <= (not int_full or rden) and dready;
+preread:
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if reset = '1' then
+ int_full <= '0';
+ elsif dready = '1' then
+ if int_full = '0' then
+ int_full <= '1';
+ oready <= '1';
+ end if;
+ elsif int_full = '1' then
+ if rden = '1' then
+ oready <= '0';
+ int_full <= '0';
+ else
+ oready <= '1';
+ end if;
+ else
+ oready <= '0';
+ end if;
+
+ int_rden_d <= int_rden;
+ if int_rden_d = '1' then
+ odata <= rdata;
+ end if;
+ end if;
+ end process;
+ end generate;
+
+
+gen_direct:
+ if not EXTRA_REGISTER generate
+ int_full <= '1' when state = S_FULL else '0';
+ int_rden <= rden;
+ odata <= rdata;
+ oready <= dready;
+ end generate;
+
+ iready <= not int_full;
+
+
+-- synthesis translate_off
+
+-- Synplify barfs on this, we need to comment out the whole shlorm.
+
+errguard:
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if over = '1' then
+ assert false report "FIFO overrun in " & behaviour'path_name
+ severity failure;
+ end if;
+ end if;
+ end process;
+
+-- synthesis translate_on
+
+end behaviour;
diff --git a/examples/ecp5_versa/libram.vhdl b/examples/ecp5_versa/libram.vhdl
new file mode 100644
index 0000000..4307b38
--- /dev/null
+++ b/examples/ecp5_versa/libram.vhdl
@@ -0,0 +1,202 @@
+-- Common RAM library package
+-- For MIPS specific RAM package: see pkg_ram.
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+package ram is
+
+ -- Unconstrained 16 bit RAM initialization type
+ type ram16_init_t is array(natural range <>) of
+ unsigned(15 downto 0);
+
+ -- Unconstrained 32 bit RAM initialization type
+ type ram32_init_t is array(natural range <>) of
+ unsigned(31 downto 0);
+
+ component DPRAM16_init is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ INIT_DATA : ram16_init_t;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ clk : in std_logic;
+ -- Port A
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0)
+ );
+ end component DPRAM16_init;
+
+ component DPRAM16_init_ce is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ INIT_DATA : ram16_init_t;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ clk : in std_logic;
+ -- Port A
+ a_ce : in std_logic;
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_ce : in std_logic;
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0)
+ );
+ end component DPRAM16_init_ce;
+
+ component DPRAM16_init_hex_ce is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ INIT_DATA : string := "mem.hex";
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ -- Port A
+ a_clk : in std_logic;
+ a_ce : in std_logic;
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_clk : in std_logic;
+ b_ce : in std_logic;
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0)
+ );
+ end component DPRAM16_init_hex_ce;
+
+ component DPRAM_init_hex is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 32;
+ INIT_DATA : string := "mem32.hex";
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ clk : in std_logic;
+ -- Port A
+ a_ce : in std_logic;
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_ce : in std_logic;
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0)
+ );
+ end component DPRAM_init_hex;
+
+
+ component DPRAM32_init is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 32;
+ INIT_DATA : ram32_init_t;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ clk : in std_logic;
+ -- Port A
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0)
+ );
+ end component DPRAM32_init;
+
+ component DPRAM is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ EN_BYPASS : boolean := false;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ clk : in std_logic;
+ -- Port A
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0)
+ );
+ end component DPRAM;
+
+ component DPRAM_clk2
+ generic(
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ EN_BYPASS : boolean := true;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port(
+ a_clk : in std_logic;
+ -- Port A
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_clk : in std_logic;
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0)
+ );
+ end component;
+
+ component bram_2psync is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ -- Port A
+ a_we : in std_logic;
+ a_addr : in unsigned(ADDR_W-1 downto 0);
+ a_write : in unsigned(DATA_W-1 downto 0);
+ a_read : out unsigned(DATA_W-1 downto 0);
+ -- Port B
+ b_we : in std_logic;
+ b_addr : in unsigned(ADDR_W-1 downto 0);
+ b_write : in unsigned(DATA_W-1 downto 0);
+ b_read : out unsigned(DATA_W-1 downto 0);
+ clk : in std_logic
+ );
+ end component bram_2psync;
+
+end package;
diff --git a/examples/ecp5_versa/pll_mac.vhd b/examples/ecp5_versa/pll_mac.vhd
new file mode 100644
index 0000000..2d23cf7
--- /dev/null
+++ b/examples/ecp5_versa/pll_mac.vhd
@@ -0,0 +1,86 @@
+-- VHDL netlist generated by SCUBA Diamond (64-bit) 3.8.0.115.3
+-- Module Version: 5.7
+--/usr/local/diamond/3.8_x64/ispfpga/bin/lin64/scuba -w -n pll_mac -lang vhdl -synth synplify -bus_exp 7 -bb -arch sa5p00g -type pll -fin 100.00 -fclkop 125 -fclkop_tol 0.0 -fclkos 25 -fclkos_tol 0.0 -phases 0 -fclkos2 50 -fclkos2_tol 0.0 -phases2 0 -fclkos3 75 -fclkos3_tol 0.0 -phases3 0 -phase_cntl STATIC -lock -fb_mode 1 -fdc /home/strubi/src/masocist/syn/lattice/versaECP5G/ipcores/pll/pll_mac/pll_mac.fdc
+
+-- Wed May 10 17:35:30 2017
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+library ecp5um;
+use ecp5um.components.all;
+
+entity pll_mac is
+ port (
+ CLKI: in std_logic;
+ CLKOP: out std_logic;
+ CLKOS: out std_logic;
+ CLKOS2: out std_logic;
+ CLKOS3: out std_logic;
+ LOCK: out std_logic);
+end pll_mac;
+
+architecture Structure of pll_mac is
+
+ -- internal signal declarations
+ signal REFCLK: std_logic;
+ signal CLKOS3_t: std_logic;
+ signal CLKOS2_t: std_logic;
+ signal CLKOS_t: std_logic;
+ signal CLKOP_t: std_logic;
+ signal scuba_vhi: std_logic;
+ signal scuba_vlo: std_logic;
+
+ attribute FREQUENCY_PIN_CLKOS3 : string;
+ attribute FREQUENCY_PIN_CLKOS2 : string;
+ attribute FREQUENCY_PIN_CLKOS : string;
+ attribute FREQUENCY_PIN_CLKOP : string;
+ attribute FREQUENCY_PIN_CLKI : string;
+ attribute ICP_CURRENT : string;
+ attribute LPF_RESISTOR : string;
+ attribute FREQUENCY_PIN_CLKOS3 of PLLInst_0 : label is "75.000000";
+ attribute FREQUENCY_PIN_CLKOS2 of PLLInst_0 : label is "50.000000";
+ attribute FREQUENCY_PIN_CLKOS of PLLInst_0 : label is "25.000000";
+ attribute FREQUENCY_PIN_CLKOP of PLLInst_0 : label is "125.000000";
+ attribute FREQUENCY_PIN_CLKI of PLLInst_0 : label is "100.000000";
+ attribute ICP_CURRENT of PLLInst_0 : label is "7";
+ attribute LPF_RESISTOR of PLLInst_0 : label is "16";
+ attribute syn_keep : boolean;
+ attribute NGD_DRC_MASK : integer;
+ attribute NGD_DRC_MASK of Structure : architecture is 1;
+
+begin
+ -- component instantiation statements
+ scuba_vhi_inst: VHI
+ port map (Z=>scuba_vhi);
+
+ scuba_vlo_inst: VLO
+ port map (Z=>scuba_vlo);
+
+ PLLInst_0: EHXPLLL
+ generic map (PLLRST_ENA=> "DISABLED", INTFB_WAKE=> "DISABLED",
+ STDBY_ENABLE=> "DISABLED", DPHASE_SOURCE=> "DISABLED",
+ CLKOS3_FPHASE=> 0, CLKOS3_CPHASE=> 9, CLKOS2_FPHASE=> 0,
+ CLKOS2_CPHASE=> 14, CLKOS_FPHASE=> 0, CLKOS_CPHASE=> 29,
+ CLKOP_FPHASE=> 0, CLKOP_CPHASE=> 5, PLL_LOCK_MODE=> 0,
+ CLKOS_TRIM_DELAY=> 0, CLKOS_TRIM_POL=> "FALLING",
+ CLKOP_TRIM_DELAY=> 0, CLKOP_TRIM_POL=> "FALLING",
+ OUTDIVIDER_MUXD=> "DIVD", CLKOS3_ENABLE=> "ENABLED",
+ OUTDIVIDER_MUXC=> "DIVC", CLKOS2_ENABLE=> "ENABLED",
+ OUTDIVIDER_MUXB=> "DIVB", CLKOS_ENABLE=> "ENABLED",
+ OUTDIVIDER_MUXA=> "DIVA", CLKOP_ENABLE=> "ENABLED", CLKOS3_DIV=> 10,
+ CLKOS2_DIV=> 15, CLKOS_DIV=> 30, CLKOP_DIV=> 6, CLKFB_DIV=> 5,
+ CLKI_DIV=> 4, FEEDBK_PATH=> "CLKOP")
+ port map (CLKI=>CLKI, CLKFB=>CLKOP_t, PHASESEL1=>scuba_vlo,
+ PHASESEL0=>scuba_vlo, PHASEDIR=>scuba_vlo,
+ PHASESTEP=>scuba_vlo, PHASELOADREG=>scuba_vlo,
+ STDBY=>scuba_vlo, PLLWAKESYNC=>scuba_vlo, RST=>scuba_vlo,
+ ENCLKOP=>scuba_vlo, ENCLKOS=>scuba_vlo, ENCLKOS2=>scuba_vlo,
+ ENCLKOS3=>scuba_vlo, CLKOP=>CLKOP_t, CLKOS=>CLKOS_t,
+ CLKOS2=>CLKOS2_t, CLKOS3=>CLKOS3_t, LOCK=>LOCK,
+ INTLOCK=>open, REFCLK=>REFCLK, CLKINTFB=>open);
+
+ CLKOS3 <= CLKOS3_t;
+ CLKOS2 <= CLKOS2_t;
+ CLKOS <= CLKOS_t;
+ CLKOP <= CLKOP_t;
+end Structure;
diff --git a/examples/ecp5_versa/soc_iomap_pkg.vhdl b/examples/ecp5_versa/soc_iomap_pkg.vhdl
new file mode 100644
index 0000000..8a7f975
--- /dev/null
+++ b/examples/ecp5_versa/soc_iomap_pkg.vhdl
@@ -0,0 +1,116 @@
+-- File generated by gensoc 394864f
+-- (c) 2012-2018, Martin Strubel <hackfin@section5.ch>
+--
+-- Changes to this file will be lost. Edit the source file.
+--
+-- LICENSE: Evaluation license. Not for commercial usage.
+----------------------------------------------------------------------------
+-- This VHDL package is generated from
+-- ../gen/syn-versa_ecp5/neo430-versa_ecp5.xml
+-- Stylesheet: vhdlregs v0.1
+
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+-- Header:
+package system_map is
+ -- HW revision tag. Use in your code to sync with firmware.
+ constant HWREV_system_map_MAJOR : natural := 0;
+ constant HWREV_system_map_MINOR : natural := 0;
+ constant HWREV_system_map_EXT : string := "";
+
+ subtype regaddr_t is unsigned(7 downto 0);
+ subtype regaddr16_t is unsigned(15 downto 0);
+
+
+ subtype REG_SIZE1B is integer range 7 downto 0;
+ subtype REG_SIZE2B is integer range 15 downto 0;
+ subtype REG_SIZE3B is integer range 23 downto 0;
+ subtype REG_SIZE4B is integer range 31 downto 0;
+
+ -- Register and bitfield constants:
+
+-------------------------------------------------------------------------
+-- Address segment 'UART'
+-- Offset:
+
+-- UART Control register
+ constant R_UART_UART_CONTROL : regaddr_t := x"00";
+-- (16x) Clock divider
+ subtype BV_UART_CLKDIV is integer range 9 downto 0;
+-- Enable receive IRQ
+ constant B_RX_IRQ_ENABLE : natural := 14;
+-- '1': Reset UART. Clear to run.
+ constant B_UART_RESET : natural := 15;
+-- UART status register
+ constant R_UART_UART_STATUS : regaddr_t := x"02";
+-- Set when data ready in RX FIFO
+ constant B_RXREADY : natural := 0;
+-- Set when TX FIFO ready for data
+ constant B_TXREADY : natural := 1;
+-- '1' when TX in progress
+ constant B_TXBUSY : natural := 2;
+-- Sticky framing error. Set when stop bit not null. Reset by UART_RESET.
+ constant B_FRERR : natural := 5;
+-- Transmitter FIFO overrun. Cleared by UART_RESET.
+ constant B_TXOVR : natural := 6;
+-- Receiver FIFO overrun. Cleared by UART_RESET.
+ constant B_RXOVR : natural := 7;
+-- RX bit counter
+ subtype BV_BITCOUNT is integer range 10 downto 8;
+-- UART receiver register
+ constant R_UART_UART_RXR : regaddr_t := x"04";
+-- UART receive data
+ subtype BV_RXDATA is integer range 7 downto 0;
+-- 1 when data valid (mirror of RXREADY bit)
+ constant B_DVALID : natural := 8;
+-- UART transmitter register
+ constant R_UART_UART_TXR : regaddr_t := x"04";
+
+
+ type uart_ReadPort is record
+ --! Exported value for register 'R_UART_UART_STATUS'
+ --! Exported value for bit (vector) 'RXREADY'
+ rxready : std_logic;
+ --! Exported value for bit (vector) 'TXREADY'
+ txready : std_logic;
+ --! Exported value for bit (vector) 'TXBUSY'
+ txbusy : std_logic;
+ --! Exported value for bit (vector) 'FRERR'
+ frerr : std_logic;
+ --! Exported value for bit (vector) 'TXOVR'
+ txovr : std_logic;
+ --! Exported value for bit (vector) 'RXOVR'
+ rxovr : std_logic;
+ --! Exported value for bit (vector) 'BITCOUNT'
+ bitcount : unsigned(BV_BITCOUNT);
+ --! Exported value for register 'R_UART_UART_RXR'
+ --! Exported value for bit (vector) 'RXDATA'
+ rxdata : unsigned(BV_RXDATA);
+ --! Exported value for bit (vector) 'DVALID'
+ dvalid : std_logic;
+ end record;
+
+ type uart_WritePort is record
+ --! Exported value for register 'R_UART_UART_CONTROL'
+ --! Exported value for bit (vector) 'UART_CLKDIV'
+ uart_clkdiv : unsigned(BV_UART_CLKDIV);
+ --! Exported value for bit (vector) 'RX_IRQ_ENABLE'
+ rx_irq_enable : std_logic;
+ --! Exported value for bit (vector) 'UART_RESET'
+ uart_reset : std_logic;
+ --! Exported value for register 'R_UART_UART_TXR'
+ uart_txr : unsigned(REG_SIZE1B);
+ --! Notify access of Register 'UART_RXR'
+ select_uart_rxr : std_logic;
+ --! Notify access of Register 'UART_TXR'
+ select_uart_txr : std_logic;
+ end record;
+
+
+
+end system_map;
+
diff --git a/examples/ecp5_versa/uart.vhdl b/examples/ecp5_versa/uart.vhdl
new file mode 100644
index 0000000..c21ab49
--- /dev/null
+++ b/examples/ecp5_versa/uart.vhdl
@@ -0,0 +1,175 @@
+-- Simple UART core implementation
+--
+-- <hackfin@section5.ch>
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+ use work.system_map.all;
+
+entity uart_core is
+ generic (
+ FIFO_DEPTH : natural := 6;
+ -- Note: Currently ineffective. See library/wrappers/bram.v
+ SYN_RAMTYPE : string := "distributed"
+ );
+ port (
+ tx : out std_logic;
+ rx : in std_logic;
+ rxirq : out std_logic;
+ ctrl : in uart_WritePort;
+ stat : out uart_ReadPort;
+ clk : in std_logic
+ );
+
+end uart_core;
+
+architecture behaviour of uart_core is
+
+ signal count16 : unsigned(4-1 downto 0) := (others => '0');
+ signal counter : unsigned(16-1 downto 0) := (others => '0');
+
+ signal strobe_rx : std_logic;
+ signal rxd : unsigned(7 downto 0);
+ signal txd : unsigned(7 downto 0);
+
+ signal rxfifo_data : unsigned(7 downto 0);
+
+ signal rxfifo_rden : std_logic;
+ signal txfifo_wren : std_logic;
+
+ signal rxdata_ready : std_logic;
+
+ signal txfifo_dready : std_logic;
+ signal txfifo_strobe : std_logic;
+
+ signal clk16_enable : std_logic;
+ signal txclk_enable : std_logic;
+
+ component FifoBuffer is
+ generic (
+ ADDR_W : natural := 6;
+ DATA_W : natural := 16;
+ EXTRA_REGISTER : boolean := false;
+ SYN_RAMTYPE : string := "block_ram"
+ );
+ port (
+ -- Write enable
+ wren : in std_logic;
+ idata : in unsigned(DATA_W-1 downto 0);
+ iready : out std_logic;
+ -- Data stream output:
+ odata : out unsigned(DATA_W-1 downto 0);
+ oready : out std_logic;
+ rden : in std_logic;
+ err : out std_logic;
+ -- debug : out unsigned(16-1 downto 0);
+ reset : in std_logic;
+ clk : in std_logic
+ );
+ end component FifoBuffer;
+
+
+begin
+
+-- Clock divider:
+clkdiv:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ clk16_enable <= '0';
+ txclk_enable <= '0';
+ -- Important to reset, otherwise, the counter might run away...
+ if ctrl.uart_reset = '1' then
+ counter <= (others => '0');
+ elsif counter = ctrl.uart_clkdiv then
+ counter <= (others => '0');
+ clk16_enable <= '1';
+ count16 <= count16 + 1;
+ if count16 = "1111" then
+ txclk_enable <= '1';
+ end if;
+ else
+ counter <= counter + 1;
+ end if;
+ end if;
+ end process;
+
+ rxfifo_rden <= ctrl.select_uart_rxr and rxdata_ready;
+ txfifo_wren <= ctrl.select_uart_txr;
+
+uart_rx: entity work.UARTrx
+ port map (
+ d_bitcount => stat.bitcount,
+ rx => rx,
+ -- Data
+ err_frame => stat.frerr,
+ data => rxd,
+ strobe => strobe_rx,
+ reset => ctrl.uart_reset,
+ clk16en => clk16_enable,
+ clk => clk
+ );
+
+uart_tx:
+ entity work.UARTtx
+ port map (
+ busy => stat.txbusy,
+ data => txd,
+ data_ready => txfifo_dready,
+ data_out_en => txfifo_strobe,
+ tx => tx,
+ reset => ctrl.uart_reset,
+ txclken => txclk_enable,
+ clk => clk
+ );
+
+
+rxfifo:
+ FifoBuffer
+ generic map (
+ DATA_W => 8,
+ ADDR_W => FIFO_DEPTH,
+ SYN_RAMTYPE => SYN_RAMTYPE
+ )
+ port map (
+ wren => strobe_rx,
+ idata => rxd,
+ iready => open,
+ odata => rxfifo_data,
+ oready => rxdata_ready,
+ rden => rxfifo_rden,
+ err => stat.rxovr,
+ reset => ctrl.uart_reset,
+ clk => clk
+ );
+
+ stat.rxdata <= rxfifo_data;
+ stat.dvalid <= rxdata_ready;
+ stat.rxready <= rxdata_ready;
+ rxirq <= rxdata_ready and ctrl.rx_irq_enable;
+
+txfifo:
+ FifoBuffer
+ generic map (
+ DATA_W => 8,
+ ADDR_W => FIFO_DEPTH,
+ SYN_RAMTYPE => SYN_RAMTYPE
+ )
+ port map (
+ wren => txfifo_wren,
+ idata => ctrl.uart_txr,
+ iready => stat.txready,
+ odata => txd,
+ oready => txfifo_dready,
+ rden => txfifo_strobe,
+ err => stat.txovr,
+ reset => ctrl.uart_reset,
+ clk => clk
+ );
+
+end behaviour;
+
+
diff --git a/examples/ecp5_versa/uart_rx.vhdl b/examples/ecp5_versa/uart_rx.vhdl
new file mode 100644
index 0000000..e535b0b
--- /dev/null
+++ b/examples/ecp5_versa/uart_rx.vhdl
@@ -0,0 +1,204 @@
+-- UART RX implementation
+--
+-- (c) 06/2008, Martin Strubel <strubel@section5.ch>
+
+-- This module implements a standard UART receive channel.
+-- The clock divider has to be chosen such that the master clock
+-- divided by k = (2 * (div + 1)) is the 16 fold of the desired baud
+-- rate.
+
+-- On reception of a start bit, the lock counter is starting and the
+-- signal is sampled at the position of each lock marker which is at
+-- 'count' = 8 by default.
+
+-- Once a byte has arrived, it has to be read immediately by the
+-- client (FIFO assumed). Valid data must be clocked on rising edge of
+-- the 'strobe' pin from the 'data' bus.
+
+-- This is a very primitive implementation:
+-- * No Parity and other checks
+-- * No debouncing. Must be done on top level input.
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use ieee.numeric_std.all; -- for TO_UNSIGNED
+
+
+entity UARTrx is
+ generic (
+ CLKDIV2 : positive := 3 -- power of 2 of (clkdiv)
+ );
+ port (
+ d_bitcount : out unsigned(2 downto 0);
+
+ rx : in std_logic; -- RX UART
+ err_frame : out std_logic;
+ -- Data
+ data : out unsigned(7 downto 0);
+ strobe : out std_logic; -- Data valid strobe pulse
+ reset : in std_logic; -- Reset pin, LOW active
+ clk16en : in std_logic; -- UART clock enable
+ clk : in std_logic -- UART clock x 16
+ );
+
+end UARTrx;
+
+architecture behaviour of UARTrx is
+ -- State machine states:
+ -- IDLE: Waiting for start bit
+ -- START: Getting start bit
+ -- SHIFT: Shifting data
+ -- STOP: Getting stop bit ( No longer used, identical with S_IDLE )
+
+ type uart_state_t is (S_IDLE, S_START, S_SHIFT, S_STOP);
+
+ signal state : uart_state_t := S_IDLE;
+ signal rxd : std_logic;
+ signal frame_err : std_logic := '0'; -- Frame Error flag
+ signal rxtrigger : std_logic;
+ -- signal start : std_logic := '0';
+
+ signal strobeq : std_logic;
+ signal strobe_i : std_logic;
+
+ signal bitcount : unsigned(2 downto 0) := "000"; -- Bit counter
+ -- This is the clk counter that is used to synchronize to the
+ -- middle of a data bit signal
+ signal count : unsigned(CLKDIV2 downto 0) := (others => '0');
+ signal is_count_begin : std_logic; -- When count == 0
+ signal is_count_mid : std_logic; -- When count == 8
+ -- Shift register:
+ signal dsr : unsigned(7 downto 0) := x"00";
+
+begin
+
+ -- Detect RX start bit (synchronous to clk):
+rx_posedge:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if clk16en = '1' then
+ rxd <= rx;
+ rxtrigger <= rxd and (not rx);
+ end if;
+ end if;
+ end process;
+
+ -- This signal is:
+ -- HIGH on falling edge
+ -- LOW on rising edge, LOW when idle
+
+ -- It is not latched, thus it can be very short.
+
+
+generate_rxclk_en:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if clk16en = '1' then
+ case state is
+ when S_IDLE => count <= (others => '0');
+ when others => count <= count + 1;
+ end case;
+ end if;
+ end if;
+ end process;
+
+ is_count_begin <= '1' when count = "1111" else '0';
+ is_count_mid <= '1' when count = "0111" else '0';
+
+state_decode:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if reset = '1' then
+ state <= S_IDLE;
+ elsif clk16en = '1' then
+ case state is
+ when S_STOP | S_IDLE =>
+ if rxtrigger = '1' then
+ state <= S_START;
+ else
+ state <= S_IDLE;
+ end if;
+ when S_START =>
+ if is_count_begin = '1' then
+ state <= S_SHIFT;
+ end if;
+ when S_SHIFT =>
+ if is_count_begin = '1' and bitcount = "111" then
+ state <= S_STOP;
+ end if;
+ when others =>
+ state <= S_IDLE;
+ end case;
+ end if;
+ end if;
+ end process;
+
+shift:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if clk16en = '1' and is_count_mid = '1' then
+ if state = S_SHIFT then
+ dsr <= rx & dsr(7 downto 1);
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- Rising edge, when data valid
+ strobe_i <= '0' when state = S_SHIFT else '1';
+
+ -- From this, we generate a clk wide pulse:
+
+tx_strobe:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ strobeq <= strobe_i;
+ data <= dsr;
+ end if;
+ end process;
+
+ strobe <= not(strobeq) and strobe_i; -- Pulse on rising edge
+
+bitcounter:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if clk16en = '1' and is_count_begin = '1' then
+ case state is
+ when S_SHIFT =>
+ bitcount <= bitcount + 1;
+ when others =>
+ bitcount <= "000";
+ end case;
+ end if;
+ end if;
+ end process;
+
+-- Framing errors:
+detect_frerr:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if reset = '1' then
+ frame_err <= '0';
+ elsif state = S_STOP and is_count_mid = '1' and rx = '0' then
+ frame_err <= '1';
+ end if;
+ end if;
+ end process;
+
+
+
+ err_frame <= frame_err;
+
+ -- Debugging:
+ d_bitcount <= bitcount;
+
+end behaviour;
+
+
diff --git a/examples/ecp5_versa/uart_tx.vhdl b/examples/ecp5_versa/uart_tx.vhdl
new file mode 100644
index 0000000..b91fb66
--- /dev/null
+++ b/examples/ecp5_versa/uart_tx.vhdl
@@ -0,0 +1,125 @@
+-- UART TX implementation
+--
+-- (c) 2008 - 2015, Martin Strubel <strubel@section5.ch>
+--
+
+-- This implementation depends on an external FIFO that can be emptied
+-- as follows:
+-- When 'data_out_en' == 1 on rising edge of 'clk', 'data' is latched
+-- into the shift register and clocked out to the 'tx' pin. The FIFO
+-- increments its pointer and asserts the next data byte to 'data'.
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use ieee.numeric_std.all; -- for TO_UNSIGNED
+
+entity UARTtx is
+ port (
+ busy : out std_logic;
+ data : in unsigned(7 downto 0);
+ data_ready : in std_logic; -- Data in FIFO ready
+ data_out_en : out std_logic; -- Data out enable
+ tx : out std_logic; -- TX UART
+ reset : in std_logic; -- Reset pin, LOW active
+ txclken : in std_logic;
+ clk : in std_logic
+ );
+end UARTtx;
+
+architecture behaviour of UARTtx is
+
+ type uart_state_t is (S_IDLE, S_START, S_SHIFT, S_STOP);
+
+ signal state : uart_state_t := S_IDLE;
+ signal nextstate : uart_state_t;
+
+ -- Data Shift register:
+ signal dsr : unsigned(7 downto 0) := x"00";
+ signal bitcount : unsigned(2 downto 0) := "000"; -- Bit counter
+
+
+begin
+
+sync_state_advance:
+ process (clk)
+ begin
+ if falling_edge(clk) then
+ if txclken = '1' then
+ if reset = '1' then
+ state <= S_IDLE;
+ else
+ state <= nextstate;
+ end if;
+ end if;
+ end if;
+ end process;
+
+state_decode:
+ process (state, nextstate, bitcount, data_ready)
+ begin
+ case state is
+ when S_STOP =>
+ if data_ready = '1' then
+ nextstate <= S_START;
+ else
+ nextstate <= S_IDLE;
+ end if;
+ when S_IDLE =>
+ if data_ready = '1' then
+ nextstate <= S_START;
+ else
+ nextstate <= S_IDLE;
+ end if;
+ when S_START =>
+ nextstate <= S_SHIFT;
+ when S_SHIFT =>
+ if bitcount = "000" then
+ nextstate <= S_STOP;
+ else
+ nextstate <= S_SHIFT;
+ end if;
+ when others =>
+ nextstate <= S_IDLE;
+ end case;
+ end process;
+
+bitcounter:
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if txclken = '1' then
+ case state is
+ when S_SHIFT =>
+ bitcount <= bitcount + 1;
+ when others =>
+ bitcount <= "000";
+ end case;
+ end if;
+ end if;
+ end process;
+
+shift:
+ process (clk)
+ begin
+ if falling_edge(clk) then
+ data_out_en <= '0';
+ if txclken = '1' then
+ case state is
+ when S_START =>
+ dsr <= data;
+ data_out_en <= '1';
+ tx <= '0';
+ when S_SHIFT =>
+ dsr <= '1' & dsr(7 downto 1);
+ tx <= dsr(0);
+ when others =>
+ tx <= '1';
+ end case;
+ end if;
+ end if;
+ end process;
+
+ -- d_state <= std_logic_vector(TO_UNSIGNED(uart_state_t'pos(state), 4));
+ busy <= '1' when state /= S_IDLE else '0';
+
+end behaviour;
diff --git a/examples/ecp5_versa/versa_ecp5.lpf b/examples/ecp5_versa/versa_ecp5.lpf
new file mode 100644
index 0000000..f38d914
--- /dev/null
+++ b/examples/ecp5_versa/versa_ecp5.lpf
@@ -0,0 +1,122 @@
+FREQUENCY NET "clk_in" 100.000000 MHz ;
+IOBUF PORT "clk_in" IO_TYPE=LVDS DIFFRESISTOR=100 ;
+# FREQUENCY NET "clk_serdes_c" 156.250000 MHz ;
+IOBUF PORT "clk_serdes" IO_TYPE=LVDS DIFFRESISTOR=100 ;
+# On board oscillator:
+LOCATE COMP "clk_in" SITE "P3" ;
+LOCATE COMP "dip_sw[7]" SITE "K20" ;
+LOCATE COMP "dip_sw[6]" SITE "J19" ;
+LOCATE COMP "dip_sw[5]" SITE "K18" ;
+LOCATE COMP "dip_sw[4]" SITE "J18" ;
+LOCATE COMP "dip_sw[3]" SITE "F2" ;
+LOCATE COMP "dip_sw[2]" SITE "G3" ;
+LOCATE COMP "dip_sw[1]" SITE "K3" ;
+LOCATE COMP "dip_sw[0]" SITE "H2" ;
+# LED bank
+LOCATE COMP "oled[0]" SITE "E16" ;
+LOCATE COMP "oled[1]" SITE "D17" ;
+LOCATE COMP "oled[2]" SITE "D18" ;
+LOCATE COMP "oled[3]" SITE "E18" ;
+LOCATE COMP "oled[4]" SITE "F17" ;
+LOCATE COMP "oled[5]" SITE "F18" ;
+LOCATE COMP "oled[6]" SITE "E17" ;
+LOCATE COMP "oled[7]" SITE "F16" ;
+IOBUF PORT "oled[0]" ;
+IOBUF PORT "oled[1]" ;
+IOBUF PORT "oled[2]" ;
+IOBUF PORT "oled[3]" ;
+IOBUF PORT "oled[4]" ;
+IOBUF PORT "oled[5]" ;
+IOBUF PORT "oled[6]" ;
+IOBUF PORT "oled[7]" ;
+##################################################################
+LOCATE COMP "rxd_uart" SITE "C11" ;
+LOCATE COMP "txd_uart" SITE "A11" ;
+# Internal SPI port:
+LOCATE COMP "spi_mosi" SITE "W2" ;
+LOCATE COMP "spi_miso" SITE "V2" ;
+LOCATE COMP "spi_cs" SITE "R2" ;
+# 14 segment LED I/O
+LOCATE COMP "seg[0]" SITE "M20" ;
+LOCATE COMP "seg[1]" SITE "L18" ;
+LOCATE COMP "seg[2]" SITE "M19" ;
+LOCATE COMP "seg[3]" SITE "L16" ;
+LOCATE COMP "seg[4]" SITE "L17" ;
+LOCATE COMP "seg[5]" SITE "M18" ;
+LOCATE COMP "seg[6]" SITE "N16" ;
+LOCATE COMP "seg[7]" SITE "M17" ;
+LOCATE COMP "seg[8]" SITE "N18" ;
+LOCATE COMP "seg[9]" SITE "P17" ;
+LOCATE COMP "seg[10]" SITE "N17" ;
+LOCATE COMP "seg[11]" SITE "P16" ;
+LOCATE COMP "seg[12]" SITE "R16" ;
+LOCATE COMP "seg[13]" SITE "R17" ;
+LOCATE COMP "segdp" SITE "U1" ;
+IOBUF PORT "segdp" PULLMODE=NONE OPENDRAIN=OFF CLAMP=ON DRIVE=8 ;
+IOBUF PORT "seg[13]" ;
+IOBUF PORT "seg[12]" ;
+IOBUF PORT "seg[11]" ;
+IOBUF PORT "seg[10]" ;
+IOBUF PORT "seg[9]" ;
+IOBUF PORT "seg[8]" ;
+IOBUF PORT "seg[7]" ;
+IOBUF PORT "seg[6]" ;
+IOBUF PORT "seg[5]" ;
+IOBUF PORT "seg[4]" ;
+IOBUF PORT "seg[3]" ;
+IOBUF PORT "seg[2]" ;
+IOBUF PORT "seg[1]" ;
+IOBUF PORT "seg[0]" ;
+############################################################################
+# Ethernet
+#
+# Not connected:
+# LOCATE COMP "phy_clk125" SITE "L19" ;
+# LOCATE COMP "phy_rgmii_rxclk" SITE "L20" ;
+LOCATE COMP "phy_rgmii_rxctl" SITE "U19" ;
+LOCATE COMP "phy_rgmii_rxd[3]" SITE "R18" ;
+LOCATE COMP "phy_rgmii_rxd[2]" SITE "T19" ;
+LOCATE COMP "phy_rgmii_rxd[1]" SITE "U20" ;
+LOCATE COMP "phy_rgmii_rxd[0]" SITE "T20" ;
+LOCATE COMP "eth_rst_n" SITE "U17" ;
+LOCATE COMP "phy_rgmii_txclk" SITE "P19" ;
+LOCATE COMP "phy_rgmii_txctl" SITE "R20" ;
+LOCATE COMP "phy_rgmii_txd[3]" SITE "P20" ;
+LOCATE COMP "phy_rgmii_txd[2]" SITE "P18" ;
+LOCATE COMP "phy_rgmii_txd[1]" SITE "N20" ;
+LOCATE COMP "phy_rgmii_txd[0]" SITE "N19" ;
+LOCATE COMP "ts_mac_coremdc" SITE "T18" ;
+LOCATE COMP "ts_mac_coremdio" SITE "U18" ;
+LOCATE COMP "hw_config" SITE "T17" ;
+############################################################################
+# BLOCK JTAGPATHS ;
+# SYSCONFIG SLAVE_SPI_PORT=DISABLE CONFIG_MODE=JTAG CONFIG_SECURE=OFF TRANSFR=OFF MASTER_SPI_PORT=DISABLE SLAVE_PARALLEL_PORT=DISABLE MCCLK_FREQ=38.8 BACKGROUND_RECONFIG=OFF ;
+IOBUF PORT "spi_miso" IO_TYPE=LVCMOS25 ;
+IOBUF PORT "rxd_uart" IO_TYPE=LVCMOS33 ;
+IOBUF PORT "txd_uart" IO_TYPE=LVCMOS33 ;
+# BLOCK NET "soc/perio/rx_reset" ;
+# BLOCK NET "soc/perio/tx_reset" ;
+DEFINE PORT GROUP "rgmii_in" "phy_rgmii_rxctl"
+"phy_rgmii_rxd[3]"
+"phy_rgmii_rxd[2]"
+"phy_rgmii_rxd[1]"
+"phy_rgmii_rxd[0]" ;
+# FREQUENCY PORT "phy_rgmii_rxclk" 125.000000 MHz ;
+# INPUT_SETUP GROUP "rgmii_in"5.000000 ns CLKPORT "phy_rgmii_rxclk" ;
+LOCATE COMP "clk_serdes" SITE "A4" ;
+
+# JTAG pins:
+# LOCATE COMP "tck" SITE "T5" ;
+# LOCATE COMP "tdi" SITE "R5" ;
+# LOCATE COMP "tms" SITE "U5" ;
+# LOCATE COMP "tdo" SITE "V4" ;
+
+LOCATE COMP "reset_n" SITE "T1" ;
+# IOBUF PORT "reset_n" ;
+
+IOBUF PORT "tck" IO_TYPE=LVCMOS33 ;
+IOBUF PORT "tdi" IO_TYPE=LVCMOS33 ;
+IOBUF PORT "tms" IO_TYPE=LVCMOS33 ;
+
+# User code for rv32 TAP:
+USERCODE HEX "CAFE1050" ;
diff --git a/examples/ecp5_versa/versa_ecp5_top.vhdl b/examples/ecp5_versa/versa_ecp5_top.vhdl
new file mode 100644
index 0000000..a476390
--- /dev/null
+++ b/examples/ecp5_versa/versa_ecp5_top.vhdl
@@ -0,0 +1,162 @@
+--
+-- Versa ECP5(G) top level module
+--
+--
+-- 1/2017 Martin Strubel <hackfin@section5.ch>
+--
+-- Taken from MaSoCist and stripped down for the example.
+-- Functionality:
+
+-- * Blinks the first orange LED every second
+-- * Loops back the UART (fixed at 115200 bps) through a FIFO and
+-- turns lower cap alpha characters into upper case.
+
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library work;
+ use work.system_map.all;
+
+entity versa_ecp5_top is
+ generic(
+ CLK_FREQUENCY : positive := 25000000
+ );
+ port (
+ twi_scl : inout std_logic;
+ twi_sda : inout std_logic;
+
+ rxd_uart : in std_logic; -- FT2232 -> CPU
+ txd_uart : out std_logic; -- CPU -> FT2232
+
+ oled : out std_logic_vector(7 downto 0);
+ seg : out std_logic_vector(13 downto 0);
+ segdp : out std_logic;
+ dip_sw : in std_logic_vector(7 downto 0);
+
+ reset_n : in std_logic;
+ clk_in : in std_ulogic
+
+ );
+end entity versa_ecp5_top;
+
+
+architecture behaviour of versa_ecp5_top is
+
+ signal mclk : std_logic;
+ signal mclk_locked : std_logic;
+
+ -- Pixel clock:
+ signal pclk : std_logic;
+
+ signal comb_reset : std_logic;
+
+ constant f_half : integer := CLK_FREQUENCY / 2;
+ signal reset_delay : unsigned(3 downto 0);
+ signal led : unsigned(7 downto 0);
+ signal counter : integer range 0 to f_half;
+ signal toggle_led : std_ulogic := '0';
+
+ -- Uart signals:
+ signal uart_ctrl : uart_WritePort;
+ signal uart_stat : uart_ReadPort;
+
+ signal uart_idle : std_ulogic := '0';
+ signal rxready_d : std_ulogic := '0';
+ signal uart_data : unsigned(7 downto 0);
+
+
+begin
+
+ comb_reset <= (not reset_n) or (not mclk_locked);
+
+ seg <= (others => '1'); -- low active
+ segdp <= '1'; -- low active
+
+ process(mclk)
+ begin
+ if rising_edge(mclk) then
+ counter <= counter + 1;
+ if counter = f_half then
+ toggle_led <= not toggle_led;
+ counter <= 0;
+ end if;
+ end if;
+ end process;
+
+
+clk_pll1: entity work.pll_mac
+ port map (
+ CLKI => clk_in,
+ CLKOP => open,
+ CLKOS => mclk, -- 25 Mhz
+ CLKOS2 => open,
+ CLKOS3 => pclk,
+ LOCK => mclk_locked
+ );
+
+ -- Static config:
+ uart_ctrl.uart_clkdiv <= to_unsigned(CLK_FREQUENCY / 16 / 115200, 10);
+ uart_ctrl.rx_irq_enable <= '0';
+ uart_ctrl.uart_reset <= comb_reset;
+
+-- UART loopback logic:
+ process (mclk)
+ begin
+ if rising_edge(mclk) then
+ uart_ctrl.select_uart_txr <= '0'; -- default 0
+ uart_ctrl.select_uart_rxr <= '0'; -- default 0
+ rxready_d <= uart_stat.rxready;
+ if uart_idle = '1' then
+ uart_idle <= '0';
+ else
+ if rxready_d = '1' then
+ -- Modify the data a bit:
+ if uart_data > x"40" and uart_data < x"ff" then
+ uart_ctrl.uart_txr <= uart_data and "01011111";
+ else
+ uart_ctrl.uart_txr <= uart_data;
+ end if;
+ uart_ctrl.select_uart_txr <= '1'; -- signal a write
+ end if;
+ if uart_stat.rxready = '1' then
+ uart_data <= uart_stat.rxdata; -- Read data
+ uart_ctrl.select_uart_rxr <= '1'; -- signal a read
+ uart_idle <= '1'; -- Wait state
+ end if;
+ end if;
+ end if;
+ end process;
+
+uart_inst:
+ entity work.uart_core
+ port map (
+ tx => txd_uart,
+ rx => rxd_uart,
+ rxirq => open,
+ ctrl => uart_ctrl,
+ stat => uart_stat,
+ clk => mclk
+ );
+
+ led(0) <= toggle_led;
+ led(1) <= '0';
+ led(2) <= '1';
+ led(3) <= '0';
+ led(4) <= '0';
+ led(5) <= not rxd_uart;
+ led(6) <= '0';
+ led(7) <= uart_stat.rxovr;
+
+ -- Note LED are low active
+ oled <= not std_logic_vector(led);
+
+ twi_sda <= 'H';
+ twi_scl <= 'H';
+
+
+ -- txd_uart <= rxd_uart;
+
+
+end behaviour;
diff --git a/examples/ghdlsynth.mk b/examples/ghdlsynth.mk
new file mode 100644
index 0000000..d53a57c
--- /dev/null
+++ b/examples/ghdlsynth.mk
@@ -0,0 +1,34 @@
+# Common makefile for GHDL synthesis
+
+# Specify:
+#
+# VHDL_SYN_FILES = VHDL files for synthesis, unordered
+# VERILOG_FILES = auxiliary verilog wrappers that might be needed
+# PLATFORM: 'ecp5' for now
+# TOPLEVEL: top level entity name
+# TOPLEVEL_PARAMETER: top level entity name parameters, when passed a generic
+# LPF: I/O constraints file
+
+PLATFORM ?= ecp5
+
+ifneq ($(VERILOG_FILES),)
+MAYBE_READ_VERILOG = read_verilog $(VERILOG_FILES);
+endif
+
+%.json: $(VHDL_SYN_FILES)
+ $(YOSYS) -m $(GHDLSYNTH) -p \
+ "ghdl $(GHDL_FLAGS) $(GHDL_GENERICS) $^ -e $(TOPLEVEL); \
+ $(MAYBE_READ_VERILOG) \
+ synth_$(PLATFORM) \
+ -top $(TOPLEVEL)$(TOPLEVEL_PARAMETER) -json $@" 2>&1 | tee $*-report.txt
+
+%.config: %.json
+ $(NEXTPNR) --json $< --lpf $(LPF) \
+ --textcfg $@ $(NEXTPNR_FLAGS) --package $(PACKAGE)
+
+%.svf: %.config
+ $(ECPPACK) --svf $*.svf $< $@
+
+
+.PRECIOUS: %.json %.config
+