w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
serport_uart_rx_tb.vhd
Go to the documentation of this file.
1-- $Id: serport_uart_rx_tb.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-- The uart expects CLKDIV+1 wide input bit symbols.
6-- This implementation counts the number of 1's in the first CLKDIV clock
7-- cycles, and checks in the last cycle of the symbol time whether the
8-- number of 1's was > CLKDIV/2. This supresses short glitches nicely,
9-- especially for larger clock dividers.
10--
11------------------------------------------------------------------------------
12-- Module Name: serport_uart_rx_tb - sim
13-- Description: serial port UART - receiver (SIM only!)
14--
15-- Dependencies: -
16-- Target Devices: generic
17-- Tool versions: ghdl 0.18-0.31
18-- Revision History:
19-- Date Rev Version Comment
20-- 2016-05-22 767 1.0.1 don't init N_REGS (vivado fix for fsm inference)
21-- 2016-01-03 724 1.0 Initial version (copied from serport_uart_rx)
22------------------------------------------------------------------------------
23
24library ieee;
25use ieee.std_logic_1164.all;
26use ieee.numeric_std.all;
27
28use work.slvtypes.all;
29
30entity serport_uart_rx_tb is -- serial port uart: receive part
31 generic (
32 CDWIDTH : positive := 13); -- clk divider width
33 port (
34 CLK : in slbit; -- clock
35 RESET : in slbit; -- reset
36 CLKDIV : in slv(CDWIDTH-1 downto 0); -- clock divider setting
37 RXSD : in slbit; -- receive serial data (uart view)
38 RXDATA : out slv8; -- receiver data out
39 RXVAL : out slbit; -- receiver data valid
40 RXERR : out slbit; -- receiver data error (frame error)
41 RXACT : out slbit -- receiver active
42 );
44
45
46architecture sim of serport_uart_rx_tb is
47
48 type state_type is (
49 s_idle, -- s_idle: idle
50 s_colb0, -- s_colb0: collect b0 (start bit)
51 s_endb0, -- s_endb0: finish b0 (start bit)
52 s_colbx, -- s_colbx: collect bx
53 s_endbx, -- s_endbx: finish bx
54 s_colb9, -- s_colb9: collect bx (stop bit)
55 s_endb9 -- s_endb9: finish bx (stop bit)
56 );
57
58 type regs_type is record
59 state : state_type; -- state
60 ccnt : slv(CDWIDTH-1 downto 0); -- clock divider counter
61 dcnt : slv(CDWIDTH downto 0); -- data '1' counter
62 bcnt : slv4; -- bit counter
63 sreg : slv8; -- input shift register
64 end record regs_type;
65
66 constant ccntzero : slv(CDWIDTH-1 downto 0) := (others=>'0');
67 constant dcntzero : slv(CDWIDTH downto 0) := (others=>'0');
68 constant regs_init : regs_type := (
69 s_idle, -- state
70 ccntzero, -- ccnt
71 dcntzero, -- dcnt
72 (others=>'0'), -- bcnt
73 (others=>'0') -- sreg
74 );
75
77 signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
78
79begin
80
81 proc_regs: process (CLK)
82 begin
83
84 if rising_edge(CLK) then
85 R_REGS <= N_REGS;
86 end if;
87
88 end process proc_regs;
89
90 proc_next: process (R_REGS, RESET, CLKDIV, RXSD)
91
92 variable r : regs_type := regs_init;
93 variable n : regs_type := regs_init;
94
95 variable dbit : slbit := '0';
96 variable ld_ccnt : slbit := '0';
97 variable tc_ccnt : slbit := '0';
98 variable tc_bcnt : slbit := '0';
99 variable ld_dcnt : slbit := '0';
100 variable ld_bcnt : slbit := '0';
101 variable ce_bcnt : slbit := '0';
102 variable iact : slbit := '0';
103 variable ival : slbit := '0';
104 variable ierr : slbit := '0';
105
106 begin
107
108 r := R_REGS;
109 n := R_REGS;
110
111 dbit := '0';
112 ld_ccnt := '0';
113 tc_ccnt := '0';
114 tc_bcnt := '0';
115 ld_dcnt := '0';
116 ld_bcnt := '0';
117 ce_bcnt := '0';
118 iact := '1';
119 ival := '0';
120 ierr := '0';
121
122 if unsigned(r.ccnt) = 0 then
123 tc_ccnt := '1';
124 end if;
125 if unsigned(r.bcnt) = 9 then
126 tc_bcnt := '1';
127 end if;
128
129 if unsigned(r.dcnt) > unsigned("00" & CLKDIV(CDWIDTH-1 downto 1)) then
130 dbit := '1';
131 end if;
132
133 case r.state is
134
135 when s_idle => -- s_idle: idle ----------------------
136 iact := '0';
137 ld_dcnt := '1'; -- always keep dcnt in reset
138 if RXSD = '0' then -- if start bit seen
139 if tc_ccnt = '1' then
140 n.state := s_endb0; -- finish b0
141 ld_ccnt := '1'; -- start next bit
142 ce_bcnt := '1';
143 else
144 n.state := s_colb0; -- collect b0
145 end if;
146 else -- otherwise
147 ld_ccnt := '1'; -- keep all counters in reset
148 ld_bcnt := '1';
149 end if;
150
151 when s_colb0 => -- s_colb0: collect b0 (start bit) ---
152 if tc_ccnt = '1' then -- last cycle of b0 ?
153 n.state := s_endb0; -- finish b0
154 ld_ccnt := '1'; -- "
155 ce_bcnt := '1';
156 else -- continue in b0 ?
157 if dbit='1' and RXSD='1' then -- too many 1's ?
158 n.state := s_idle; -- abort to idle
159 ld_dcnt := '1'; -- put counters in reset
160 ld_ccnt := '1';
161 ld_bcnt := '1';
162 end if;
163 end if;
164
165 when s_endb0 => -- s_endb0: finish b0 (start bit) ---
166 ld_dcnt := '1'; -- start next bit
167 if dbit = '1' then -- was it a 1 ?
168 n.state := s_idle; -- abort to idle
169 ld_ccnt := '1'; -- put counters in reset
170 ld_bcnt := '1';
171 else
172 if tc_ccnt = '1' then -- last cycle of bx ?
173 n.state := s_endbx; -- finish bx
174 ld_ccnt := '1';
175 ce_bcnt := '1';
176 else -- continue in b0 ?
177 n.state := s_colbx; -- collect bx
178 end if;
179 end if;
180
181 when s_colbx => -- s_colbx: collect bx ---------------
182 if tc_ccnt = '1' then -- last cycle of bx ?
183 n.state := s_endbx; -- finish bx
184 ld_ccnt := '1';
185 ce_bcnt := '1';
186 end if;
187
188 when s_endbx => -- s_endbx: finish bx ---------------
189 ld_dcnt := '1'; -- start next bit
190 n.sreg := dbit & r.sreg(7 downto 1);
191 if tc_ccnt = '1' then -- last cycle of bx ?
192 if tc_bcnt = '1' then
193 n.state := s_endb9; -- finish b9
194 ld_bcnt := '1'; -- and wrap bcnt
195 else
196 n.state := s_endbx; -- finish bx
197 ce_bcnt := '1';
198 end if;
199 ld_ccnt := '1';
200 else -- continue in bx ?
201 if tc_bcnt = '1' then
202 n.state := s_colb9; -- collect b9
203 else
204 n.state := s_colbx; -- collect bx
205 end if;
206 end if;
207
208 when s_colb9 => -- s_colb9: collect bx (stop bit) ----
209 if tc_ccnt = '1' then -- last cycle of b9 ?
210 n.state := s_endb9; -- finish b9
211 ld_ccnt := '1'; -- "
212 ld_bcnt := '1'; -- and wrap bcnt
213 else -- continue in b9 ?
214 if dbit='1' and RXSD='1' then -- already enough 1's ?
215 n.state := s_idle; -- finish to idle
216 ld_dcnt := '1'; -- put counters in reset
217 ld_ccnt := '1';
218 ld_bcnt := '1';
219 ival := '1';
220 end if;
221 end if;
222
223 when s_endb9 => -- s_endb9: finish bx (stop bit) ----
224 ld_dcnt := '1'; -- start next bit
225 if dbit = '1' then -- was it a valid stop bit ?
226 ival := '1';
227 else
228 ierr := '1';
229 end if;
230 if RXSD = '1' then -- line in idle state ?
231 n.state := s_idle; -- finish to idle state
232 ld_ccnt := '1'; -- and put counters in reset
233 ld_bcnt := '1'; -- "
234 else
235 if tc_ccnt = '1' then -- last cycle of b9 ?
236 n.state := s_endb0; -- finish b0
237 ld_ccnt := '1'; -- "
238 ce_bcnt := '1';
239 else -- continue in b0 ?
240 n.state := s_colb0; -- collect bx
241 end if;
242 end if;
243
244 when others => null; -- -----------------------------------
245
246 end case;
247
248 if RESET = '1' then -- RESET seen
249 ld_ccnt := '1'; -- keep all counters in reset
250 ld_dcnt := '1';
251 ld_bcnt := '1';
252 n.state := s_idle;
253 end if;
254
255 if ld_ccnt = '1' then -- implement ccnt
256 n.ccnt := CLKDIV;
257 else
258 n.ccnt := slv(unsigned(r.ccnt) - 1);
259 end if;
260
261 if ld_dcnt = '1' then -- implement dcnt
262 n.dcnt(CDWIDTH downto 1) := (others=>'0');
263 n.dcnt(0) := RXSD;
264 else
265 if RXSD = '1' then
266 n.dcnt := slv(unsigned(r.dcnt) + 1);
267 end if;
268 end if;
269
270 if ld_bcnt = '1' then -- implement bcnt
271 n.bcnt := (others=>'0');
272 else
273 if ce_bcnt = '1' then
274 n.bcnt := slv(unsigned(r.bcnt) + 1);
275 end if;
276 end if;
277
278 N_REGS <= n;
279
280 RXDATA <= r.sreg;
281 RXACT <= iact;
282 RXVAL <= ival;
283 RXERR <= ierr;
284
285 end process proc_next;
286
287end sim;
slv( CDWIDTH downto 0) :=( others => '0') dcntzero
regs_type := regs_init R_REGS
(s_idle,s_colb0,s_endb0,s_colbx,s_endbx,s_colb9,s_endb9) state_type
regs_type :=( s_idle, ccntzero, dcntzero,( others => '0'),( others => '0')) regs_init
slv( CDWIDTH- 1 downto 0) :=( others => '0') ccntzero
CDWIDTH positive := 13
in CLKDIV slv( CDWIDTH- 1 downto 0)
std_logic_vector( 3 downto 0) slv4
Definition: slvtypes.vhd:36
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector( 7 downto 0) slv8
Definition: slvtypes.vhd:40
std_logic_vector slv
Definition: slvtypes.vhd:31