w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
rbd_eyemon.vhd
Go to the documentation of this file.
1-- $Id: rbd_eyemon.vhd 1181 2019-07-08 17:00:50Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2010-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: rbd_eyemon - syn
7-- Description: rbus dev: eye monitor for serport's
8--
9-- Dependencies: memlib/ram_2swsr_wfirst_gen
10--
11-- Test bench: -
12--
13-- Target Devices: generic
14-- Tool versions: xst 12.1-14.7; viv 2014.4-2016.1; ghdl 0.29-0.33
15--
16-- Synthesized (xst):
17-- Date Rev ise Target flop lutl lutm slic t peri
18-- 2011-04-02 374 12.1 M53d xc3s1000-4 46 154 - 109 s 8.7
19-- 2010-12-27 349 12.1 M53d xc3s1000-4 45 147 - 106 s 8.9
20--
21-- Revision History:
22-- Date Rev Version Comment
23-- 2016-05-22 767 4.1.1 don't init N_REGS (vivado fix for fsm inference)
24-- 2014-09-13 593 4.1 no default rbus addess anymore, def=0
25-- 2014-08-15 583 4.0 rb_mreq addr now 16 bit
26-- 2011-11-19 427 1.0.3 now numeric_std clean
27-- 2011-04-02 375 1.0.2 handle back-to-back chars properly (in sim..)
28-- 2010-12-31 352 1.0.1 simplify irb_ack logic
29-- 2010-12-27 349 1.0 Initial version
30------------------------------------------------------------------------------
31--
32-- rbus registers:
33--
34-- Addr Bits Name r/w/f Function
35-- 00 cntl r/w/- Control register
36-- 03 ena01 r/w/- track 0->1 rxsd transitions
37-- 02 ena10 r/w/- track 1->0 rxsd transitions
38-- 01 clr r/-/f w: writing a 1 starts memory clear
39-- r: 1 indicates clr in progress (512 cyc)
40-- 00 go r/w/- enables monitor
41-- 01 7:00 rdiv r/w/- Sample rate divider
42-- 10 addr r/w/- Address register
43-- 9:01 laddr r/w/ line address
44-- 00 waddr r/w/ word address
45-- 11 15:00 data r/-/- Data register
46--
47-- data format:
48-- word 1 counter msb's
49-- word 0 counter lsb's
50--
51
52library ieee;
53use ieee.std_logic_1164.all;
54use ieee.numeric_std.all;
55
56use work.slvtypes.all;
57use work.memlib.all;
58use work.rblib.all;
59
60entity rbd_eyemon is -- rbus dev: eye monitor for serport's
61 generic (
62 RB_ADDR : slv16 := (others=>'0');
63 RDIV : slv8 := (others=>'0'));
64 port (
65 CLK : in slbit; -- clock
66 RESET : in slbit; -- reset
67 RB_MREQ : in rb_mreq_type; -- rbus: request
68 RB_SRES : out rb_sres_type; -- rbus: response
69 RXSD : in slbit; -- rx: serial data
70 RXACT : in slbit -- rx: active (start seen)
71 );
72end entity rbd_eyemon;
73
74
75architecture syn of rbd_eyemon is
76
77 constant rbaddr_cntl : slv2 := "00"; -- cntl address offset
78 constant rbaddr_rdiv : slv2 := "01"; -- rdiv address offset
79 constant rbaddr_addr : slv2 := "10"; -- addr address offset
80 constant rbaddr_data : slv2 := "11"; -- data address offset
81
82 constant cntl_rbf_ena01 : integer := 3;
83 constant cntl_rbf_ena10 : integer := 2;
84 constant cntl_rbf_clr : integer := 1;
85 constant cntl_rbf_go : integer := 0;
86 subtype addr_rbf_laddr is integer range 9 downto 1;
87 constant addr_rbf_waddr : integer := 0;
88
89 type state_type is (
90 s_idle, -- s_idle: wait for char or clr
91 s_char, -- s_char: processing a char
92 s_clr -- s_clr: clear memory
93 );
94
95 type regs_type is record -- state registers
96 state : state_type; -- state
97 rbsel : slbit; -- rbus select
98 go : slbit; -- go flag
99 clr : slbit; -- clear pending
100 ena10 : slbit; -- enable 1->0
101 ena01 : slbit; -- enable 0->1
102 rdiv : slv8; -- rate divider
103 laddr : slv9; -- line address
104 waddr : slbit; -- word address
105 laddr_1 : slv9; -- line address last cycle
106 rxsd_1 : slbit; -- rxsd last cycle
107 memwe : slbit; -- write bram (clr or inc)
108 memclr : slbit; -- write zero into bram
109 rdivcnt : slv8; -- rate divider counter
110 end record regs_type;
111
112 constant regs_init : regs_type := (
113 s_idle, -- state
114 '0', -- rbsel
115 '0', -- go (default is off)
116 '0','0','0', -- clr,ena01,ena10
117 (others=>'0'), -- rdiv
118 (others=>'0'), -- laddr
119 '0', -- waddr
120 (others=>'0'), -- laddr_1
121 '0','0','0', -- rxsd_1,memwe,memclr
122 (others=>'0') -- rdivcnt
123 );
124
126 signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
127
128 signal BRAM_ENA : slbit := '0';
129 signal BRAM_DIA : slv32 := (others=>'0');
130 signal BRAM_DIB : slv32 := (others=>'0');
131 signal BRAM_DOA : slv32 := (others=>'0');
132
133begin
134
135 BRAM_DIA <= (others=>'0'); -- always 0, no writes on this port
136
138 generic map (
139 AWIDTH => 9,
140 DWIDTH => 32)
141 port map (
142 CLKA => CLK,
143 CLKB => CLK,
144 ENA => BRAM_ENA,
145 ENB => R_REGS.memwe,
146 WEA => '0',
147 WEB => R_REGS.memwe,
148 ADDRA => R_REGS.laddr,
149 ADDRB => R_REGS.laddr_1,
150 DIA => BRAM_DIA,
151 DIB => BRAM_DIB,
152 DOA => BRAM_DOA,
153 DOB => open
154 );
155
156 proc_regs: process (CLK)
157 begin
158 if rising_edge(CLK) then
159 if RESET = '1' then
160 R_REGS <= regs_init;
161 else
162 R_REGS <= N_REGS;
163 end if;
164 end if;
165 end process proc_regs;
166
167 proc_next : process (R_REGS, RB_MREQ, RXSD, RXACT, BRAM_DOA)
168 variable r : regs_type := regs_init;
169 variable n : regs_type := regs_init;
170 variable irb_ack : slbit := '0';
171 variable irb_busy : slbit := '0';
172 variable irb_err : slbit := '0';
173 variable irb_dout : slv16 := (others=>'0');
174 variable irbena : slbit := '0';
175 variable ibramen : slbit := '0';
176 variable ibramdi : slv32 := (others=>'0');
177 variable laddr_we : slbit := '0';
178 variable laddr_clr : slbit := '0';
179 variable laddr_inc : slbit := '0';
180 begin
181
182 r := R_REGS;
183 n := R_REGS;
184
185 irb_ack := '0';
186 irb_busy := '0';
187 irb_err := '0';
188 irb_dout := (others=>'0');
189
190 irbena := RB_MREQ.re or RB_MREQ.we;
191
192 ibramen := '0';
193
194 laddr_we := '0';
195 laddr_clr := '0';
196 laddr_inc := '0';
197
198 -- rbus address decoder
199 n.rbsel := '0';
200 if RB_MREQ.aval='1' and RB_MREQ.addr(15 downto 2)=RB_ADDR(15 downto 2) then
201 n.rbsel := '1';
202 ibramen := '1';
203 end if;
204
205 -- rbus transactions
206 if r.rbsel = '1' then
207
208 irb_ack := irbena; -- ack all accesses
209
210 case RB_MREQ.addr(1 downto 0) is
211
212 when rbaddr_cntl =>
213 if RB_MREQ.we = '1' then
214 n.ena01 := RB_MREQ.din(cntl_rbf_ena01);
215 n.ena10 := RB_MREQ.din(cntl_rbf_ena10);
216 if RB_MREQ.din(cntl_rbf_clr) = '1' then
217 n.clr := '1';
218 end if;
219 n.go := RB_MREQ.din(cntl_rbf_go);
220 end if;
221
222 when rbaddr_rdiv =>
223 if RB_MREQ.we = '1' then
224 n.rdiv := RB_MREQ.din(n.rdiv'range);
225 end if;
226
227 when rbaddr_addr =>
228 if RB_MREQ.we = '1' then
229 laddr_we := '1';
230 n.waddr := RB_MREQ.din(addr_rbf_waddr);
231 end if;
232
233 when rbaddr_data =>
234 if RB_MREQ.we='1' then
235 irb_err := '1';
236 end if;
237 if RB_MREQ.re = '1' then
238 if r.go='0' and r.clr='0' and r.state=s_idle then
239 n.waddr := not r.waddr;
240 if r.waddr = '1' then
241 laddr_inc := '1';
242 end if;
243 else
244 irb_err := '1';
245 end if;
246 end if;
247
248 when others => null;
249 end case;
250 end if;
251
252 -- rbus output driver
253 if r.rbsel = '1' then
254 case RB_MREQ.addr(1 downto 0) is
255 when rbaddr_cntl =>
256 irb_dout(cntl_rbf_ena01) := r.ena01;
257 irb_dout(cntl_rbf_ena10) := r.ena10;
258 irb_dout(cntl_rbf_clr) := r.clr;
259 irb_dout(cntl_rbf_go) := r.go;
260 when rbaddr_rdiv =>
261 irb_dout(r.rdiv'range) := r.rdiv;
262 when rbaddr_addr =>
263 irb_dout(addr_rbf_laddr) := r.laddr;
264 irb_dout(addr_rbf_waddr) := r.waddr;
265 when rbaddr_data =>
266 case r.waddr is
267 when '1' => irb_dout := BRAM_DOA(31 downto 16);
268 when '0' => irb_dout := BRAM_DOA(15 downto 0);
269 when others => null;
270 end case;
271 when others => null;
272 end case;
273 end if;
274
275 -- eye monitor
276 n.memwe := '0';
277 n.memclr := '0';
278
279 case r.state is
280 when s_idle => -- s_idle: wait for char or clr ------
281 if r.clr = '1' then
282 laddr_clr := '1';
283 n.state := s_clr;
284 elsif r.go = '1' and RXSD='0' then
285 laddr_clr := '1';
286 n.rdivcnt := r.rdiv;
287 n.state := s_char;
288 end if;
289
290 when s_char => -- s_char: processing a char ---------
291 n.state := s_char; -- needed to prevent vivado iSTATE
292 if RXACT = '0' then -- uart went unactive
293 if RXSD = '1' then -- line idle -> to s_idle
294 n.state := s_idle;
295 else -- already next start bit seen
296 laddr_clr := '1'; -- clear and restart
297 n.rdivcnt := r.rdiv; -- happens only in simulation...
298 end if;
299 else
300 if (r.ena01='1' and r.rxsd_1='0' and RXSD='1') or
301 (r.ena10='1' and r.rxsd_1='1' and RXSD='0') then
302 n.memwe := '1';
303 ibramen := '1';
304 end if;
305 end if;
306 if unsigned(r.rdiv)=0 or unsigned(r.rdivcnt)=0 then
307 n.rdivcnt := r.rdiv;
308 if unsigned(r.laddr) /= (2**r.laddr'length)-1 then
309 laddr_inc := '1';
310 end if;
311 else
312 n.rdivcnt := slv(unsigned(r.rdivcnt) - 1);
313 end if;
314
315 when s_clr => -- s_clr: clear memory ---------------
316 laddr_inc := '1';
317 n.memwe := '1';
318 n.memclr := '1';
319 if unsigned(r.laddr) = (2**r.laddr'length)-1 then
320 n.clr := '0';
321 n.state := s_idle;
322 end if;
323
324 when others => null;
325 end case;
326
327 if laddr_we = '1' then
328 n.laddr := RB_MREQ.din(addr_rbf_laddr);
329 elsif laddr_clr = '1' then
330 n.laddr := (others=>'0');
331 elsif laddr_inc = '1' then
332 n.laddr := slv(unsigned(r.laddr) + 1);
333 end if;
334
335 n.laddr_1 := r.laddr;
336 n.rxsd_1 := RXSD;
337
338 ibramdi := (others=>'0');
339 if r.memclr = '0' then
340 ibramdi := slv(unsigned(BRAM_DOA) + 1);
341 end if;
342
343 N_REGS <= n;
344
345 BRAM_ENA <= ibramen;
346 BRAM_DIB <= ibramdi;
347
348 RB_SRES.dout <= irb_dout;
349 RB_SRES.ack <= irb_ack;
350 RB_SRES.err <= irb_err;
351 RB_SRES.busy <= irb_busy;
352
353 end process proc_next;
354
355end syn;
in DIA slv( DWIDTH- 1 downto 0)
in ADDRB slv( AWIDTH- 1 downto 0)
in ADDRA slv( AWIDTH- 1 downto 0)
out DOB slv( DWIDTH- 1 downto 0)
in DIB slv( DWIDTH- 1 downto 0)
out DOA slv( DWIDTH- 1 downto 0)
slv2 := "11" rbaddr_data
Definition: rbd_eyemon.vhd:80
slv32 :=( others => '0') BRAM_DIB
Definition: rbd_eyemon.vhd:130
regs_type :=( s_idle, '0', '0', '0', '0', '0',( others => '0'),( others => '0'), '0',( others => '0'), '0', '0', '0',( others => '0')) regs_init
Definition: rbd_eyemon.vhd:112
integer := 1 cntl_rbf_clr
Definition: rbd_eyemon.vhd:84
slv2 := "01" rbaddr_rdiv
Definition: rbd_eyemon.vhd:78
slv32 :=( others => '0') BRAM_DOA
Definition: rbd_eyemon.vhd:131
slv2 := "10" rbaddr_addr
Definition: rbd_eyemon.vhd:79
slbit := '0' BRAM_ENA
Definition: rbd_eyemon.vhd:128
slv2 := "00" rbaddr_cntl
Definition: rbd_eyemon.vhd:77
(s_idle,s_char,s_clr) state_type
Definition: rbd_eyemon.vhd:89
integer := 3 cntl_rbf_ena01
Definition: rbd_eyemon.vhd:82
regs_type := regs_init R_REGS
Definition: rbd_eyemon.vhd:125
regs_type N_REGS
Definition: rbd_eyemon.vhd:126
integer range 9 downto 1 addr_rbf_laddr
Definition: rbd_eyemon.vhd:86
integer := 2 cntl_rbf_ena10
Definition: rbd_eyemon.vhd:83
slv32 :=( others => '0') BRAM_DIA
Definition: rbd_eyemon.vhd:129
integer := 0 addr_rbf_waddr
Definition: rbd_eyemon.vhd:87
integer := 0 cntl_rbf_go
Definition: rbd_eyemon.vhd:85
in RESET slbit
Definition: rbd_eyemon.vhd:66
in RXSD slbit
Definition: rbd_eyemon.vhd:69
in CLK slbit
Definition: rbd_eyemon.vhd:65
in RXACT slbit
Definition: rbd_eyemon.vhd:71
in RB_MREQ rb_mreq_type
Definition: rbd_eyemon.vhd:67
RB_ADDR slv16 :=( others => '0')
Definition: rbd_eyemon.vhd:62
RDIV slv8 :=( others => '0')
Definition: rbd_eyemon.vhd:63
out RB_SRES rb_sres_type
Definition: rbd_eyemon.vhd:68
Definition: rblib.vhd:32
std_logic_vector( 8 downto 0) slv9
Definition: slvtypes.vhd:41
std_logic_vector( 31 downto 0) slv32
Definition: slvtypes.vhd:59
std_logic_vector( 15 downto 0) slv16
Definition: slvtypes.vhd:48
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector( 7 downto 0) slv8
Definition: slvtypes.vhd:40
std_logic_vector( 1 downto 0) slv2
Definition: slvtypes.vhd:34
std_logic_vector slv
Definition: slvtypes.vhd:31