-
Notifications
You must be signed in to change notification settings - Fork 293
Expand file tree
/
Copy pathuart_rx.vhd
More file actions
125 lines (109 loc) · 3.4 KB
/
uart_rx.vhd
File metadata and controls
125 lines (109 loc) · 3.4 KB
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
-- 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/.
--
-- Copyright (c) 2014-2026, Lars Asplund lars.anders.asplund@gmail.com
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- pragma translate_off
library vunit_lib;
use vunit_lib.check_pkg.all;
use vunit_lib.logger_pkg.all;
-- pragma translate_on
entity uart_rx is
generic (
cycles_per_bit : natural := 434;
parity : natural := 0);
port (
clk : in std_logic;
-- Serial input bit
rx : in std_logic;
overflow : out std_logic := '0';
-- AXI stream for output bytes
tready : in std_logic;
tvalid : out std_Logic := '0';
tdata : out std_logic_vector(7 downto 0));
begin
-- pragma translate_off
check_stable(clk, check_enabled, tvalid, tready, tdata, "tdata must be stable until tready is active");
check_stable(clk, check_enabled, tvalid, tready, tvalid, "tvalid must be active until tready is active");
check_not_unknown(clk, check_enabled, tvalid, "tvalid must never be unknown");
check_not_unknown(clk, check_enabled, tready, "tready must never be unknown");
check_not_unknown(clk, check_enabled, rx, "rx must never be unknown");
traffic_logger: process (clk) is
begin
if tvalid = '1' and tready = '1' and rising_edge(clk) then
debug("Received " & to_string(to_integer(unsigned(tdata))));
end if;
end process traffic_logger;
-- pragma translate_on
end entity;
architecture a of uart_rx is
signal tvalid_int : std_logic := '0';
function data_size(
constant parity: natural
) return natural is
begin
if parity = 0 then
-- uart data (8 bits)
return 8;
elsif parity = 1 or parity = 2 then
-- uart data (8 bits)+ parity
return 9;
else
-- invalid mode
return 0;
end if;
end function data_size;
begin
main : process (clk)
type state_t is (idle, receiving, done);
variable state : state_t := idle;
variable datawidth : natural := data_size(parity);
variable cycles : natural range 0 to cycles_per_bit-1 := 0;
variable data : std_logic_vector(datawidth-1 downto 0);
variable index : natural range 0 to data'length-1 := 0;
begin
if rising_edge(clk) then
overflow <= '0';
case state is
when idle =>
if rx = '0' then
if cycles = cycles_per_bit/2 - 1 then
state := receiving;
cycles := 0;
index := 0;
else
cycles := cycles + 1;
end if;
else
cycles := 0;
end if;
when receiving =>
if cycles = cycles_per_bit - 1 then
data := rx & data(data'length-1 downto 1);
cycles := 0;
if index = data'length - 1 then
state := done;
else
index := index + 1;
end if;
else
cycles := cycles + 1;
end if;
when done =>
-- New output overwrites old output
overflow <= tvalid_int and not tready;
tvalid_int <= '1';
tdata <= data(7 downto 0);
state := idle;
end case;
-- output was read
if tvalid_int = '1' and tready = '1' then
tvalid_int <= '0';
end if;
end if;
end process;
tvalid <= tvalid_int;
end architecture;