diff options
Diffstat (limited to 'testsuite/gna/bug019/PoC/src/io')
-rw-r--r-- | testsuite/gna/bug019/PoC/src/io/uart/uart.pkg.vhdl | 155 | ||||
-rw-r--r-- | testsuite/gna/bug019/PoC/src/io/uart/uart_bclk.vhdl | 108 | ||||
-rw-r--r-- | testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl | 320 | ||||
-rw-r--r-- | testsuite/gna/bug019/PoC/src/io/uart/uart_rx.vhdl | 174 | ||||
-rw-r--r-- | testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl | 140 |
5 files changed, 897 insertions, 0 deletions
diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart.pkg.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart.pkg.vhdl new file mode 100644 index 0000000..b5c3e9d --- /dev/null +++ b/testsuite/gna/bug019/PoC/src/io/uart/uart.pkg.vhdl @@ -0,0 +1,155 @@ +-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*- +-- vim: tabstop=2:shiftwidth=2:noexpandtab +-- kate: tab-width 2; replace-tabs off; indent-width 2; +-- +-- ============================================================================ +-- Authors: Martin Zabel +-- Patrick Lehmann +-- +-- Package: Component declarations for PoC.io.uart +-- +-- Description: +-- ------------------------------------ +-- TODO +-- +-- License: +-- ============================================================================ +-- Copyright 2008-2015 Technische Universitaet Dresden - Germany +-- Chair for VLSI-Design, Diagnostics and Architecture +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- ============================================================================ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library PoC; +use PoC.utils.all; +use PoC.physical.all; + + +package uart is + type T_IO_UART_FLOWCONTROL_KIND is ( + UART_FLOWCONTROL_NONE, + UART_FLOWCONTROL_XON_XOFF, + UART_FLOWCONTROL_RTS_CTS, + UART_FLOWCONTROL_RTR_CTS + ); + + constant C_IO_UART_TYPICAL_BAUDRATES : T_BAUDVEC := ( + 0 => 300 Bd, 1 => 600 Bd, 2 => 1200 Bd, 3 => 1800 Bd, 4 => 2400 Bd, + 5 => 4000 Bd, 6 => 4800 Bd, 7 => 7200 Bd, 8 => 9600 Bd, 9 => 14400 Bd, + 10 => 16000 Bd, 11 => 19200 Bd, 12 => 28800 Bd, 13 => 38400 BD, 14 => 51200 Bd, + 15 => 56000 Bd, 16 => 57600 Bd, 17 => 64000 Bd, 18 => 76800 Bd, 19 => 115200 Bd, + 20 => 128000 Bd, 21 => 153600 Bd, 22 => 230400 Bd, 23 => 250000 Bd, 24 => 256000 BD, + 25 => 460800 Bd, 26 => 500000 Bd, 27 => 576000 Bd, 28 => 921600 Bd + ); + + function io_UART_IsTypicalBaudRate(br : BAUD) return BOOLEAN; + + -- Bit clock generator + component uart_bclk is + generic ( + CLOCK_FREQ : FREQ := 100 MHz; + BAUDRATE : BAUD := 115200 Bd + ); + port ( + clk : in std_logic; + rst : in std_logic; + bclk_r : out std_logic; + bclk_x8_r : out std_logic + ); + end component; + + -- Transmitter + component uart_tx is + port ( + clk : in std_logic; + rst : in std_logic; + bclk_r : in std_logic; + stb : in std_logic; + din : in std_logic_vector(7 downto 0); + rdy : out std_logic; + txd : out std_logic + ); + end component; + + -- Receiver + component uart_rx is + generic ( + OUT_REGS : boolean + ); + port ( + clk : in std_logic; + rst : in std_logic; + bclk_x8_r : in std_logic; + rxd : in std_logic; + dos : out std_logic; + dout : out std_logic_vector(7 downto 0) + ); + end component; + + -- Wrappers + -- =========================================================================== + -- UART with FIFOs and optional flow control + component uart_fifo is + generic ( + CLOCK_FREQ : FREQ := 100 MHz; + BAUDRATE : BAUD := 115200 Bd; + FLOWCONTROL : T_IO_UART_FLOWCONTROL_KIND := UART_FLOWCONTROL_NONE; + TX_MIN_DEPTH : POSITIVE := 16; + TX_ESTATE_BITS : NATURAL := 1; + RX_MIN_DEPTH : POSITIVE := 16; + RX_FSTATE_BITS : NATURAL := 1; + RX_OUT_REGS : BOOLEAN := FALSE; + + SWFC_XON_CHAR : std_logic_vector(7 downto 0) := x"11"; -- ^Q + SWFC_XON_TRIGGER : real := 0.0625; + SWFC_XOFF_CHAR : std_logic_vector(7 downto 0) := x"13"; -- ^S + SWFC_XOFF_TRIGGER : real := 0.75 + ); + port ( + Clock : in std_logic; + Reset : in std_logic; + + -- FIFO interface + TX_put : in STD_LOGIC; + TX_Data : in STD_LOGIC_VECTOR(7 downto 0); + TX_Full : out STD_LOGIC; + TX_EmptyState : out STD_LOGIC_VECTOR(TX_ESTATE_BITS - 1 downto 0); + + RX_Valid : out STD_LOGIC; + RX_Data : out STD_LOGIC_VECTOR(7 downto 0); + RX_got : in STD_LOGIC; + RX_FullState : out STD_LOGIC_VECTOR(RX_FSTATE_BITS - 1 downto 0); + RX_Overflow : out std_logic; + + -- External Pins + UART_RX : in std_logic; + UART_TX : out std_logic + ); + end component; +end package; + + +package body uart is + function io_UART_IsTypicalBaudRate(br : BAUD) return BOOLEAN is + begin + for i in C_IO_UART_TYPICAL_BAUDRATES'range loop + next when (br /= C_IO_UART_TYPICAL_BAUDRATES(i)); + return TRUE; + end loop; + return FALSE; + end function; +end package body; diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_bclk.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_bclk.vhdl new file mode 100644 index 0000000..da26785 --- /dev/null +++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_bclk.vhdl @@ -0,0 +1,108 @@ +-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*- +-- vim: tabstop=2:shiftwidth=2:noexpandtab +-- kate: tab-width 2; replace-tabs off; indent-width 2; +-- +-- ============================================================================ +-- Authors: Martin Zabel +-- Patrick Lehmann +-- +-- Module: UART bit clock / baud rate generator +-- +-- Description: +-- ------------------------------------ +-- TODO +-- +-- old comments: +-- UART BAUD rate generator +-- bclk_r = bit clock is rising +-- bclk_x8_r = bit clock times 8 is rising +-- +-- +-- License: +-- ============================================================================ +-- Copyright 2008-2015 Technische Universitaet Dresden - Germany +-- Chair for VLSI-Design, Diagnostics and Architecture +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- ============================================================================ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library PoC; +use PoC.utils.all; +use PoC.strings.all; +use PoC.physical.all; +use PoC.components.all; +use PoC.uart.all; + + +entity uart_bclk is + generic ( + CLOCK_FREQ : FREQ := 100 MHz; + BAUDRATE : BAUD := 115200 Bd + ); + port ( + clk : in std_logic; + rst : in std_logic; + bclk : out std_logic; + bclk_x8 : out std_logic + ); +end entity; + + +architecture rtl of uart_bclk is + constant UART_OVERSAMPLING_RATE : POSITIVE := 8; + constant TIME_UNIT_INTERVAL : TIME := 1 sec / (to_real(BAUDRATE, 1 Bd) * real(UART_OVERSAMPLING_RATE)); + constant BAUDRATE_COUNTER_MAX : POSITIVE := TimingToCycles(TIME_UNIT_INTERVAL, CLOCK_FREQ); + constant BAUDRATE_COUNTER_BITS : POSITIVE := log2ceilnz(BAUDRATE_COUNTER_MAX + 1); + + -- registers + signal x8_cnt : unsigned(BAUDRATE_COUNTER_BITS - 1 downto 0) := (others => '0'); + signal x1_cnt : unsigned(2 downto 0) := (others => '0'); + + -- control signals + signal x8_cnt_done : std_logic; + signal x1_cnt_done : std_logic; + + signal bclk_r : STD_LOGIC := '0'; + signal bclk_x8_r : STD_LOGIC := '0'; +begin + assert FALSE -- LF works in QuartusII + report "uart_bclk:" & LF & + " CLOCK_FREQ=" & to_string(CLOCK_FREQ, 3) & LF & + " BAUDRATE=" & to_string(BAUDRATE, 3) & LF & + " COUNTER_MAX=" & INTEGER'image(BAUDRATE_COUNTER_MAX) & LF & + " COUNTER_BITS=" & INTEGER'image(BAUDRATE_COUNTER_BITS) + severity NOTE; + + assert io_UART_IsTypicalBaudRate(BAUDRATE) + report "The baudrate " & to_string(BAUDRATE, 3) & " is not known to be a typical baudrate!" + severity WARNING; + + x8_cnt <= upcounter_next(cnt => x8_cnt, rst => (rst or x8_cnt_done)) when rising_edge(clk); + x8_cnt_done <= upcounter_equal(cnt => x8_cnt, value => BAUDRATE_COUNTER_MAX - 1); + + x1_cnt <= upcounter_next(cnt => x1_cnt, rst => rst, en => x8_cnt_done) when rising_edge(clk); + x1_cnt_done <= comp_allzero(x1_cnt); + + -- outputs + -- --------------------------------------------------------------------------- + -- only x8_cnt_done is pulsed for one clock cycle! + bclk_r <= (x1_cnt_done and x8_cnt_done) when rising_edge(clk); + bclk_x8_r <= x8_cnt_done when rising_edge(clk); + + bclk <= bclk_r; + bclk_x8 <= bclk_x8_r; +end; diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl new file mode 100644 index 0000000..e1c1c9e --- /dev/null +++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl @@ -0,0 +1,320 @@ +-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*- +-- vim: tabstop=2:shiftwidth=2:noexpandtab +-- kate: tab-width 2; replace-tabs off; indent-width 2; +-- +-- ============================================================================ +-- Authors: Martin Zabel +-- Patrick Lehmann +-- +-- Module: UART Wrapper with Embedded FIFOs and Optional Flow Control +-- +-- Description: +-- ------------------------------------ +-- Small FIFOs are included in this module, if larger or asynchronous +-- transmit / receive FIFOs are required, then they must be connected +-- externally. +-- +-- old comments: +-- UART BAUD rate generator +-- bclk = bit clock is rising +-- bclk_x8 = bit clock times 8 is rising +-- +-- +-- License: +-- ============================================================================ +-- Copyright 2008-2015 Technische Universitaet Dresden - Germany +-- Chair for VLSI-Design, Diagnostics and Architecture +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- ============================================================================ + + +library IEEE; +use IEEE.std_logic_1164.all; + +library PoC; +use PoC.vectors.all; +use PoC.physical.all; +use PoC.components.all; +use PoC.uart.all; + + +entity uart_fifo is + generic ( + CLOCK_FREQ : FREQ := 100 MHz; + BAUDRATE : BAUD := 115200 Bd; + FLOWCONTROL : T_IO_UART_FLOWCONTROL_KIND := UART_FLOWCONTROL_NONE; + TX_MIN_DEPTH : POSITIVE := 16; + TX_ESTATE_BITS : NATURAL := 1; + RX_MIN_DEPTH : POSITIVE := 16; + RX_FSTATE_BITS : NATURAL := 1; + RX_OUT_REGS : BOOLEAN := FALSE; + ADD_INPUT_SYNCHRONIZERS : BOOLEAN := TRUE; + + SWFC_XON_CHAR : std_logic_vector(7 downto 0) := x"11"; -- ^Q + SWFC_XON_TRIGGER : real := 0.0625; + SWFC_XOFF_CHAR : std_logic_vector(7 downto 0) := x"13"; -- ^S + SWFC_XOFF_TRIGGER : real := 0.75 + ); + port ( + Clock : in std_logic; + Reset : in std_logic; + + -- FIFO interface + TX_put : in STD_LOGIC; + TX_Data : in STD_LOGIC_VECTOR(7 downto 0); + TX_Full : out STD_LOGIC; + TX_EmptyState : out STD_LOGIC_VECTOR(TX_ESTATE_BITS - 1 downto 0); + + RX_Valid : out STD_LOGIC; + RX_Data : out STD_LOGIC_VECTOR(7 downto 0); + RX_got : in STD_LOGIC; + RX_FullState : out STD_LOGIC_VECTOR(RX_FSTATE_BITS - 1 downto 0); + RX_Overflow : out std_logic; + + -- External pins + UART_TX : out std_logic; + UART_RX : in std_logic + ); +end entity; + + +architecture rtl of uart_fifo is + + signal FC_TX_Strobe : STD_LOGIC; + signal FC_TX_Data : T_SLV_8; + signal FC_TX_got : STD_LOGIC; + signal FC_RX_put : STD_LOGIC; + signal FC_RX_Data : T_SLV_8; + + signal TXFIFO_Valid : STD_LOGIC; + signal TXFIFO_Data : T_SLV_8; + + signal RXFIFO_Full : STD_LOGIC; + + signal TXUART_Ready : STD_LOGIC; + signal RXUART_Strobe : STD_LOGIC; + signal RXUART_Data : T_SLV_8; + + signal BitClock : STD_LOGIC; + signal BitClock_x8 : STD_LOGIC; + + signal UART_RX_sync : STD_LOGIC; + +begin + assert FALSE report "uart_fifo: BAUDRATE=: " & to_string(BAUDRATE, 3) severity NOTE; + + -- =========================================================================== + -- Transmit and Receive FIFOs + -- =========================================================================== + TXFIFO : entity PoC.fifo_cc_got + generic map ( + D_BITS => 8, -- Data Width + MIN_DEPTH => TX_MIN_DEPTH, -- Minimum FIFO Depth + DATA_REG => TRUE, -- Store Data Content in Registers + STATE_REG => FALSE, -- Registered Full/Empty Indicators + OUTPUT_REG => FALSE, -- Registered FIFO Output + ESTATE_WR_BITS => TX_ESTATE_BITS, -- Empty State Bits + FSTATE_RD_BITS => 0 -- Full State Bits + ) + port map ( + rst => Reset, + clk => Clock, + put => TX_put, + din => TX_Data, + full => TX_Full, + estate_wr => TX_EmptyState, + + valid => TXFIFO_Valid, + dout => TXFIFO_Data, + got => FC_TX_got, + fstate_rd => open + ); + + RXFIFO : entity PoC.fifo_cc_got + generic map ( + D_BITS => 8, -- Data Width + MIN_DEPTH => RX_MIN_DEPTH, -- Minimum FIFO Depth + DATA_REG => TRUE, -- Store Data Content in Registers + STATE_REG => FALSE, -- Registered Full/Empty Indicators + OUTPUT_REG => FALSE, -- Registered FIFO Output + ESTATE_WR_BITS => 0, -- Empty State Bits + FSTATE_RD_BITS => RX_FSTATE_BITS -- Full State Bits + ) + port map ( + rst => Reset, + clk => Clock, + put => FC_RX_put, + din => FC_RX_Data, + full => RXFIFO_Full, + estate_wr => open, + + valid => RX_Valid, + dout => RX_Data, + got => RX_got, + fstate_rd => RX_FullState + ); + + genNOFC : if (FLOWCONTROL = UART_FLOWCONTROL_NONE) generate + signal Overflow_r : std_logic := '0'; + begin + + FC_TX_Strobe <= TXFIFO_Valid and TXUART_Ready; + FC_TX_Data <= TXFIFO_Data; + FC_TX_got <= TXFIFO_Valid and TXUART_Ready; + + FC_RX_put <= RXUART_Strobe; + FC_RX_Data <= RXUART_Data; + + Overflow_r <= ffrs(q => Overflow_r, rst => Reset, set => (RXUART_Strobe and RXFIFO_Full)) when rising_edge(Clock); + + RX_Overflow <= Overflow_r; + end generate; + -- =========================================================================== + -- Software Flow Control + -- =========================================================================== + genSWFC : if (FLOWCONTROL = UART_FLOWCONTROL_XON_XOFF) generate + constant XON : std_logic_vector(7 downto 0) := x"11"; -- ^Q + constant XOFF : std_logic_vector(7 downto 0) := x"13"; -- ^S + + constant XON_TRIG : integer := integer(SWFC_XON_TRIGGER * real(2**RX_FSTATE_BITS)); + constant XOFF_TRIG : integer := integer(SWFC_XOFF_TRIGGER * real(2**RX_FSTATE_BITS)); + + signal send_xoff : std_logic; + signal send_xon : std_logic; + + signal set_xoff_transmitted : std_logic; + signal clr_xoff_transmitted : std_logic; + signal discard_user : std_logic; + + signal set_overflow : std_logic; + + -- registers + signal xoff_transmitted : std_logic; + + begin +-- -- send XOFF only once when fill state goes above trigger level +-- send_xoff <= (not xoff_transmitted) when (rf_fs >= XOFF_TRIG) else '0'; +-- set_xoff_transmitted <= tx_rdy when (rf_fs >= XOFF_TRIG) else '0'; +-- +-- -- send XON only once when receive FIFO is almost empty +-- send_xon <= xoff_transmitted when (rf_fs = XON_TRIG) else '0'; +-- clr_xoff_transmitted <= tx_rdy when (rf_fs = XON_TRIG) else '0'; +-- +-- -- discard any user supplied XON/XOFF +-- discard_user <= '1' when (tf_dout = SWFC_XON_CHAR) or (tf_dout = SWFC_XOFF_CHAR) else '0'; +-- +-- -- tx / tf control +-- tx_din <= SWFC_XOFF_CHAR when (send_xoff = '1') else +-- SWFC_XON_CHAR when (send_xon = '1') else +-- tf_dout; +-- +-- tx_stb <= send_xoff or send_xon or (tf_valid and (not discard_user)); +-- tf_got <= (send_xoff nor send_xon) and +-- tf_valid and tx_rdy; -- always check tf_valid +-- +-- -- rx / rf control +-- rf_put <= (not rf_full) and rx_dos; -- always check rf_full +-- rf_din <= rx_dout; +-- +-- set_overflow <= rf_full and rx_dos; +-- +-- -- registers +-- process (Clock) +-- begin -- process +-- if rising_edge(Clock) then +-- if (rst or set_xoff_transmitted) = '1' then +-- -- send a XON after reset +-- xoff_transmitted <= '1'; +-- elsif clr_xoff_transmitted = '1' then +-- xoff_transmitted <= '0'; +-- end if; +-- +-- if rst = '1' then +-- overflow <= '0'; +-- elsif set_overflow = '1' then +-- overflow <= '1'; +-- end if; +-- end if; +-- end process; + end generate; + -- =========================================================================== + -- Hardware Flow Control + -- =========================================================================== + genHWFC1 : if (FLOWCONTROL = UART_FLOWCONTROL_RTS_CTS) generate + + begin + + end generate; + -- =========================================================================== + -- Hardware Flow Control + -- =========================================================================== + genHWFC2 : if (FLOWCONTROL = UART_FLOWCONTROL_RTR_CTS) generate + + begin + + end generate; + + -- =========================================================================== + -- BitClock, Transmitter, Receiver + -- =========================================================================== + genNoSync : if (ADD_INPUT_SYNCHRONIZERS = FALSE) generate + UART_RX_sync <= UART_RX; + end generate; + genSync: if (ADD_INPUT_SYNCHRONIZERS = TRUE) generate + sync_i : entity PoC.sync_Bits + port map ( + Clock => Clock, -- Clock to be synchronized to + Input(0) => UART_RX, -- Data to be synchronized + Output(0) => UART_RX_sync -- synchronised data + ); + end generate; + -- =========================================================================== + -- BitClock, Transmitter, Receiver + -- =========================================================================== + bclk : entity PoC.uart_bclk + generic map ( + CLOCK_FREQ => CLOCK_FREQ, + BAUDRATE => BAUDRATE + ) + port map ( + clk => Clock, + rst => Reset, + bclk => BitClock, + bclk_x8 => BitClock_x8 + ); + + TX : entity PoC.uart_tx + port map ( + clk => Clock, + rst => Reset, + bclk => BitClock, + stb => FC_TX_Strobe, + din => FC_TX_Data, + rdy => TXUART_Ready, + txd => UART_TX + ); + + RX : entity PoC.uart_rx + generic map ( + OUT_REGS => RX_OUT_REGS + ) + port map ( + clk => Clock, + rst => Reset, + bclk_x8 => BitClock_x8, + dos => RXUART_Strobe, + dout => RXUART_Data, + rxd => UART_RX_sync + ); +end; diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_rx.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_rx.vhdl new file mode 100644 index 0000000..01383ba --- /dev/null +++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_rx.vhdl @@ -0,0 +1,174 @@ +-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*- +-- vim: tabstop=2:shiftwidth=2:noexpandtab +-- kate: tab-width 2; replace-tabs off; indent-width 2; +-- +-- ============================================================================ +-- Authors: Martin Zabel +-- Patrick Lehmann +-- +-- Module: UART Receiver +-- +-- Description: +-- ------------------------------------ +-- TODO +-- +-- old comments: +-- Serial configuration: 8 data bits, 1 stop bit, no parity +-- +-- bclk_x8 = bit clock (defined by BAUD rate) times 8 +-- dos = data out strobe, signals that dout is valid, active high for one +-- cycle +-- dout = data out = received byte +-- +-- OUT_REGS: +-- If disabled, then dos is a combinatorial output. Further merging of logic is +-- possible but timing constraints might fail. If enabled, 9 more registers are +-- required. But now, dout toggles only after receiving of full byte. +-- +-- +-- License: +-- ============================================================================ +-- Copyright 2008-2015 Technische Universitaet Dresden - Germany +-- Chair for VLSI-Design, Diagnostics and Architecture +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- ============================================================================ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library PoC; +use PoC.components.all; + + +entity uart_rx is + generic ( + OUT_REGS : boolean + ); + port ( + clk : in std_logic; + rst : in std_logic; + bclk_x8 : in std_logic; + rxd : in std_logic; + dos : out std_logic; + dout : out std_logic_vector(7 downto 0) + ); +end entity; + + +architecture rtl of uart_rx is + type states is (IDLE, RDATA); + signal state : states := IDLE; + signal next_state : states; + + -- registers + signal rxd_reg1 : std_logic := '1'; + signal rxd_reg2 : std_logic := '1'; + signal sr : std_logic_vector(7 downto 0) := (others => '0'); -- data only + signal bclk_cnt : unsigned(2 downto 0) := to_unsigned(4, 3); + signal shift_cnt : unsigned(3 downto 0) := (others => '0'); + + -- control signals + signal rxd_falling : std_logic; + signal bclk_rising : std_logic; + signal start_bclk : std_logic; + signal shift_sr : std_logic; + signal shift_done : std_logic; + signal put_data : std_logic; + +begin + + rxd_falling <= (not rxd_reg1) and rxd_reg2; + bclk_rising <= bclk_x8 when (comp_allone(bclk_cnt) = '1') else '0'; + + -- shift_cnt count from 0 to 9 (1 start bit + 8 data bits) + shift_cnt <= upcounter_next(cnt => shift_cnt, rst => start_bclk, en => shift_sr) when rising_edge(clk); + shift_done <= upcounter_equal(cnt => shift_cnt, value => 9); + + bclk_cnt <= upcounter_next(cnt => bclk_cnt, rst => start_bclk, en => bclk_x8, init => 4) when rising_edge(clk); + + process (state, rxd_falling, bclk_x8, bclk_rising, shift_done) + begin + next_state <= state; + start_bclk <= '0'; + shift_sr <= '0'; + put_data <= '0'; + + case state is + when IDLE => + -- wait for start bit + if (rxd_falling and bclk_x8) = '1' then + next_state <= RDATA; + start_bclk <= '1'; -- = rst_shift_cnt + end if; + + when RDATA => + if bclk_rising = '1' then + -- bit clock keeps running + if shift_done = '1' then + -- stop bit reached + put_data <= '1'; + next_state <= IDLE; + + else + -- TODO: check start bit? + shift_sr <= '1'; + end if; + end if; + + when others => null; + end case; + end process; + + process (clk) + begin + if rising_edge(clk) then + if rst = '1' then + state <= IDLE; + else + state <= next_state; + end if; + + rxd_reg1 <= rxd; + + if bclk_x8 = '1' then + -- align to bclk_x8, so when we can easily check for + -- the falling edge of the start bit + rxd_reg2 <= rxd_reg1; + end if; + + if shift_sr = '1' then + -- shift into MSB + sr <= rxd_reg2 & sr(sr'left downto 1); + end if; + end if; + end process; + + -- output + gOutRegs: if OUT_REGS = true generate + process (clk) + begin + if rising_edge(clk) then + dos <= put_data and rxd_reg2; -- check stop bit + dout <= sr; + end if; + end process; + end generate gOutRegs; + + gNoOutRegs: if OUT_REGS = false generate + dos <= put_data and rxd_reg2; -- check stop bit + dout <= sr; + end generate gNoOutRegs; + +end; diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl new file mode 100644 index 0000000..fe329fa --- /dev/null +++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl @@ -0,0 +1,140 @@ +-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*- +-- vim: tabstop=2:shiftwidth=2:noexpandtab +-- kate: tab-width 2; replace-tabs off; indent-width 2; +-- +-- ============================================================================ +-- Authors: Martin Zabel +-- Patrick Lehmann +-- +-- Module: UART Transmitter +-- +-- Description: +-- ------------------------------------ +-- TODO +-- +-- old comments: +-- Serial configuration: 8 data bits, 1 stop bit, no parity +-- +-- bclk = bit clk is rising +-- stb = strobe, i.e. transmit byte @ din +-- rdy = ready +-- +-- +-- License: +-- ============================================================================ +-- Copyright 2008-2015 Technische Universitaet Dresden - Germany +-- Chair for VLSI-Design, Diagnostics and Architecture +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- ============================================================================ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library PoC; +use PoC.components.all; + + +entity uart_tx is + port ( + clk : in std_logic; + rst : in std_logic; + bclk : in std_logic; + stb : in std_logic; + din : in std_logic_vector(7 downto 0); + rdy : out std_logic; + txd : out std_logic + ); +end entity; + + +architecture rtl of uart_tx is + type states is (IDLE, TDATA); + signal state : states := IDLE; + signal next_state : states; + + -- register + signal sr : std_logic_vector(9 downto 1) := (others => '0'); + signal sr0 : std_logic := '1'; -- current bit to transmit + signal shift_cnt : unsigned(3 downto 0) := (others => '0'); + signal shift_done : STD_LOGIC; + + -- control signals + signal start_tx : std_logic; + signal shift_sr : std_logic; + +begin + + process (state, stb, bclk, shift_done) + begin + next_state <= state; + start_tx <= '0'; + shift_sr <= '0'; + + case state is + when IDLE => + if stb = '1' then + -- start_tx triggers register initialization + start_tx <= '1'; + next_state <= TDATA; + end if; + + when TDATA => + if bclk = '1' then + -- also shift stop bit into sr0! + shift_sr <= '1'; + + if (shift_done = '1') then + -- condition is true at beginning of sending the stop-bit + -- synchronization to the bitclk ensures that stop-bit is + -- transmitted fully + next_state <= IDLE; + end if; + end if; + when others => null; + end case; + end process; + + process (clk) + begin + if rising_edge(clk) then + if rst = '1' then + state <= IDLE; + else + state <= next_state; + end if; + + if start_tx = '1' then + -- data, start bit + sr <= din & '0'; + elsif shift_sr = '1' then + sr <= '1' & sr(sr'left downto sr'right+1); + end if; + + if rst = '1' then + sr0 <= '1'; -- idle + elsif shift_sr = '1' then + sr0 <= sr(1); + end if; + end if; + end process; + + shift_cnt <= upcounter_next(cnt => shift_cnt, rst => start_tx, en => shift_sr) when rising_edge(clk); + shift_done <= upcounter_equal(cnt => shift_cnt, value => 9); + + -- outputs + txd <= sr0; + rdy <= '1' when state = IDLE else '0'; + +end; |