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;
|