summaryrefslogtreecommitdiff
path: root/testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl
blob: fe329faf912db003f45b58cdc81db5cf776ccc5a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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;