aboutsummaryrefslogtreecommitdiffstats
path: root/icestick
diff options
context:
space:
mode:
authormarph91 <33229141+marph91@users.noreply.github.com>2019-08-22 20:45:38 +0200
committertgingold <tgingold@users.noreply.github.com>2019-08-22 20:45:38 +0200
commit4f3462be120ad924ae1f6df5cc59a2d0a87f459d (patch)
tree417c4140740244f682671392d7660a86b05965c9 /icestick
parentd359d6deb55e5c51707c86263b090fabbc5c41b2 (diff)
downloadghdl-yosys-plugin-4f3462be120ad924ae1f6df5cc59a2d0a87f459d.tar.gz
ghdl-yosys-plugin-4f3462be120ad924ae1f6df5cc59a2d0a87f459d.tar.bz2
ghdl-yosys-plugin-4f3462be120ad924ae1f6df5cc59a2d0a87f459d.zip
Icestick uart (#37)
* added UART example for the icestick * extended testsuite by the UART example
Diffstat (limited to 'icestick')
-rwxr-xr-xicestick/uart/README.md11
-rwxr-xr-xicestick/uart/hdl/uart_rx.vhd66
-rwxr-xr-xicestick/uart/hdl/uart_top.vhd49
-rwxr-xr-xicestick/uart/hdl/uart_tx.vhd62
-rwxr-xr-xicestick/uart/syn/constraints/uart.pcf6
-rwxr-xr-xicestick/uart/syn/synth.sh15
6 files changed, 209 insertions, 0 deletions
diff --git a/icestick/uart/README.md b/icestick/uart/README.md
new file mode 100755
index 0000000..b53def6
--- /dev/null
+++ b/icestick/uart/README.md
@@ -0,0 +1,11 @@
+# icestick-uart
+Simple UART sender and receiver for the lattice icestick. It echoes every received word back.
+Configuration: 115200 8N1
+
+## Repository structure
+- hdl: Contains the hardware design.
+- syn: Contains the scripts and constraints for synthesis.
+
+## Usage
+- `cd syn && ./synth.sh`
+- configure and open putty or another serial terminal and type something \ No newline at end of file
diff --git a/icestick/uart/hdl/uart_rx.vhd b/icestick/uart/hdl/uart_rx.vhd
new file mode 100755
index 0000000..5f488cc
--- /dev/null
+++ b/icestick/uart/hdl/uart_rx.vhd
@@ -0,0 +1,66 @@
+library ieee;
+ use ieee.std_logic_1164.all;
+
+entity uart_rx is
+ generic (
+ C_BITS : integer := 8;
+ C_CYCLES_PER_BIT : integer := 104
+ );
+ port (
+ isl_clk : in std_logic;
+ isl_data_n : in std_logic;
+ oslv_data : out std_logic_vector(C_BITS-1 downto 0);
+ osl_valid : out std_logic
+ );
+end entity uart_rx;
+
+architecture rtl of uart_rx is
+ signal int_cycle_cnt : integer range 0 to C_CYCLES_PER_BIT-1 := 0;
+ signal int_bit_cnt : integer range 0 to C_BITS+1 := 0;
+
+ signal slv_data : std_logic_vector(C_BITS-1 downto 0) := (others => '0');
+ signal sl_valid : std_logic := '0';
+
+ type t_state is (IDLE, INIT, RECEIVE);
+ signal state : t_state;
+
+begin
+ process(isl_clk)
+ begin
+ if rising_edge(isl_clk) then
+ case state is
+ when IDLE =>
+ sl_valid <= '0';
+ if isl_data_n = '0' then
+ -- wait for the start bit
+ state <= INIT;
+ end if;
+
+ when INIT =>
+ int_cycle_cnt <= C_CYCLES_PER_BIT / 2;
+ int_bit_cnt <= 0;
+ state <= RECEIVE;
+
+ when RECEIVE =>
+ if int_bit_cnt < C_BITS+1 then
+ if int_cycle_cnt < C_CYCLES_PER_BIT-1 then
+ int_cycle_cnt <= int_cycle_cnt+1;
+ else
+ -- receive data bits
+ int_cycle_cnt <= 0;
+ int_bit_cnt <= int_bit_cnt+1;
+ slv_data <= not isl_data_n & slv_data(slv_data'LEFT downto 1); -- low active
+ end if;
+ elsif isl_data_n = '1' then
+ -- wait for the stop bit
+ sl_valid <= '1';
+ state <= IDLE;
+ end if;
+
+ end case;
+ end if;
+ end process;
+
+ oslv_data <= slv_data;
+ osl_valid <= sl_valid;
+end architecture rtl;
diff --git a/icestick/uart/hdl/uart_top.vhd b/icestick/uart/hdl/uart_top.vhd
new file mode 100755
index 0000000..889a3a0
--- /dev/null
+++ b/icestick/uart/hdl/uart_top.vhd
@@ -0,0 +1,49 @@
+library ieee;
+ use ieee.std_logic_1164.all;
+
+entity uart_top is
+ generic (
+ C_BITS : integer := 8
+ );
+ port (
+ isl_clk : in std_logic;
+ isl_data_n : in std_logic;
+ osl_data_n : out std_logic;
+ osl_ready : out std_logic
+ );
+end uart_top;
+
+architecture behavioral of uart_top is
+ constant C_QUARTZ_FREQ : integer := 12000000; -- Hz
+ constant C_BAUDRATE : integer := 115200; -- words / s
+ constant C_CYCLES_PER_BIT : integer := C_QUARTZ_FREQ / C_BAUDRATE;
+
+ signal sl_valid_out_tx : std_logic := '0';
+ signal slv_data_out_tx : std_logic_vector(C_BITS-1 downto 0) := (others => '0');
+
+begin
+ i_uart_rx: entity work.uart_rx
+ generic map (
+ C_BITS => C_BITS,
+ C_CYCLES_PER_BIT => C_CYCLES_PER_BIT
+ )
+ port map (
+ isl_clk => isl_clk,
+ isl_data_n => isl_data_n,
+ oslv_data => slv_data_out_tx,
+ osl_valid => sl_valid_out_tx
+ );
+
+ i_uart_tx: entity work.uart_tx
+ generic map (
+ C_BITS => C_BITS,
+ C_CYCLES_PER_BIT => C_CYCLES_PER_BIT
+ )
+ port map (
+ isl_clk => isl_clk,
+ isl_valid => sl_valid_out_tx,
+ islv_data => slv_data_out_tx,
+ osl_data_n => osl_data_n,
+ osl_ready => osl_ready
+ );
+end behavioral; \ No newline at end of file
diff --git a/icestick/uart/hdl/uart_tx.vhd b/icestick/uart/hdl/uart_tx.vhd
new file mode 100755
index 0000000..b6c5800
--- /dev/null
+++ b/icestick/uart/hdl/uart_tx.vhd
@@ -0,0 +1,62 @@
+library ieee;
+ use ieee.std_logic_1164.all;
+
+entity uart_tx is
+ generic (
+ -- TODO: range in submodules is not yet supported by synthesis
+ -- it would be useful to limit between 5 to 8
+ C_BITS : integer := 8;
+ C_CYCLES_PER_BIT : integer := 104
+ );
+ port (
+ isl_clk : in std_logic;
+ isl_valid : in std_logic;
+ islv_data : in std_logic_vector(C_BITS-1 downto 0);
+ osl_ready : out std_logic;
+ osl_data_n : out std_logic
+ );
+end entity uart_tx;
+
+architecture rtl of uart_tx is
+ signal int_cycle_cnt : integer range 0 to C_CYCLES_PER_BIT-1 := 0;
+ signal int_bit_cnt : integer range 0 to C_BITS+2 := 0;
+
+ signal slv_data : std_logic_vector(C_BITS downto 0) := (others => '0');
+
+ type t_state is (IDLE, INIT, SEND);
+ signal state : t_state;
+
+begin
+ process(isl_clk)
+ begin
+ if rising_edge(isl_clk) then
+ case state is
+ when IDLE =>
+ if isl_valid = '1' then
+ state <= INIT;
+ end if;
+
+ when INIT =>
+ int_cycle_cnt <= 0;
+ int_bit_cnt <= 0;
+ slv_data <= islv_data & '1';
+ state <= SEND;
+
+ when SEND =>
+ if int_cycle_cnt < C_CYCLES_PER_BIT-1 then
+ int_cycle_cnt <= int_cycle_cnt+1;
+ elsif int_bit_cnt < C_BITS+1 then
+ int_cycle_cnt <= 0;
+ int_bit_cnt <= int_bit_cnt+1;
+ slv_data <= '0' & slv_data(slv_data'LEFT downto 1);
+ else
+ state <= IDLE;
+ end if;
+
+ end case;
+ end if;
+ end process;
+
+ osl_ready <= '1' when state = IDLE else '0';
+ osl_data_n <= not slv_data(0); -- low active
+end architecture rtl; \ No newline at end of file
diff --git a/icestick/uart/syn/constraints/uart.pcf b/icestick/uart/syn/constraints/uart.pcf
new file mode 100755
index 0000000..e3e5016
--- /dev/null
+++ b/icestick/uart/syn/constraints/uart.pcf
@@ -0,0 +1,6 @@
+# FTDI Port B UART
+set_io osl_data_n 8 # UART TX
+set_io isl_data_n 9 # UART RX
+
+# 12 MHz clock
+set_io isl_clk 21
diff --git a/icestick/uart/syn/synth.sh b/icestick/uart/syn/synth.sh
new file mode 100755
index 0000000..884f1b6
--- /dev/null
+++ b/icestick/uart/syn/synth.sh
@@ -0,0 +1,15 @@
+set -e
+
+ROOT="$(pwd)/.."
+
+rm -rf build
+mkdir -p build
+cd build
+
+ghdl -a "$ROOT"/hdl/uart_rx.vhd
+ghdl -a "$ROOT"/hdl/uart_tx.vhd
+ghdl -a "$ROOT"/hdl/uart_top.vhd
+yosys -m ghdl -p 'ghdl uart_top; synth_ice40 -json uart_top.json'
+nextpnr-ice40 --hx1k --json uart_top.json --pcf ../constraints/uart.pcf --asc uart_top.asc --pcf-allow-unconstrained
+icepack uart_top.asc uart_top.bin
+iceprog uart_top.bin