From 85a8de46f7f32c149d941414416996c55dd80e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 21 Nov 2017 22:11:53 +0100 Subject: [PATCH] add uart and top vhd --- .gitignore | 5 ++ top.vhd | 45 +++++++++++++++ uart_rx.vhd | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++ uart_tx.vhd | 110 +++++++++++++++++++++++++++++++++++ 4 files changed, 321 insertions(+) create mode 100644 .gitignore create mode 100644 top.vhd create mode 100644 uart_rx.vhd create mode 100644 uart_tx.vhd diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e5d6e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +#*# +*# +*.bak +*~ +.#* diff --git a/top.vhd b/top.vhd new file mode 100644 index 0000000..ba3ec0b --- /dev/null +++ b/top.vhd @@ -0,0 +1,45 @@ +------------------------------------------------------------------------------- +-- Title : MachXO2 Serial Configuration +-- Project : tiny-xo2 +------------------------------------------------------------------------------- +-- File : top.vhd +-- Author : マリオ +-- Company : +-- Created : 2017-11-21 +-- Last update: 2017-11-21 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: +------------------------------------------------------------------------------- +-- Copyright (c) 2017 GPLv2 +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity config_top is + + generic ( + BAUD_RATE : integer := 9600); + + port ( + clk : in std_logic; -- input clock 12 MHz + dts : in std_logic; -- DTS Strobe signal + uart_tx : out std_logic; -- UART TX + uart_rx : in std_logic); -- UART RX + +end entity config_top; + + +architecture RTL of config_top is + +begin -- architecture RTL + + + + + +end architecture RTL; diff --git a/uart_rx.vhd b/uart_rx.vhd new file mode 100644 index 0000000..4f388df --- /dev/null +++ b/uart_rx.vhd @@ -0,0 +1,161 @@ +-- -------------------------------------------------------------------------- -- +-- uart_rx.vhd: Basic UART (rx) +-- +-- Copyright (C) 2017 Markus Koch +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at http://mozilla.org/MPL/2.0/. +-- -------------------------------------------------------------------------- -- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity uart_rx is + port( + clk : in std_logic; + rst : in std_logic; + data : out std_logic_vector(7 downto 0); + byte_ready : out std_logic; + error : out std_logic; + + ckDiv : in std_logic_vector(15 downto 0); + parityEnable : in std_logic; + parityOdd : in std_logic; + twoStopBits : in std_logic; + + rx : in std_logic + ); +end entity uart_rx; + +architecture RTL of uart_rx is + constant SYNCH_COUNT : integer := 11; -- Min. 8 + constant BITCOUNT : integer := 8; + + type state_t is (SYNCH, IDLE, START, RECEIVE, PARITY, STOP); + + signal state : state_t; + signal clkDivider : unsigned(15 downto 0); + signal bitCounter : integer range 0 to SYNCH_COUNT; + signal data_i : std_logic_vector(7 downto 0); +-- signal rx_edge : std_logic; + signal parity_calc : std_logic; + signal rx_i : std_logic; + +begin + synchronizer_inst : entity work.synchronizer + generic map( + COUNT => 1 + ) + port map( + clk => clk, + rst => rst, + dIn(0) => rx, + dOut(0) => rx_i + ); + + -- edgeDetector_inst : entity work.edgeDetector + -- port map(clk => clk, + -- rst => rst, + -- sig => rx_i, + -- risingEdge => open, + -- fallingEdge => open, + -- anyEdge => rx_edge); + + rxFSM : process(clk, rst, parityOdd, ckDiv) is + begin + if rst = '1' then + state <= SYNCH; + bitCounter <= SYNCH_COUNT; + clkDivider <= unsigned(ckDiv); + error <= '0'; + parity_calc <= parityOdd; + data_i <= x"00"; + data <= x"00"; + byte_ready <= '0'; + elsif rising_edge(clk) then + byte_ready <= '0'; + error <= '0'; + if (clkDivider = 0) then + clkDivider <= unsigned(ckDiv); + else + clkDivider <= clkDivider - 1; + end if; + case state is + when SYNCH => -- Wait for 11 consecutive ones + if (clkDivider = to_unsigned(0, clkDivider'length)) then + if rx_i = '1' then + if bitCounter = 0 then + state <= IDLE; + else + bitCounter <= bitcounter - 1; + end if; + else + bitCounter <= SYNCH_COUNT; + end if; + end if; + when IDLE => -- Detect transition for sync + if rx_i = '0' then + state <= START; + clkDivider <= unsigned('0' & ckDiv(15 downto 1)); -- cMax_half. After that we are in the middle of the start bit + parity_calc <= parityOdd; + end if; + when START => + if (clkDivider = to_unsigned(0, clkDivider'length)) then + if rx_i = '0' then + state <= RECEIVE; + bitCounter <= 0; + else + report "uart_rx: START BIT ERROR" severity warning; + error <= '1'; + state <= SYNCH; + end if; + end if; + when RECEIVE => + if (clkDivider = to_unsigned(0, clkDivider'length)) then + data_i(bitCounter) <= rx_i; + if rx_i = '1' then + parity_calc <= not parity_calc; + end if; + if bitCounter = BITCOUNT - 1 then + bitCounter <= 0; + if parityEnable = '1' then + state <= PARITY; + else + state <= STOP; + end if; + else + bitCounter <= bitCounter + 1; + end if; + end if; + when PARITY => + if (clkDivider = to_unsigned(0, clkDivider'length)) then + if parity_calc = rx_i then + state <= STOP; + else + state <= SYNCH; + error <= '1'; + report "uart_rx: PARITY ERROR" severity warning; + end if; + end if; + when STOP => + if (clkDivider = to_unsigned(0, clkDivider'length)) then + if (rx_i = '1') then + bitCounter <= bitCounter + 1; + if bitCounter = 1 or twoStopBits = '0' then + state <= IDLE; + data <= data_i; + byte_ready <= '1'; + end if; + else + error <= '1'; + state <= SYNCH; + report "uart_rx: STOP BIT ERROR" severity warning; + end if; + end if; + end case; + end if; + end process rxFSM; + +end architecture RTL; diff --git a/uart_tx.vhd b/uart_tx.vhd new file mode 100644 index 0000000..e1b335f --- /dev/null +++ b/uart_tx.vhd @@ -0,0 +1,110 @@ +-- -------------------------------------------------------------------------- -- +-- uart_tx.vhd: Basic UART (tx) +-- +-- Copyright (C) 2017 Markus Koch +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at http://mozilla.org/MPL/2.0/. +-- -------------------------------------------------------------------------- -- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity uart_tx is + port( + clk : in std_logic; + rst : in std_logic; + data : in std_logic_vector(7 downto 0); + byte_ready : in std_logic; + busy : out std_logic; + + ckDiv : in std_logic_vector(15 downto 0); + parityEnable : in std_logic; + parityOdd : in std_logic; + twoStopBits : in std_logic; + + tx : out std_logic + ); +end entity uart_tx; + +architecture RTL of uart_tx is + type state_t is (IDLE, START, TRANSMIT, PARITY, STOP); + + signal state : state_t; + signal clkDivider : unsigned(15 downto 0); + signal data_i : std_logic_vector(7 downto 0); + signal bitCounter : integer range 0 to 7; + signal parity_calc : std_logic; + +begin + txFSM : process(clk, rst, ckDiv, parityOdd) is + begin + if rst = '1' then + data_i <= x"00"; + state <= IDLE; + tx <= '1'; + bitCounter <= 0; + busy <= '0'; + clkDivider <= unsigned(ckDiv); + parity_calc <= parityOdd; + elsif rising_edge(clk) then + busy <= '1'; + + if (clkDivider = 0) then + clkDivider <= unsigned(ckDiv); + else + clkDivider <= clkDivider - 1; + end if; + + case state is + when IDLE => + busy <= '0'; + tx <= '1'; + if byte_ready = '1' then + data_i <= data; + state <= START; + clkDivider <= unsigned(ckDiv); + bitCounter <= 0; + parity_calc <= '0'; + busy <= '1'; + tx <= '1'; + end if; + when START => + tx <= '0'; + state <= TRANSMIT; + when TRANSMIT => + if (clkDivider = to_unsigned(0, clkDivider'length)) then + tx <= data_i(bitCounter); + if data_i(bitCounter) = '1' then + parity_calc <= not parity_calc; + end if; + if bitCounter = 7 then + bitCounter <= 0; + if parityEnable = '1' then + state <= PARITY; + else + state <= STOP; + end if; + else + bitCounter <= bitCounter + 1; + end if; + end if; + when PARITY => + if (clkDivider = to_unsigned(0, clkDivider'length)) then + tx <= parity_calc; + state <= STOP; + end if; + when STOP => + if (clkDivider = to_unsigned(0, clkDivider'length)) then + tx <= '1'; + bitCounter <= bitCounter + 1; + if (bitCounter = 1 and twoStopBits = '0') or (bitCounter = 2 and twoStopBits = '1') then + state <= IDLE; + end if; + end if; + end case; + end if; + end process txFSM; +end architecture RTL;