w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
pdp11_dmpcnt.vhd
Go to the documentation of this file.
1-- $Id: pdp11_dmpcnt.vhd 1181 2019-07-08 17:00:50Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2018-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: pdp11_dmpcnt - syn
7-- Description: pdp11: debug&moni: performance counters
8--
9-- Dependencies: -
10-- Test bench: -
11--
12-- Target Devices: generic
13-- Tool versions: ise 14.7; viv 2017.2-2019.1; ghdl 0.34-0.35
14--
15-- Synthesized (xst):
16-- Date Rev ise Target flop lutl lutm slic t peri
17-- 2018-09-23 1050 14.7 131013 xc6slx16-2 250 337 20 121 s 6.5
18--
19-- Revision History: -
20-- Date Rev Version Comment
21-- 2019-06-02 1159 1.0.1 use rbaddr_ constants
22-- 2018-09-29 1051 1.0 Initial version
23-- 2018-09-23 1050 0.1 First draft
24------------------------------------------------------------------------------
25--
26-- rbus registers:
27--
28-- Addr Bits Name r/w/f Function
29-- 00 cntl -/w/f Control register
30-- 15 ainc -/w/- enable address autoinc
31-- 13:09 caddr -/w/- counter address
32-- 07:00 vers r/-/- counter layout version
33-- 02:00 func 0/-/f change run status if != noop
34-- 0xx noop
35-- 100 sto stop
36-- 101 sta start
37-- 110 clr clear
38-- 111 loa load caddr
39-- 01 stat r/-/- Status register
40-- 15 ainc r/-/- enable address autoinc
41-- 13:09 caddr r/-/- counter address
42-- 08 waddr r/-/- word address
43-- 00 run r/-/- running
44-- 10 data r/-/- Data register
45--
46
47library ieee;
48use ieee.std_logic_1164.all;
49use ieee.numeric_std.all;
50
51use work.slvtypes.all;
52use work.memlib.all;
53use work.rblib.all;
54
55-- ----------------------------------------------------------------------------
56
57entity pdp11_dmpcnt_precnt is -- pre-counter
58 port (
59 CLK : in slbit; -- clock
60 CLR : in slbit; -- clear
61 ENA : in slbit; -- count
62 DOUT : out slv5 -- data
63 );
65
66architecture syn of pdp11_dmpcnt_precnt is
67 signal R_CNT : slv5 := (others=>'0');
68begin
69 proc_cnt: process (CLK)
70 begin
71
72 if rising_edge(CLK) then
73 if CLR = '1' then
74 R_CNT <= (others=>'0');
75 else
76 if ENA = '1' then
77 R_CNT <= slv(unsigned(R_CNT) + 1);
78 end if;
79 end if;
80 end if;
81
82 end process proc_cnt;
83
84 DOUT <= R_CNT;
85
86end syn;
87
88-- ----------------------------------------------------------------------------
89
90library ieee;
91use ieee.std_logic_1164.all;
92use ieee.numeric_std.all;
93
94use work.slvtypes.all;
95use work.memlib.all;
96use work.rblib.all;
97use work.pdp11.all;
98
99entity pdp11_dmpcnt is -- debug&moni: performance counters
100 generic (
101 RB_ADDR : slv16 := rbaddr_dmpcnt_off; -- rbus address
102 VERS : slv8 := slv(to_unsigned(1, 8)); -- counter layout version
103 CENA : slv32 := (others=>'1')); -- counter enables
104 port (
105 CLK : in slbit; -- clock
106 RESET : in slbit; -- reset
107 RB_MREQ : in rb_mreq_type; -- rbus: request
108 RB_SRES : out rb_sres_type; -- rbus: response
109 PERFSIG : in slv32 -- signals to count
110 );
111end pdp11_dmpcnt;
112
113
114architecture syn of pdp11_dmpcnt is
115
116 constant rbaddr_cntl : slv2 := "00"; -- cntl address offset
117 constant rbaddr_stat : slv2 := "01"; -- stat address offset
118 constant rbaddr_data : slv2 := "10"; -- data address offset
119
120 constant cntl_rbf_ainc : integer := 15;
121 subtype cntl_rbf_caddr is integer range 13 downto 9;
122 subtype cntl_rbf_vers is integer range 7 downto 0;
123 subtype cntl_rbf_func is integer range 2 downto 0;
124
125 constant stat_rbf_ainc : integer := 15;
126 subtype stat_rbf_caddr is integer range 13 downto 9;
127 constant stat_rbf_waddr : integer := 8;
128 constant stat_rbf_run : integer := 0;
129
130 constant func_sto : slv3 := "100"; -- func: stop
131 constant func_sta : slv3 := "101"; -- func: start
132 constant func_clr : slv3 := "110"; -- func: clear
133 constant func_loa : slv3 := "111"; -- func: load
134
135 type regs_type is record
136 rbsel : slbit; -- rbus select
137 run : slbit; -- run flag
138 saddr : slv5; -- scan address
139 raddr : slv5; -- read address (counter)
140 waddr : slbit; -- read address (word)
141 ainc : slbit; -- enable ddress autoinc
142 zbusy : slbit; -- clear in progress
143 dval : slbit; -- data valid
144 dout : slv32; -- read data (valid if dval=1)
145 psig : slv32; -- signals, floped
146 end record regs_type;
147
148 constant regs_init : regs_type := (
149 '0','0', -- rbsel,run
150 (others=>'0'), -- saddr
151 (others=>'0'), -- raddr
152 '0','0','0','0', -- waddr,ainc,zbusy,dval
153 (others=>'0'), -- dout
154 (others=>'0') -- psig
155 );
156
158 signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer)
159
160 type pre_do_type is array (31 downto 0) of slv5;
161
162 signal PRE_CLR : slv32 := (others=>'0');
163 signal PRE_DO : pre_do_type := (others=> (others => '0'));
164 signal MEM_DI : slv32 := (others=>'0');
165 signal MEM_DO : slv32 := (others=>'0');
166
167 begin
168
169 MEM : ram_1swar_gen
170 generic map (
171 AWIDTH => 5,
172 DWIDTH => 32)
173 port map (
174 CLK => CLK,
175 WE => '1',
176 ADDR => R_REGS.saddr,
177 DI => MEM_DI,
178 DO => MEM_DO
179 );
180
181 PRE: for i in 31 downto 0 generate
182 ENA: if CENA(i)='1' generate
183 CNT : entity work.pdp11_dmpcnt_precnt
184 port map (
185 CLK => CLK,
186 CLR => PRE_CLR(i),
187 ENA => R_REGS.psig(i),
188 DOUT => PRE_DO(i)
189 );
190 end generate ENA;
191 end generate PRE;
192
193 proc_cnt: process (R_REGS, PRE_DO, MEM_DO)
194 variable iclr : slv32 := (others=>'0');
195 variable ipdo : slv32 := (others=>'0');
196 variable icnt : slv32 := (others=>'0');
197 variable imdi : slv32 := (others=>'0');
198 constant ipdo_pad: slv(31 downto 5) := (others=>'0');
199 constant icnt_pad: slv(31 downto 1) := (others=>'0');
200 begin
201 iclr := (others=>'0');
202 iclr(to_integer(unsigned(R_REGS.saddr))) := '1';
203
204 ipdo := ipdo_pad & PRE_DO(to_integer(unsigned(R_REGS.saddr)));
205 icnt := icnt_pad & R_REGS.psig(to_integer(unsigned(R_REGS.saddr)));
206 PRE_CLR <= iclr;
207 if R_REGS.zbusy = '0' then
208 imdi := slv(unsigned(MEM_DO) + unsigned(ipdo) + unsigned(icnt));
209 else
210 imdi := (others=>'0');
211 end if;
212 MEM_DI <= imdi;
213
214 end process proc_cnt;
215
216 proc_regs: process (CLK)
217 begin
218
219 if rising_edge(CLK) then
220 if RESET = '1' then
221 R_REGS <= regs_init;
222 else
223 R_REGS <= N_REGS;
224 end if;
225 end if;
226
227 end process proc_regs;
228
229 proc_next: process (R_REGS, RB_MREQ, PERFSIG, MEM_DO)
230
231 variable r : regs_type := regs_init;
232 variable n : regs_type := regs_init;
233
234 variable irb_ack : slbit := '0';
235 variable irb_busy : slbit := '0';
236 variable irb_err : slbit := '0';
237 variable irb_dout : slv16 := (others=>'0');
238 variable irbena : slbit := '0';
239
240 begin
241
242 r := R_REGS;
243 n := R_REGS;
244
245 irb_ack := '0';
246 irb_busy := '0';
247 irb_err := '0';
248 irb_dout := (others=>'0');
249 irbena := RB_MREQ.re or RB_MREQ.we;
250
251 -- rbus address decoder
252 n.rbsel := '0';
253 if RB_MREQ.aval='1' then
254 if RB_MREQ.addr(15 downto 2)=RB_ADDR(15 downto 2) then
255 n.rbsel := '1';
256 end if;
257 end if;
258
259 if r.run = '1' then -- if running
260 n.psig := PERFSIG; -- capture performance signals
261 else
262 n.psig := (others=>'0'); -- otherwise ignore them
263 end if;
264
265 n.saddr := slv(unsigned(r.saddr) + 1); -- scan counter (always running)
266
267 -- capture data in dout buffer if scan=read address and looking at lsb and
268 -- if either data not valid or no rbus cycle active. this ensures that
269 -- dval waits end, and also that data isn't changing during rbus active.
270 if r.saddr = r.raddr and r.waddr = '0' and
271 (r.dval='0' or r.rbsel='0') then
272 n.dout := MEM_DO; -- capture data
273 n.dval := '1';
274 end if;
275
276 -- rbus transactions
277 if r.rbsel = '1' then
278 irb_ack := irbena; -- ack all accesses
279 case RB_MREQ.addr(1 downto 0) is
280
281 when rbaddr_cntl => -- cntl ------------------
282 if RB_MREQ.we = '1' then
283 case RB_MREQ.din(cntl_rbf_func) is
284 when func_sto => -- func: stop ------------
285 n.run := '0';
286
287 when func_sta => -- func: start -----------
288 n.run := '1';
289
290 when func_clr => -- func: clear -----------
291 n.run := '0';
292 if r.zbusy = '0' then
293 n.zbusy := '1';
294 n.saddr := (others=>'0');
295 n.raddr := (others=>'0');
296 n.waddr := '0';
297 n.ainc := '0';
298 irb_busy := '1';
299 else
300 if r.saddr = "11111" then
301 n.zbusy := '0';
302 n.dval := '0';
303 else
304 irb_busy := '1';
305 end if;
306 end if;
307
308 when func_loa => -- func: load ------------
309 n.ainc := RB_MREQ.din(cntl_rbf_ainc);
310 n.raddr := RB_MREQ.din(cntl_rbf_caddr);
311 n.waddr := '0';
312 n.dval := '0';
313
314 when others => null; -- <> --------------------
315 end case;
316 end if;
317
318 when rbaddr_stat => -- stat ------------------
319 irb_err := RB_MREQ.we;
320
321 when rbaddr_data => -- data ------------------
322 -- write to data is an error
323 if RB_MREQ.we='1' then
324 irb_err := '1'; -- error
325 end if;
326 if RB_MREQ.re = '1' then
327 if r.dval = '0' then
328 irb_busy := '1';
329 else
330 n.waddr := not r.waddr;
331 if r.ainc='1' and r.waddr = '1' then -- autoinc and wrap ?
332 n.raddr := slv(unsigned(r.raddr) + 1);
333 n.dval := '0';
334 end if;
335 end if;
336 end if;
337
338 when others => irb_err := '1'; -- <> --------------------
339 end case;
340 end if;
341
342 -- rbus output driver
343 if r.rbsel = '1' then
344 case RB_MREQ.addr(1 downto 0) is
345
346 when rbaddr_cntl => null; -- cntl ------------------
347 irb_dout(cntl_rbf_vers) := VERS;
348
349 when rbaddr_stat => -- stat ------------------
350 irb_dout(stat_rbf_ainc) := r.ainc;
351 irb_dout(stat_rbf_caddr) := r.raddr;
352 irb_dout(stat_rbf_waddr) := r.waddr;
353 irb_dout(stat_rbf_run) := r.run;
354
355 when rbaddr_data => -- data ------------------
356 if r.waddr = '0' then
357 irb_dout := r.dout(15 downto 0);
358 else
359 irb_dout := r.dout(31 downto 16);
360 end if;
361
362 when others => null;
363 end case;
364 end if;
365
366 N_REGS <= n;
367
368 RB_SRES.ack <= irb_ack;
369 RB_SRES.err <= irb_err;
370 RB_SRES.busy <= irb_busy;
371 RB_SRES.dout <= irb_dout;
372
373 end process proc_next;
374
375end syn;
slv3 := "100" func_sto
slv2 := "10" rbaddr_data
slv2 := "01" rbaddr_stat
slv32 :=( others => '0') MEM_DI
integer range 7 downto 0 cntl_rbf_vers
slv3 := "101" func_sta
( 31 downto 0) slv5 pre_do_type
integer range 13 downto 9 stat_rbf_caddr
slv32 :=( others => '0') MEM_DO
regs_type :=( '0', '0',( others => '0'),( others => '0'), '0', '0', '0', '0',( others => '0'),( others => '0')) regs_init
slv2 := "00" rbaddr_cntl
integer range 2 downto 0 cntl_rbf_func
slv3 := "110" func_clr
integer range 13 downto 9 cntl_rbf_caddr
integer := 15 cntl_rbf_ainc
slv32 :=( others => '0') PRE_CLR
slv3 := "111" func_loa
regs_type := regs_init R_REGS
pre_do_type :=( others =>( others => '0')) PRE_DO
integer := 8 stat_rbf_waddr
integer := 15 stat_rbf_ainc
integer := 0 stat_rbf_run
slv5 :=( others => '0') R_CNT
_library_ ieeeieee
in RESET slbit
CENA slv32 :=( others => '1')
VERS slv8 := slv( to_unsigned( 1, 8) )
in CLK slbit
in RB_MREQ rb_mreq_type
RB_ADDR slv16 := rbaddr_dmpcnt_off
out RB_SRES rb_sres_type
in PERFSIG slv32
Definition: pdp11.vhd:123
in ADDR slv( AWIDTH- 1 downto 0)
out DO slv( DWIDTH- 1 downto 0)
AWIDTH positive := 4
in DI slv( DWIDTH- 1 downto 0)
in CLK slbit
in WE slbit
DWIDTH positive := 16
Definition: rblib.vhd:32
std_logic_vector( 4 downto 0) slv5
Definition: slvtypes.vhd:37
std_logic_vector( 2 downto 0) slv3
Definition: slvtypes.vhd:35
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