w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
serport_uart_autobaud.vhd
Go to the documentation of this file.
1-- $Id: serport_uart_autobaud.vhd 1181 2019-07-08 17:00:50Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2007-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: serport_uart_autobaud - syn
7-- Description: serial port UART - autobauder
8--
9-- Dependencies: -
10-- Test bench: tb/tb_serport_autobaud
11-- Target Devices: generic
12-- Tool versions: ise 8.2-14.7; viv 2014.4-2016.2; ghdl 0.18-0.33
13-- Revision History:
14-- Date Rev Version Comment
15-- 2016-05-22 767 1.1.1 don't init N_REGS (vivado fix for fsm inference)
16-- 2015-02-01 641 1.1 add CLKDIV_F
17-- 2011-10-22 417 1.0.4 now numeric_std clean
18-- 2010-04-18 279 1.0.3 change ccnt start value to -3, better rounding
19-- 2007-10-14 89 1.0.2 all instantiation with CDINIT=0
20-- 2007-10-12 88 1.0.1 avoid ieee.std_logic_unsigned, use cast to unsigned
21-- 2007-06-30 62 1.0 Initial version
22------------------------------------------------------------------------------
23-- NOTE: for test bench usage a copy of all serport_* entities, with _tb
24-- !!!! appended to the name, has been created in the /tb sub folder.
25-- !!!! Ensure to update the copy when this file is changed !!
26
27library ieee;
28use ieee.std_logic_1164.all;
29use ieee.numeric_std.all;
30
31use work.slvtypes.all;
32
33entity serport_uart_autobaud is -- serial port uart: autobauder
34 generic (
35 CDWIDTH : positive := 13; -- clk divider width
36 CDINIT: natural := 15); -- clk divider initial/reset setting
37 port (
38 CLK : in slbit; -- clock
39 CE_MSEC : in slbit; -- 1 msec clock enable
40 RESET : in slbit; -- reset
41 RXSD : in slbit; -- receive serial data (uart view)
42 CLKDIV : out slv(CDWIDTH-1 downto 0); -- clock divider setting
43 CLKDIV_F: out slv3; -- clock divider fractional part
44 ACT : out slbit; -- active; if 1 clkdiv is invalid
45 DONE : out slbit -- resync done
46 );
48
49
50architecture syn of serport_uart_autobaud is
51
52 type state_type is (
53 s_idle,
54 s_break,
55 s_wait,
56 s_sync
57 );
58
59 type regs_type is record
60 ccnt : slv(CDWIDTH-1+3 downto 0); -- clock divider counter
61 mcnt : slv7; -- msec counter
62 seen1 : slbit; -- seen a '1' in this msec
63 state : state_type; -- state
64 end record regs_type;
65
66 -- Note on initialization of ccnt:
67 -- - in the current logic ccnt is incremented n-1 times when n is number
68 -- clock cycles with a RXD of '0'. When running at 50 MBaud, ccnt will
69 -- be incremented 7 (not 8!) times.
70 -- - the three LSBs of ccnt should be at 100 under perfect conditions, this
71 -- gives the best rounded estimate of CLKDIV.
72 -- - therefore ccnt is inititialized with 111111.101: 101 + 111 -> 1100
73 -- --> ccntinit = -3
74
75 constant ccntinit : slv(CDWIDTH-1+3 downto 0) :=
76 slv(to_unsigned(2**(CDWIDTH+3)-3, CDWIDTH+3));
77 constant mcntzero : slv7 := (others=>'0');
78 constant mcntlast : slv7 := (others=>'1');
79 constant regs_init : regs_type := (
80 slv(to_unsigned(CDINIT,CDWIDTH))&"000",
81 (others=>'0'),
82 '0',
83 s_idle
84 );
85
87 signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
88
89begin
90
91 assert CDINIT <= 2**CDWIDTH-1
92 report "assert(CDINIT <= 2**CDWIDTH-1): CDINIT too large for given CDWIDTH"
93 severity failure;
94
95 proc_regs: process (CLK)
96 begin
97
98 if rising_edge(CLK) then
99 if RESET = '1' then
100 R_REGS <= regs_init;
101 else
102 R_REGS <= N_REGS;
103 end if;
104 end if;
105
106 end process proc_regs;
107
108 proc_next: process (R_REGS, CE_MSEC, RESET, RXSD)
109
110 variable r : regs_type := regs_init;
111 variable n : regs_type := regs_init;
112
113 variable iact : slbit := '0';
114 variable idone : slbit := '0';
115
116 begin
117
118 r := R_REGS;
119 n := R_REGS;
120
121 iact := '1';
122 idone := '0';
123
124 case r.state is
125 when s_idle => -- s_idle: idle, detect break --------
126 iact := '0';
127 if CE_MSEC = '1' then -- if end of msec
128 if r.seen1 = '0' then -- if no '1' seen on RXD
129 n.mcnt := slv(unsigned(r.mcnt) + 1); -- up break timer counter
130 if r.mcnt = mcntlast then -- after 127 msec
131 n.state := s_break; -- break detected !
132 end if;
133 else -- otherwise if '1' seen
134 n.mcnt := mcntzero; -- clear break timer again
135 end if;
136 n.seen1 := RXSD; -- latch current RXD value
137 else -- otherwise if not at end-of-msec
138 n.seen1 := r.seen1 or RXSD; -- remember whether RXS=1 seen
139 end if;
140
141 when s_break => -- s_break: detect end of break ------
142 if RXSD = '1' then -- if end of break seen
143 n.state := s_wait; -- to s_wait to wait for sync char
144 n.ccnt := ccntinit; -- and initialize ccnt
145 end if; -- otherwise stay in s_break
146
147 when s_wait => -- s_wait: wait for sync char --------
148 if RXSD = '0' then -- if start bit if sync char seen
149 n.state := s_sync; -- to s_sync to wait for end of '0'
150 end if; -- otherwise stay in s_wait
151
152 when s_sync => -- s_sync: wait for end of '0' bits --
153 if RXSD = '1' then -- if end of '0' bits seen
154 n.state := s_idle; -- to s_idle, autobauding done
155 idone := '1'; -- emit done pulse
156 else -- otherwise still in '0' of sync
157 n.ccnt := slv(unsigned(n.ccnt) + 1); -- increment ccnt
158 end if;
159
160 when others => null; -- -----------------------------------
161 end case;
162
163 N_REGS <= n;
164
165 CLKDIV <= r.ccnt(CDWIDTH-1+3 downto 3);
166 CLKDIV_F <= r.ccnt(2 downto 0);
167 ACT <= iact or RESET;
168 DONE <= idone;
169
170 end process proc_next;
171
172end syn;
(s_idle,s_break,s_wait,s_sync) state_type
slv( CDWIDTH- 1+ 3 downto 0) := slv( to_unsigned( 2**( CDWIDTH+ 3)- 3, CDWIDTH+ 3) ) ccntinit
slv7 :=( others => '0') mcntzero
regs_type :=( slv( to_unsigned( CDINIT, CDWIDTH) )& "000",( others => '0'), '0', s_idle) regs_init
regs_type := regs_init R_REGS
slv7 :=( others => '1') mcntlast
out CLKDIV slv( CDWIDTH- 1 downto 0)
std_logic_vector( 6 downto 0) slv7
Definition: slvtypes.vhd:39
std_logic_vector( 2 downto 0) slv3
Definition: slvtypes.vhd:35
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector slv
Definition: slvtypes.vhd:31