From 4f3462be120ad924ae1f6df5cc59a2d0a87f459d Mon Sep 17 00:00:00 2001 From: marph91 <33229141+marph91@users.noreply.github.com> Date: Thu, 22 Aug 2019 20:45:38 +0200 Subject: Icestick uart (#37) * added UART example for the icestick * extended testsuite by the UART example --- icestick/uart/README.md | 11 ++++++ icestick/uart/hdl/uart_rx.vhd | 66 ++++++++++++++++++++++++++++++++++ icestick/uart/hdl/uart_top.vhd | 49 +++++++++++++++++++++++++ icestick/uart/hdl/uart_tx.vhd | 62 ++++++++++++++++++++++++++++++++ icestick/uart/syn/constraints/uart.pcf | 6 ++++ icestick/uart/syn/synth.sh | 15 ++++++++ 6 files changed, 209 insertions(+) create mode 100755 icestick/uart/README.md create mode 100755 icestick/uart/hdl/uart_rx.vhd create mode 100755 icestick/uart/hdl/uart_top.vhd create mode 100755 icestick/uart/hdl/uart_tx.vhd create mode 100755 icestick/uart/syn/constraints/uart.pcf create mode 100755 icestick/uart/syn/synth.sh (limited to 'icestick') 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 -- cgit v1.2.3