w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
sysmon_rbus_core.vhd
Go to the documentation of this file.
1-- $Id: sysmon_rbus_core.vhd 1181 2019-07-08 17:00:50Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2016-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: sysmon_rbus_core - syn
7-- Description: SYSMON interface to rbus (generic)
8--
9-- Dependencies: -
10--
11-- Test bench: -
12--
13-- Target Devices: generic (all with SYSMON or XADC)
14-- Tool versions: viv 2015.4-2019.1; ghdl 0.33-0.35
15--
16-- Revision History:
17-- Date Rev Version Comment
18-- 2016-05-25 767 1.0.1 don't init N_REGS (vivado fix for fsm inference)
19-- BUGFIX: use s_init in regs_init (was s_idle)
20-- 2016-03-12 741 1.0 Initial version
21-- 2016-03-06 738 0.1 First draft
22------------------------------------------------------------------------------
23--
24-- rbus registers:
25-- - in general 1-to-1 mapping to sysmon/xadc address space
26-- --> see function in sysmon/xadc user guide
27-- - 8 addresses are implemented on the controller (base is ibase, default x"78")
28-- --> see function below
29--
30-- Addr Bits Name r/w/f Function
31-- 000 cntl -/-/f cntl
32-- 15 reset -/-/f reset SYSMON
33-- 001 stat r/w/- stat
34-- 3 jlock r/c/- JTAGLOCKED seen
35-- 2 jmod r/c/- JTAGMODIFIED seen
36-- 1 jbusy r/c/- JTAGBUSY seen
37-- 0 ot r/c/- OT seen
38-- 010 almh r/w/- alm history
39-- *:00 alm r/c/- ALM(*:0) seen
40-- 011 -/-/- <unused>
41-- 100 temp r/-/- current temp value
42-- 101 alm r/-/- current alm value
43-- *:00 alm r/-/- alm(*:0)
44-- 110 -/-/- <unused>
45-- 111 eos r/-/- eos counter
46--
47
48library ieee;
49use ieee.std_logic_1164.all;
50use ieee.numeric_std.all;
51
52use work.slvtypes.all;
53use work.rblib.all;
54use work.sysmonrbuslib.all;
55
56-- ----------------------------------------------------------------------------
57
58entity sysmon_rbus_core is -- SYSMON interface to rbus
59 generic (
60 DAWIDTH : positive := 7; -- drp address bus width
61 ALWIDTH : positive := 8; -- alm width
62 TEWIDTH : positive := 12; -- temp width
63 IBASE : slv8 := x"78"; -- base of controller register window
64 RB_ADDR : slv16 := x"fb00");
65 port (
66 CLK : in slbit; -- clock
67 RESET : in slbit := '0'; -- reset
68 RB_MREQ : in rb_mreq_type; -- rbus: request
69 RB_SRES : out rb_sres_type; -- rbus: response
70 SM_DEN : out slbit; -- sysmon: drp enable
71 SM_DWE : out slbit; -- sysmon: drp write enable
72 SM_DADDR : out slv(DAWIDTH-1 downto 0); -- sysmon: drp address
73 SM_DI : out slv16; -- sysmon: data input
74 SM_DO : in slv16; -- sysmon: data output
75 SM_DRDY : in slbit; -- sysmon: data ready
76 SM_EOS : in slbit; -- sysmon: end of scan
77 SM_RESET : out slbit; -- sysmon: reset
78 SM_ALM : in slv(ALWIDTH-1 downto 0);-- sysmon: alarms
79 SM_OT : in slbit; -- sysmon: overtemperature
80 SM_JTAGBUSY : in slbit; -- sysmon: JTAGBUSY
81 SM_JTAGLOCKED : in slbit; -- sysmon: JTAGLOCKED
82 SM_JTAGMODIFIED : in slbit; -- sysmon: JTAGMODIFIED
83 TEMP : out slv(TEWIDTH-1 downto 0) -- die temp
84 );
86
87architecture syn of sysmon_rbus_core is
88
89 type state_type is (
90 s_init, -- init: wait for jtaglocked down
91 s_idle, -- idle: dispatch
92 s_wait, -- wait: wait on drdy
93 s_twait -- twait: wait on drdy of temp read
94 );
95
96 type regs_type is record
97 rbsel : slbit; -- rbus select
98 state : state_type; -- state
99 eoscnt : slv16; -- eos counter
100 stat_ot : slbit; -- stat: ot
101 stat_jlock : slbit; -- stat: jtag locked
102 stat_jmod : slbit; -- stat: jtag modified
103 stat_jbusy : slbit; -- stat: jtag busy
104 almh : slv(ALWIDTH-1 downto 0); -- almh
105 temp : slv(TEWIDTH-1 downto 0); -- temp value
106 tpend : slbit; -- temp pending
107 end record regs_type;
108
109 constant regs_init : regs_type := (
110 '0', -- rbsel
111 s_init, -- state
112 (others=>'0'), -- eoscnt
113 '0','0','0','0', -- stat_ot, stat_j*
114 slv(to_unsigned(0,ALWIDTH)), -- almh
115 slv(to_unsigned(0,TEWIDTH)), -- temp
116 '0' -- tpend
117 );
118
119 signal R_REGS : regs_type := regs_init; -- state registers
120 signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
121
122 -- only internal regs have names, only 3 LSB in constant
123 constant rbaddr_cntl: slv3 := "000"; -- 0 -/-/f
124 constant rbaddr_stat: slv3 := "001"; -- 1 r/w/-
125 constant rbaddr_almh: slv3 := "010"; -- 2 r/w/-
126 constant rbaddr_temp: slv3 := "100"; -- 4 r/-/-
127 constant rbaddr_alm: slv3 := "101"; -- 5 r/-/-
128 constant rbaddr_eos: slv3 := "111"; -- 7 r/-/-
129
130 constant cntl_rbf_reset: integer := 15;
131
132 constant stat_rbf_jlock: integer := 3;
133 constant stat_rbf_jmod: integer := 2;
134 constant stat_rbf_jbusy: integer := 1;
135 constant stat_rbf_ot: integer := 0;
136
137begin
138
139 assert DAWIDTH=7 or DAWIDTH=8
140 report "assert(DAWIDTH=7 or DAWIDTH=8): unsupported DAWIDTH"
141 severity failure;
142 assert ALWIDTH<=16
143 report "assert ALWIDTH<16: unsupported ALWIDTH"
144 severity failure;
145 assert TEWIDTH=10 or TEWIDTH=12
146 report "assert(TEWIDTH=10 or TEWIDTH=12): unsupported TEWIDTH"
147 severity failure;
148 assert IBASE(2 downto 0) = "000"
149 report "assert IBASE(2:0) = 000: invalid IBASE"
150 severity failure;
151
152 proc_regs: process (CLK)
153 begin
154
155 if rising_edge(CLK) then
156 if RESET = '1' then
157 R_REGS <= regs_init;
158 else
159 R_REGS <= N_REGS;
160 end if;
161 end if;
162
163 end process proc_regs;
164
165 proc_next: process (R_REGS, RB_MREQ, SM_DO, SM_DRDY, SM_EOS, SM_ALM, SM_OT,
167
168 variable r : regs_type := regs_init;
169 variable n : regs_type := regs_init;
170
171 variable irb_ack : slbit := '0';
172 variable irb_busy : slbit := '0';
173 variable irb_err : slbit := '0';
174 variable irb_dout : slv16 := (others=>'0');
175 variable irbena : slbit := '0';
176
177 variable irb_addr_ext : slbit := '0';
178 variable irb_addr_int : slbit := '0';
179
180 variable ism_den : slbit := '0';
181 variable ism_dwe : slbit := '0';
182 variable ism_daddr : slv(DAWIDTH-1 downto 0) := (others=>'0');
183 variable ism_reset : slbit := '0';
184
185 begin
186
187 r := R_REGS;
188 n := R_REGS;
189
190 irb_ack := '0';
191 irb_busy := '0';
192 irb_err := '0';
193 irb_dout := (others=>'0');
194
195 irbena := RB_MREQ.re or RB_MREQ.we;
196
197 -- check for internal rbus controller register window
198 irb_addr_int := '0';
199 if RB_MREQ.addr(DAWIDTH-1 downto 3) = IBASE(DAWIDTH-1 downto 3) then
200 irb_addr_int := '1';
201 end if;
202
203 ism_den := '0';
204 ism_dwe := '0';
205 ism_daddr := RB_MREQ.addr(DAWIDTH-1 downto 0); -- default
206 ism_reset := '0';
207
208 -- handle EOS
209 if SM_EOS = '1' then
210 n.tpend := '1'; -- queue temp read
211 n.eoscnt := slv(unsigned(r.eoscnt) + 1); -- and count it
212 end if;
213
214 -- update stat and almh register fields
215 n.stat_ot := r.stat_ot or SM_OT;
216 n.stat_jlock := r.stat_jlock or SM_JTAGLOCKED;
217 n.stat_jmod := r.stat_jmod or SM_JTAGMODIFIED;
218 n.stat_jbusy := r.stat_jbusy or SM_JTAGBUSY;
219 n.almh := r.almh or SM_ALM;
220
221 -- rbus address decoder
222 n.rbsel := '0';
223 if RB_MREQ.aval='1' and RB_MREQ.addr(15 downto 7)=RB_ADDR(15 downto 7) then
224 n.rbsel := '1';
225 end if;
226
227 irb_ack := r.rbsel and irbena; -- ack all accesses
228 irb_busy := irb_ack; -- busy is default
229
230 -- internal state machine
231 case r.state is
232 when s_init => -- init: wait for jtaglocked down ----
233 if SM_JTAGLOCKED = '0' then
234 n.stat_jlock := '0'; -- clear status
235 n.state := s_idle; -- start working
236 end if;
237
238 when s_idle => -- idle: dispatch --------------------
239 if r.tpend = '1' then -- temp update pending ?
240 n.tpend := '0'; -- mark done
241 if SM_JTAGLOCKED = '0' then -- if not jlocked
242 ism_daddr := "0000000"; -- temp is reg 00h
243 ism_dwe := '0'; -- do read
244 ism_den := '1'; -- start drp cycle
245 n.state := s_twait;
246 end if;
247
248 elsif r.rbsel = '1' then -- rbus access ?
249 if irb_addr_int ='1' then -- internal controller regs
250 irb_busy := '0';
251 case RB_MREQ.addr(2 downto 0) is
252 when rbaddr_cntl =>
253 if RB_MREQ.we = '1' then
254 ism_reset := RB_MREQ.din(cntl_rbf_reset);
255 end if;
256
257 when rbaddr_stat =>
258 if RB_MREQ.we = '1' then
259 n.stat_jlock := r.stat_jlock and
260 not RB_MREQ.din(stat_rbf_jlock);
261 n.stat_jmod := r.stat_jmod and
262 not RB_MREQ.din(stat_rbf_jmod);
263 n.stat_jbusy := r.stat_jbusy and
264 not RB_MREQ.din(stat_rbf_jbusy);
265 n.stat_ot := r.stat_ot and
266 not RB_MREQ.din(stat_rbf_ot);
267 end if;
268
269 when rbaddr_almh =>
270 if RB_MREQ.we = '1' then
271 n.almh := r.almh and not RB_MREQ.din(r.almh'range);
272 end if;
273
274 when rbaddr_temp =>
275 irb_err := RB_MREQ.we;
276 when rbaddr_alm =>
277 irb_err := RB_MREQ.we;
278 when rbaddr_eos =>
279 irb_err := RB_MREQ.we;
280
281 when others =>
282 irb_err := irbena;
283 end case;
284
285 else -- sysmon reg access
286 if irbena = '1' then
287 if SM_JTAGLOCKED = '0' then -- if not jlocked
288 ism_daddr := RB_MREQ.addr(ism_daddr'range);
289 ism_dwe := RB_MREQ.we;
290 ism_den := '1'; -- start drp cycle
291 n.state := s_wait;
292 else
293 irb_err := '1'; -- quit with error if jlocked
294 end if;
295 end if;
296
297 end if;
298 end if;
299
300 when s_wait => -- wait: wait on drdy ----------------
301 n.state := s_wait;
302 if SM_DRDY = '1' then
303 irb_busy := '0';
304 n.state := s_idle;
305 end if;
306
307 when s_twait => -- twait: wait on drdy of temp read --
308 n.state := s_twait;
309 if SM_DRDY = '1' then
310 n.temp := SM_DO(15 downto 16-TEWIDTH); -- take msb's
311 n.state := s_idle;
312 end if;
313
314 when others => null; -- <> ------------------------------
315 end case; -- case r.state
316
317 -- rbus output driver
318 if r.rbsel = '1' then
319 if irb_addr_int = '1' then
320 case RB_MREQ.addr(2 downto 0) is
321 when rbaddr_stat =>
322 irb_dout(stat_rbf_jlock) := r.stat_jlock;
323 irb_dout(stat_rbf_jmod) := r.stat_jmod;
324 irb_dout(stat_rbf_jbusy) := r.stat_jbusy;
325 irb_dout(stat_rbf_ot) := r.stat_ot;
326
327 when rbaddr_almh =>
328 irb_dout(r.almh'range) := r.almh;
329
330 when rbaddr_temp =>
331 irb_dout(r.temp'range) := r.temp;
332
333 when rbaddr_alm =>
334 irb_dout(SM_ALM'range) := SM_ALM;
335
336 when rbaddr_eos =>
337 irb_dout := r.eoscnt;
338
339 when others =>
340 irb_dout := (others=>'0');
341 end case;
342 else
343 irb_dout := SM_DO;
344 end if;
345 end if;
346
347 N_REGS <= n;
348
349 SM_DEN <= ism_den;
350 SM_DWE <= ism_dwe;
351 SM_DADDR <= ism_daddr;
352 SM_DI <= RB_MREQ.din;
353 SM_RESET <= ism_reset;
354
355 TEMP <= r.temp;
356
357 RB_SRES <= rb_sres_init;
358 RB_SRES.ack <= irb_ack;
359 RB_SRES.busy <= irb_busy;
360 RB_SRES.err <= irb_err;
361 RB_SRES.dout <= irb_dout;
362
363 end process proc_next;
364
365end syn;
Definition: rblib.vhd:32
std_logic_vector( 2 downto 0) slv3
Definition: slvtypes.vhd:35
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 slv
Definition: slvtypes.vhd:31
(s_init,s_idle,s_wait,s_twait) state_type
integer := 15 cntl_rbf_reset
regs_type := regs_init R_REGS
regs_type :=( '0', s_init,( others => '0'), '0', '0', '0', '0', slv( to_unsigned( 0, ALWIDTH) ), slv( to_unsigned( 0, TEWIDTH) ), '0') regs_init
TEWIDTH positive := 12
out SM_DADDR slv( DAWIDTH- 1 downto 0)
RB_ADDR slv16 := x"fb00"
in RB_MREQ rb_mreq_type
in SM_JTAGMODIFIED slbit
DAWIDTH positive := 7
in SM_ALM slv( ALWIDTH- 1 downto 0)
IBASE slv8 := x"78"
out RB_SRES rb_sres_type
out TEMP slv( TEWIDTH- 1 downto 0)
ALWIDTH positive := 8
in RESET slbit := '0'