diff options
Diffstat (limited to 'examples/icestick/uart')
| -rwxr-xr-x | examples/icestick/uart/README.md | 11 | ||||
| -rwxr-xr-x | examples/icestick/uart/hdl/uart_rx.vhd | 66 | ||||
| -rwxr-xr-x | examples/icestick/uart/hdl/uart_top.vhd | 49 | ||||
| -rwxr-xr-x | examples/icestick/uart/hdl/uart_tx.vhd | 62 | ||||
| -rwxr-xr-x | examples/icestick/uart/syn/constraints/uart.pcf | 6 | ||||
| -rwxr-xr-x | examples/icestick/uart/syn/synth.sh | 15 | 
6 files changed, 209 insertions, 0 deletions
| diff --git a/examples/icestick/uart/README.md b/examples/icestick/uart/README.md new file mode 100755 index 0000000..b53def6 --- /dev/null +++ b/examples/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/examples/icestick/uart/hdl/uart_rx.vhd b/examples/icestick/uart/hdl/uart_rx.vhd new file mode 100755 index 0000000..5f488cc --- /dev/null +++ b/examples/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/examples/icestick/uart/hdl/uart_top.vhd b/examples/icestick/uart/hdl/uart_top.vhd new file mode 100755 index 0000000..889a3a0 --- /dev/null +++ b/examples/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/examples/icestick/uart/hdl/uart_tx.vhd b/examples/icestick/uart/hdl/uart_tx.vhd new file mode 100755 index 0000000..b6c5800 --- /dev/null +++ b/examples/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/examples/icestick/uart/syn/constraints/uart.pcf b/examples/icestick/uart/syn/constraints/uart.pcf new file mode 100755 index 0000000..e3e5016 --- /dev/null +++ b/examples/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/examples/icestick/uart/syn/synth.sh b/examples/icestick/uart/syn/synth.sh new file mode 100755 index 0000000..884f1b6 --- /dev/null +++ b/examples/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 | 
