1 |
59 |
zero_gravi |
-- #################################################################################################
|
2 |
|
|
-- # << NEORV32 - RISC-V-Compatible Debug Module (DM) >> #
|
3 |
|
|
-- # ********************************************************************************************* #
|
4 |
|
|
-- # Compatible to the "Minimal RISC-V External Debug Spec. Version 0.13.2" #
|
5 |
|
|
-- # -> "Execution-based" debugging scheme #
|
6 |
|
|
-- # ********************************************************************************************* #
|
7 |
|
|
-- # Key features: #
|
8 |
|
|
-- # * register access commands only #
|
9 |
|
|
-- # * auto-execution commands #
|
10 |
|
|
-- # * for a single hart only #
|
11 |
|
|
-- # * 2 general purpose program buffer entries #
|
12 |
|
|
-- # * 1 general purpose data buffer entry #
|
13 |
|
|
-- # #
|
14 |
|
|
-- # CPU access: #
|
15 |
|
|
-- # * ROM for "park loop" code #
|
16 |
|
|
-- # * program buffer #
|
17 |
|
|
-- # * data buffer #
|
18 |
|
|
-- # * control and status register #
|
19 |
|
|
-- # ********************************************************************************************* #
|
20 |
|
|
-- # BSD 3-Clause License #
|
21 |
|
|
-- # #
|
22 |
|
|
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
|
23 |
|
|
-- # #
|
24 |
|
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
25 |
|
|
-- # permitted provided that the following conditions are met: #
|
26 |
|
|
-- # #
|
27 |
|
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
28 |
|
|
-- # conditions and the following disclaimer. #
|
29 |
|
|
-- # #
|
30 |
|
|
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
|
31 |
|
|
-- # conditions and the following disclaimer in the documentation and/or other materials #
|
32 |
|
|
-- # provided with the distribution. #
|
33 |
|
|
-- # #
|
34 |
|
|
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
|
35 |
|
|
-- # endorse or promote products derived from this software without specific prior written #
|
36 |
|
|
-- # permission. #
|
37 |
|
|
-- # #
|
38 |
|
|
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
|
39 |
|
|
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
|
40 |
|
|
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
|
41 |
|
|
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
|
42 |
|
|
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
|
43 |
|
|
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
|
44 |
|
|
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
|
45 |
|
|
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
|
46 |
|
|
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
|
47 |
|
|
-- # ********************************************************************************************* #
|
48 |
|
|
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
|
49 |
|
|
-- #################################################################################################
|
50 |
|
|
|
51 |
|
|
library ieee;
|
52 |
|
|
use ieee.std_logic_1164.all;
|
53 |
|
|
use ieee.numeric_std.all;
|
54 |
|
|
|
55 |
|
|
library neorv32;
|
56 |
|
|
use neorv32.neorv32_package.all;
|
57 |
|
|
|
58 |
|
|
entity neorv32_debug_dm is
|
59 |
|
|
port (
|
60 |
|
|
-- global control --
|
61 |
|
|
clk_i : in std_ulogic; -- global clock line
|
62 |
|
|
rstn_i : in std_ulogic; -- global reset line, low-active
|
63 |
|
|
-- debug module interface (DMI) --
|
64 |
|
|
dmi_rstn_i : in std_ulogic;
|
65 |
|
|
dmi_req_valid_i : in std_ulogic;
|
66 |
|
|
dmi_req_ready_o : out std_ulogic; -- DMI is allowed to make new requests when set
|
67 |
|
|
dmi_req_addr_i : in std_ulogic_vector(06 downto 0);
|
68 |
|
|
dmi_req_op_i : in std_ulogic; -- 0=read, 1=write
|
69 |
|
|
dmi_req_data_i : in std_ulogic_vector(31 downto 0);
|
70 |
|
|
dmi_resp_valid_o : out std_ulogic; -- response valid when set
|
71 |
|
|
dmi_resp_ready_i : in std_ulogic; -- ready to receive respond
|
72 |
|
|
dmi_resp_data_o : out std_ulogic_vector(31 downto 0);
|
73 |
|
|
dmi_resp_err_o : out std_ulogic; -- 0=ok, 1=error
|
74 |
|
|
-- CPU bus access --
|
75 |
|
|
cpu_addr_i : in std_ulogic_vector(31 downto 0); -- address
|
76 |
|
|
cpu_rden_i : in std_ulogic; -- read enable
|
77 |
|
|
cpu_wren_i : in std_ulogic; -- write enable
|
78 |
|
|
cpu_data_i : in std_ulogic_vector(31 downto 0); -- data in
|
79 |
|
|
cpu_data_o : out std_ulogic_vector(31 downto 0); -- data out
|
80 |
|
|
cpu_ack_o : out std_ulogic; -- transfer acknowledge
|
81 |
|
|
-- CPU control --
|
82 |
|
|
cpu_ndmrstn_o : out std_ulogic; -- soc reset
|
83 |
|
|
cpu_halt_req_o : out std_ulogic -- request hart to halt (enter debug mode)
|
84 |
|
|
);
|
85 |
|
|
end neorv32_debug_dm;
|
86 |
|
|
|
87 |
|
|
architecture neorv32_debug_dm_rtl of neorv32_debug_dm is
|
88 |
|
|
|
89 |
|
|
-- DM configuration --
|
90 |
|
|
constant nscratch_c : std_ulogic_vector(03 downto 0) := "0001"; -- number of dscratch* registers in CPU = 1
|
91 |
|
|
constant dataaccess_c : std_ulogic := '1'; -- 1: abstract data is memory-mapped, 0: abstract data is CSR-mapped
|
92 |
|
|
constant datasize_c : std_ulogic_vector(03 downto 0) := "0001"; -- number of data registers in memory/CSR space = 1
|
93 |
|
|
constant dataaddr_c : std_ulogic_vector(11 downto 0) := dm_data_base_c(11 downto 0); -- signed base address of data registers in memory/CSR space
|
94 |
|
|
|
95 |
|
|
-- available DMI registers --
|
96 |
|
|
constant addr_data0_c : std_ulogic_vector(6 downto 0) := "000" & x"4";
|
97 |
|
|
constant addr_dmcontrol_c : std_ulogic_vector(6 downto 0) := "001" & x"0";
|
98 |
|
|
constant addr_dmstatus_c : std_ulogic_vector(6 downto 0) := "001" & x"1";
|
99 |
|
|
constant addr_hartinfo_c : std_ulogic_vector(6 downto 0) := "001" & x"2";
|
100 |
|
|
constant addr_abstractcs_c : std_ulogic_vector(6 downto 0) := "001" & x"6";
|
101 |
|
|
constant addr_command_c : std_ulogic_vector(6 downto 0) := "001" & x"7";
|
102 |
|
|
constant addr_abstractauto_c : std_ulogic_vector(6 downto 0) := "001" & x"8";
|
103 |
|
|
constant addr_nextdm_c : std_ulogic_vector(6 downto 0) := "001" & x"d";
|
104 |
|
|
constant addr_progbuf0_c : std_ulogic_vector(6 downto 0) := "010" & x"0";
|
105 |
|
|
constant addr_progbuf1_c : std_ulogic_vector(6 downto 0) := "010" & x"1";
|
106 |
|
|
constant addr_sbcs_c : std_ulogic_vector(6 downto 0) := "011" & x"8";
|
107 |
|
|
constant addr_haltsum0_c : std_ulogic_vector(6 downto 0) := "100" & x"0";
|
108 |
|
|
|
109 |
|
|
-- RISC-V 32-bit instruction prototypes --
|
110 |
|
|
constant instr_nop_c : std_ulogic_vector(31 downto 0) := x"00000013"; -- nop
|
111 |
|
|
constant instr_lw_c : std_ulogic_vector(31 downto 0) := x"00002003"; -- lw zero, 0(zero)
|
112 |
|
|
constant instr_sw_c : std_ulogic_vector(31 downto 0) := x"00002023"; -- sw zero, 0(zero)
|
113 |
|
|
constant instr_ebreak_c : std_ulogic_vector(31 downto 0) := x"00100073"; -- ebreak
|
114 |
|
|
|
115 |
|
|
-- debug module controller --
|
116 |
|
|
type dm_ctrl_state_t is (CMD_IDLE, CMD_EXE_CHECK, CMD_EXE_PREPARE, CMD_EXE_TRIGGER, CMD_EXE_BUSY, CMD_EXE_ERROR);
|
117 |
|
|
type dm_ctrl_t is record
|
118 |
|
|
-- fsm --
|
119 |
|
|
state : dm_ctrl_state_t;
|
120 |
|
|
busy : std_ulogic;
|
121 |
|
|
ldsw_progbuf : std_ulogic_vector(31 downto 0);
|
122 |
|
|
pbuf_en : std_ulogic;
|
123 |
|
|
-- error flags --
|
124 |
|
|
illegal_state : std_ulogic;
|
125 |
|
|
illegal_cmd : std_ulogic;
|
126 |
|
|
cmderr : std_ulogic_vector(02 downto 0);
|
127 |
|
|
-- hart status --
|
128 |
|
|
hart_halted : std_ulogic;
|
129 |
|
|
hart_resume_req : std_ulogic;
|
130 |
|
|
hart_resume_ack : std_ulogic;
|
131 |
|
|
hart_reset : std_ulogic;
|
132 |
|
|
end record;
|
133 |
|
|
signal dm_ctrl : dm_ctrl_t;
|
134 |
|
|
|
135 |
|
|
-- debug module DMI registers / access --
|
136 |
|
|
type progbuf_t is array (0 to 1) of std_ulogic_vector(31 downto 0);
|
137 |
|
|
type dm_reg_t is record
|
138 |
|
|
dmcontrol_ndmreset : std_ulogic;
|
139 |
|
|
dmcontrol_dmactive : std_ulogic;
|
140 |
|
|
abstractauto_autoexecdata : std_ulogic;
|
141 |
|
|
abstractauto_autoexecprogbuf : std_ulogic_vector(01 downto 0);
|
142 |
|
|
progbuf : progbuf_t;
|
143 |
|
|
command : std_ulogic_vector(31 downto 0);
|
144 |
|
|
--
|
145 |
|
|
halt_req : std_ulogic;
|
146 |
|
|
resume_req : std_ulogic;
|
147 |
|
|
reset_ack : std_ulogic;
|
148 |
|
|
wr_acc_err : std_ulogic;
|
149 |
|
|
rd_acc_err : std_ulogic;
|
150 |
|
|
clr_acc_err : std_ulogic;
|
151 |
|
|
autoexec_wr : std_ulogic;
|
152 |
|
|
autoexec_rd : std_ulogic;
|
153 |
|
|
end record;
|
154 |
|
|
signal dm_reg : dm_reg_t;
|
155 |
|
|
|
156 |
|
|
-- cpu program buffer --
|
157 |
|
|
type cpu_progbuf_t is array (0 to 4) of std_ulogic_vector(31 downto 0);
|
158 |
|
|
signal cpu_progbuf : cpu_progbuf_t;
|
159 |
|
|
|
160 |
|
|
-- **********************************************************
|
161 |
|
|
-- CPU Bus Interface
|
162 |
|
|
-- **********************************************************
|
163 |
|
|
|
164 |
|
|
-- Debug Core Interface
|
165 |
|
|
type dci_t is record
|
166 |
|
|
halt_ack : std_ulogic; -- CPU (re-)entered HALT state (single-shot)
|
167 |
|
|
resume_req : std_ulogic; -- DM wants the CPU to resume when set
|
168 |
|
|
resume_ack : std_ulogic; -- CPU starts resuming when set (single-shot)
|
169 |
|
|
execute_req : std_ulogic; -- DM wants CPU to execute program buffer when set
|
170 |
|
|
execute_ack : std_ulogic; -- CPU starts executing program buffer when set (single-shot)
|
171 |
|
|
exception_ack : std_ulogic; -- CPU has detected an exception (single-shot)
|
172 |
|
|
progbuf : std_ulogic_vector(255 downto 0); -- program buffer, 4 32-bit entries
|
173 |
|
|
data_we : std_ulogic; -- write abstract data
|
174 |
|
|
wdata : std_ulogic_vector(31 downto 0); -- abstract write data
|
175 |
|
|
rdata : std_ulogic_vector(31 downto 0); -- abstract read data
|
176 |
|
|
end record;
|
177 |
|
|
signal dci : dci_t;
|
178 |
|
|
|
179 |
|
|
-- IO space: module base address --
|
180 |
|
|
constant hi_abb_c : natural := 31; -- high address boundary bit
|
181 |
|
|
constant lo_abb_c : natural := index_size_f(dm_size_c); -- low address boundary bit
|
182 |
|
|
|
183 |
|
|
-- status and control register - bits --
|
184 |
|
|
constant sreg_halt_ack_c : natural := 0; -- -/w: CPU is halted in debug mode and waits in park loop
|
185 |
|
|
constant sreg_resume_req_c : natural := 1; -- r/-: DM requests CPU to resume
|
186 |
|
|
constant sreg_resume_ack_c : natural := 2; -- -/w: CPU starts resuming
|
187 |
|
|
constant sreg_execute_req_c : natural := 3; -- r/-: DM requests to execute program buffer
|
188 |
|
|
constant sreg_execute_ack_c : natural := 4; -- -/w: CPU starts to execute program buffer
|
189 |
|
|
constant sreg_exception_ack_c : natural := 5; -- -/w: CPU has detected an exception
|
190 |
|
|
|
191 |
|
|
-- code ROM for "park loop" --
|
192 |
|
|
type code_rom_file_t is array (0 to 31) of std_ulogic_vector(31 downto 0);
|
193 |
|
|
constant code_rom_file : code_rom_file_t := (
|
194 |
|
|
00000000 => x"0180006f",
|
195 |
|
|
00000001 => x"7b241073",
|
196 |
|
|
00000002 => x"02000413",
|
197 |
|
|
00000003 => x"98802023",
|
198 |
|
|
00000004 => x"7b202473",
|
199 |
|
|
00000005 => x"00100073",
|
200 |
|
|
00000006 => x"7b241073",
|
201 |
|
|
00000007 => x"00100413",
|
202 |
|
|
00000008 => x"98802023",
|
203 |
|
|
00000009 => x"98002403",
|
204 |
|
|
00000010 => x"00847413",
|
205 |
|
|
00000011 => x"02041263",
|
206 |
|
|
00000012 => x"98002403",
|
207 |
|
|
00000013 => x"00247413",
|
208 |
|
|
00000014 => x"00041463",
|
209 |
|
|
00000015 => x"fe9ff06f",
|
210 |
|
|
00000016 => x"00400413",
|
211 |
|
|
00000017 => x"98802023",
|
212 |
|
|
00000018 => x"7b202473",
|
213 |
|
|
00000019 => x"7b200073",
|
214 |
|
|
00000020 => x"01000413",
|
215 |
|
|
00000021 => x"98802023",
|
216 |
|
|
00000022 => x"7b202473",
|
217 |
|
|
00000023 => x"88000067",
|
218 |
|
|
others => x"00100073" -- ebreak
|
219 |
|
|
);
|
220 |
|
|
|
221 |
|
|
-- global access control --
|
222 |
|
|
signal acc_en : std_ulogic;
|
223 |
|
|
signal rden : std_ulogic;
|
224 |
|
|
signal wren : std_ulogic;
|
225 |
|
|
signal maddr : std_ulogic_vector(01 downto 0);
|
226 |
|
|
|
227 |
|
|
-- data buffer --
|
228 |
|
|
signal data_buf : std_ulogic_vector(31 downto 0);
|
229 |
|
|
|
230 |
|
|
-- program buffer access --
|
231 |
|
|
type prog_buf_t is array (0 to 3) of std_ulogic_vector(31 downto 0);
|
232 |
|
|
signal prog_buf : prog_buf_t;
|
233 |
|
|
|
234 |
|
|
begin
|
235 |
|
|
|
236 |
|
|
-- Debug Module Command Controller --------------------------------------------------------
|
237 |
|
|
-- -------------------------------------------------------------------------------------------
|
238 |
|
|
dm_controller: process(clk_i)
|
239 |
|
|
begin
|
240 |
|
|
if rising_edge(clk_i) then
|
241 |
|
|
if (dm_reg.dmcontrol_dmactive = '0') or (dmi_rstn_i = '0') then -- DM reset / DM disabled
|
242 |
|
|
dm_ctrl.state <= CMD_IDLE;
|
243 |
|
|
dm_ctrl.ldsw_progbuf <= instr_nop_c;
|
244 |
|
|
dci.execute_req <= '0';
|
245 |
|
|
dm_ctrl.pbuf_en <= '0';
|
246 |
|
|
--
|
247 |
|
|
dm_ctrl.illegal_cmd <= '-';
|
248 |
|
|
dm_ctrl.illegal_state <= '-';
|
249 |
|
|
dm_ctrl.cmderr <= "000";
|
250 |
|
|
--
|
251 |
|
|
dm_ctrl.hart_reset <= '0';
|
252 |
|
|
dm_ctrl.hart_halted <= '0';
|
253 |
|
|
dm_ctrl.hart_resume_req <= '0';
|
254 |
|
|
dm_ctrl.hart_resume_ack <= '0';
|
255 |
|
|
else -- DM active
|
256 |
|
|
|
257 |
|
|
-- defaults --
|
258 |
|
|
dci.execute_req <= '0';
|
259 |
|
|
dm_ctrl.illegal_cmd <= '0';
|
260 |
|
|
dm_ctrl.illegal_state <= '0';
|
261 |
|
|
|
262 |
|
|
-- command execution fsm --
|
263 |
|
|
case dm_ctrl.state is
|
264 |
|
|
|
265 |
|
|
when CMD_IDLE => -- wait for new abstract command
|
266 |
|
|
-- ------------------------------------------------------------
|
267 |
|
|
if (dmi_req_valid_i = '1') and (dmi_req_op_i = '1') then -- valid DM write access
|
268 |
|
|
if (dmi_req_addr_i = addr_command_c) then
|
269 |
|
|
if (dm_ctrl.cmderr = "000") then -- only execute if no error
|
270 |
|
|
dm_ctrl.state <= CMD_EXE_CHECK;
|
271 |
|
|
end if;
|
272 |
|
|
end if;
|
273 |
|
|
elsif (dm_reg.autoexec_rd = '1') or (dm_reg.autoexec_wr = '1') then -- auto execution trigger
|
274 |
|
|
dm_ctrl.state <= CMD_EXE_CHECK;
|
275 |
|
|
end if;
|
276 |
|
|
|
277 |
|
|
when CMD_EXE_CHECK => -- check if command is valid / supported
|
278 |
|
|
-- ------------------------------------------------------------
|
279 |
|
|
if (dm_reg.command(31 downto 24) = x"00") and -- cmdtype: register access
|
280 |
|
|
(dm_reg.command(23) = '0') and -- reserved
|
281 |
|
|
(dm_reg.command(22 downto 20) = "010") and -- aarsize: has to be 32-bit
|
282 |
|
|
(dm_reg.command(19) = '0') and -- aarpostincrement: not supported
|
283 |
|
|
((dm_reg.command(17) = '0') or (dm_reg.command(15 downto 05) = "00010000000")) then -- regno: only GPRs are supported: 0x1000..0x101f if transfer is set
|
284 |
|
|
if (dm_ctrl.hart_halted = '1') then -- CPU is halted
|
285 |
|
|
dm_ctrl.state <= CMD_EXE_PREPARE;
|
286 |
|
|
else -- error! CPU is still running
|
287 |
|
|
dm_ctrl.illegal_state <= '1';
|
288 |
|
|
dm_ctrl.state <= CMD_EXE_ERROR;
|
289 |
|
|
end if;
|
290 |
|
|
else -- invalid command
|
291 |
|
|
dm_ctrl.illegal_cmd <= '1';
|
292 |
|
|
dm_ctrl.state <= CMD_EXE_ERROR;
|
293 |
|
|
end if;
|
294 |
|
|
|
295 |
|
|
when CMD_EXE_PREPARE => -- setup program buffer
|
296 |
|
|
-- ------------------------------------------------------------
|
297 |
|
|
if (dm_reg.command(17) = '1') then -- "transfer"
|
298 |
|
|
if (dm_reg.command(16) = '0') then -- "write" = 0 -> read from GPR
|
299 |
|
|
dm_ctrl.ldsw_progbuf <= instr_sw_c;
|
300 |
|
|
dm_ctrl.ldsw_progbuf(31 downto 25) <= dataaddr_c(11 downto 05); -- destination address
|
301 |
|
|
dm_ctrl.ldsw_progbuf(24 downto 20) <= dm_reg.command(4 downto 0); -- "regno" = source register
|
302 |
|
|
dm_ctrl.ldsw_progbuf(11 downto 07) <= dataaddr_c(04 downto 00); -- destination address
|
303 |
|
|
else -- "write" = 0 -> write to GPR
|
304 |
|
|
dm_ctrl.ldsw_progbuf <= instr_lw_c;
|
305 |
|
|
dm_ctrl.ldsw_progbuf(31 downto 20) <= dataaddr_c; -- source address
|
306 |
|
|
dm_ctrl.ldsw_progbuf(11 downto 07) <= dm_reg.command(4 downto 0); -- "regno" = destination register
|
307 |
|
|
end if;
|
308 |
|
|
else
|
309 |
|
|
dm_ctrl.ldsw_progbuf <= instr_nop_c;
|
310 |
|
|
end if;
|
311 |
|
|
--
|
312 |
|
|
if (dm_reg.command(18) = '1') then -- "postexec" - execute DMI program buffer
|
313 |
|
|
dm_ctrl.pbuf_en <= '1';
|
314 |
|
|
else -- empty program buffer, execute NOPs
|
315 |
|
|
dm_ctrl.pbuf_en <= '0';
|
316 |
|
|
end if;
|
317 |
|
|
--
|
318 |
|
|
dm_ctrl.state <= CMD_EXE_TRIGGER;
|
319 |
|
|
|
320 |
|
|
when CMD_EXE_TRIGGER => -- request CPU to execute command
|
321 |
|
|
-- ------------------------------------------------------------
|
322 |
|
|
dci.execute_req <= '1'; -- request execution
|
323 |
|
|
if (dci.execute_ack = '1') then -- CPU starts execution
|
324 |
|
|
dm_ctrl.state <= CMD_EXE_BUSY;
|
325 |
|
|
end if;
|
326 |
|
|
|
327 |
|
|
when CMD_EXE_BUSY => -- wait for CPU to finish
|
328 |
|
|
-- ------------------------------------------------------------
|
329 |
|
|
if (dci.halt_ack = '1') then -- CPU is parked again -> execution done
|
330 |
|
|
dm_ctrl.state <= CMD_IDLE;
|
331 |
|
|
end if;
|
332 |
|
|
|
333 |
|
|
when CMD_EXE_ERROR => -- delay cycle for error to arrive abstracts.cmderr
|
334 |
|
|
-- ------------------------------------------------------------
|
335 |
|
|
dm_ctrl.state <= CMD_IDLE;
|
336 |
|
|
|
337 |
|
|
when others => -- undefined
|
338 |
|
|
-- ------------------------------------------------------------
|
339 |
|
|
dm_ctrl.state <= CMD_IDLE;
|
340 |
|
|
|
341 |
|
|
end case;
|
342 |
|
|
|
343 |
|
|
|
344 |
|
|
-- error flag register --
|
345 |
|
|
-- ------------------------------------------------------------
|
346 |
|
|
if (dm_ctrl.cmderr = "000") then
|
347 |
|
|
if (dm_ctrl.illegal_state = '1') then -- cannot execute since hart is not in expected state
|
348 |
|
|
dm_ctrl.cmderr <= "100";
|
349 |
|
|
elsif (dci.exception_ack = '1') then -- exception during execution
|
350 |
|
|
dm_ctrl.cmderr <= "011";
|
351 |
|
|
elsif (dm_ctrl.illegal_cmd = '1') then -- unsupported command
|
352 |
|
|
dm_ctrl.cmderr <= "010";
|
353 |
|
|
elsif (dm_reg.rd_acc_err = '1') or (dm_reg.wr_acc_err = '1') then -- invalid read/write while command is executing
|
354 |
|
|
dm_ctrl.cmderr <= "001";
|
355 |
|
|
end if;
|
356 |
|
|
elsif (dm_reg.clr_acc_err = '1') then -- acknowledge/clear error flags
|
357 |
|
|
dm_ctrl.cmderr <= "000";
|
358 |
|
|
end if;
|
359 |
|
|
|
360 |
|
|
|
361 |
|
|
-- hart status --
|
362 |
|
|
-- ------------------------------------------------------------
|
363 |
|
|
|
364 |
|
|
-- HALTED --
|
365 |
|
|
if (dm_reg.dmcontrol_ndmreset = '1') then
|
366 |
|
|
dm_ctrl.hart_halted <= '0';
|
367 |
|
|
elsif (dci.halt_ack = '1') then
|
368 |
|
|
dm_ctrl.hart_halted <= '1';
|
369 |
|
|
elsif (dci.resume_ack = '1') then
|
370 |
|
|
dm_ctrl.hart_halted <= '0';
|
371 |
|
|
end if;
|
372 |
|
|
|
373 |
|
|
-- RESUME REQ --
|
374 |
|
|
if (dm_reg.dmcontrol_ndmreset = '1') then
|
375 |
|
|
dm_ctrl.hart_resume_req <= '0';
|
376 |
|
|
elsif (dm_reg.resume_req = '1') then
|
377 |
|
|
dm_ctrl.hart_resume_req <= '1';
|
378 |
|
|
elsif (dci.resume_ack = '1') then
|
379 |
|
|
dm_ctrl.hart_resume_req <= '0';
|
380 |
|
|
end if;
|
381 |
|
|
|
382 |
|
|
-- RESUME ACK --
|
383 |
|
|
if (dm_reg.dmcontrol_ndmreset = '1') then
|
384 |
|
|
dm_ctrl.hart_resume_ack <= '0';
|
385 |
|
|
elsif (dci.resume_ack = '1') then
|
386 |
|
|
dm_ctrl.hart_resume_ack <= '1';
|
387 |
|
|
elsif (dm_reg.resume_req = '1') then
|
388 |
|
|
dm_ctrl.hart_resume_ack <= '0';
|
389 |
|
|
end if;
|
390 |
|
|
|
391 |
|
|
-- hart has been RESET --
|
392 |
|
|
if (dm_reg.dmcontrol_ndmreset = '1') then
|
393 |
|
|
dm_ctrl.hart_reset <= '1';
|
394 |
|
|
elsif (dm_reg.reset_ack = '1') then
|
395 |
|
|
dm_ctrl.hart_reset <= '0';
|
396 |
|
|
elsif (dm_reg.dmcontrol_ndmreset = '1') then
|
397 |
|
|
dm_ctrl.hart_reset <= '1';
|
398 |
|
|
end if;
|
399 |
|
|
|
400 |
|
|
end if;
|
401 |
|
|
end if;
|
402 |
|
|
end process dm_controller;
|
403 |
|
|
|
404 |
|
|
-- controller busy flag --
|
405 |
|
|
dm_ctrl.busy <= '0' when (dm_ctrl.state = CMD_IDLE) else '1';
|
406 |
|
|
|
407 |
|
|
|
408 |
|
|
-- Debug Module Interface - Write Access --------------------------------------------------
|
409 |
|
|
-- -------------------------------------------------------------------------------------------
|
410 |
|
|
dmi_write_access: process(rstn_i, clk_i)
|
411 |
|
|
begin
|
412 |
|
|
if (rstn_i = '0') then
|
413 |
|
|
dm_reg.dmcontrol_ndmreset <= '0';
|
414 |
|
|
dm_reg.dmcontrol_dmactive <= '0'; -- DM is in reset state after hardware reset
|
415 |
|
|
--
|
416 |
|
|
dm_reg.abstractauto_autoexecdata <= '0';
|
417 |
|
|
dm_reg.abstractauto_autoexecprogbuf <= "00";
|
418 |
|
|
--
|
419 |
|
|
dm_reg.command <= (others => '0');
|
420 |
|
|
dm_reg.progbuf <= (others => instr_nop_c);
|
421 |
|
|
--
|
422 |
|
|
dm_reg.halt_req <= '0';
|
423 |
|
|
dm_reg.resume_req <= '0';
|
424 |
|
|
dm_reg.reset_ack <= '0';
|
425 |
|
|
dm_reg.wr_acc_err <= '0';
|
426 |
|
|
dm_reg.clr_acc_err <= '0';
|
427 |
|
|
dm_reg.autoexec_wr <= '0';
|
428 |
|
|
elsif rising_edge(clk_i) then
|
429 |
|
|
|
430 |
|
|
-- default --
|
431 |
|
|
dm_reg.halt_req <= '0';
|
432 |
|
|
dm_reg.resume_req <= '0';
|
433 |
|
|
dm_reg.reset_ack <= '0';
|
434 |
|
|
dm_reg.wr_acc_err <= '0';
|
435 |
|
|
dm_reg.clr_acc_err <= '0';
|
436 |
|
|
dm_reg.autoexec_wr <= '0';
|
437 |
|
|
|
438 |
|
|
-- DMI access --
|
439 |
|
|
if (dmi_req_valid_i = '1') and (dmi_req_op_i = '1') then -- valid DMI write request
|
440 |
|
|
|
441 |
|
|
-- debug module control --
|
442 |
|
|
if (dmi_req_addr_i = addr_dmcontrol_c) then
|
443 |
|
|
dm_reg.halt_req <= dmi_req_data_i(31); -- haltreq (-/w): write 1 to request halt
|
444 |
|
|
dm_reg.resume_req <= dmi_req_data_i(30); -- resumereq (-/w1): write 1 to request resume
|
445 |
|
|
dm_reg.reset_ack <= dmi_req_data_i(28); -- ackhavereset (-/w1)
|
446 |
|
|
dm_reg.dmcontrol_ndmreset <= dmi_req_data_i(01); -- ndmreset (r/w): soc reset
|
447 |
|
|
dm_reg.dmcontrol_dmactive <= dmi_req_data_i(00); -- dmactive (r/w): DM reset
|
448 |
|
|
end if;
|
449 |
|
|
|
450 |
|
|
-- write abstract command --
|
451 |
|
|
if (dmi_req_addr_i = addr_command_c) then
|
452 |
|
|
if (dm_ctrl.busy = '0') and (dm_ctrl.cmderr = "000") then -- idle and no errors yet
|
453 |
|
|
dm_reg.command <= dmi_req_data_i;
|
454 |
|
|
end if;
|
455 |
|
|
end if;
|
456 |
|
|
|
457 |
|
|
-- write abstract command autoexec --
|
458 |
|
|
if (dmi_req_addr_i = addr_abstractauto_c) then
|
459 |
|
|
if (dm_ctrl.busy = '0') then -- idle and no errors yet
|
460 |
|
|
dm_reg.abstractauto_autoexecdata <= dmi_req_data_i(00);
|
461 |
|
|
dm_reg.abstractauto_autoexecprogbuf(0) <= dmi_req_data_i(16);
|
462 |
|
|
dm_reg.abstractauto_autoexecprogbuf(1) <= dmi_req_data_i(17);
|
463 |
|
|
end if;
|
464 |
|
|
end if;
|
465 |
|
|
|
466 |
|
|
-- auto execution trigger --
|
467 |
|
|
if ((dmi_req_addr_i = addr_data0_c) and (dm_reg.abstractauto_autoexecdata = '1')) or
|
468 |
|
|
((dmi_req_addr_i = addr_progbuf0_c) and (dm_reg.abstractauto_autoexecprogbuf(0) = '1')) or
|
469 |
|
|
((dmi_req_addr_i = addr_progbuf1_c) and (dm_reg.abstractauto_autoexecprogbuf(1) = '1')) then
|
470 |
|
|
dm_reg.autoexec_wr <= '1';
|
471 |
|
|
end if;
|
472 |
|
|
|
473 |
|
|
-- acknowledge command error --
|
474 |
|
|
if (dmi_req_addr_i = addr_abstractcs_c) then
|
475 |
|
|
if (dmi_req_data_i(10 downto 8) = "111") then
|
476 |
|
|
dm_reg.clr_acc_err <= '1';
|
477 |
|
|
end if;
|
478 |
|
|
end if;
|
479 |
|
|
|
480 |
|
|
-- write program buffer --
|
481 |
|
|
if (dmi_req_addr_i(dmi_req_addr_i'left downto 1) = addr_progbuf0_c(dmi_req_addr_i'left downto 1)) then
|
482 |
|
|
if (dm_ctrl.busy = '0') then -- idle
|
483 |
|
|
if (dmi_req_addr_i(0) = addr_progbuf0_c(0)) then
|
484 |
|
|
dm_reg.progbuf(0) <= dmi_req_data_i;
|
485 |
|
|
else
|
486 |
|
|
dm_reg.progbuf(1) <= dmi_req_data_i;
|
487 |
|
|
end if;
|
488 |
|
|
end if;
|
489 |
|
|
end if;
|
490 |
|
|
|
491 |
|
|
-- invalid access (while command is executing) --
|
492 |
|
|
if (dm_ctrl.busy = '1') then -- busy
|
493 |
|
|
if (dmi_req_addr_i = addr_abstractcs_c) or
|
494 |
|
|
(dmi_req_addr_i = addr_command_c) or
|
495 |
|
|
(dmi_req_addr_i = addr_abstractauto_c) or
|
496 |
|
|
(dmi_req_addr_i = addr_data0_c) or
|
497 |
|
|
(dmi_req_addr_i = addr_progbuf0_c) or
|
498 |
|
|
(dmi_req_addr_i = addr_progbuf1_c) then
|
499 |
|
|
dm_reg.wr_acc_err <= '1';
|
500 |
|
|
end if;
|
501 |
|
|
end if;
|
502 |
|
|
|
503 |
|
|
end if;
|
504 |
|
|
end if;
|
505 |
|
|
end process dmi_write_access;
|
506 |
|
|
|
507 |
|
|
|
508 |
|
|
-- Direct Control -------------------------------------------------------------------------
|
509 |
|
|
-- -------------------------------------------------------------------------------------------
|
510 |
|
|
-- write to abstract data register --
|
511 |
|
|
dci.data_we <= '1' when (dmi_req_valid_i = '1') and (dmi_req_op_i = '1') and (dmi_req_addr_i = addr_data0_c) and (dm_ctrl.busy = '0') else '0';
|
512 |
|
|
dci.wdata <= dmi_req_data_i;
|
513 |
|
|
|
514 |
|
|
-- CPU halt/resume request --
|
515 |
|
|
cpu_halt_req_o <= dm_reg.halt_req and dm_reg.dmcontrol_dmactive; -- single shot
|
516 |
|
|
dci.resume_req <= dm_ctrl.hart_resume_req; -- permanent
|
517 |
|
|
|
518 |
|
|
-- SoC reset --
|
519 |
|
|
cpu_ndmrstn_o <= not (dm_reg.dmcontrol_ndmreset and dm_reg.dmcontrol_dmactive);
|
520 |
|
|
|
521 |
|
|
-- build program buffer array for cpu access --
|
522 |
|
|
cpu_progbuf(0) <= dm_ctrl.ldsw_progbuf; -- pseudo program buffer for GPR access
|
523 |
|
|
cpu_progbuf(1) <= instr_nop_c when (dm_ctrl.pbuf_en = '0') else dm_reg.progbuf(0);
|
524 |
|
|
cpu_progbuf(2) <= instr_nop_c when (dm_ctrl.pbuf_en = '0') else dm_reg.progbuf(1);
|
525 |
|
|
cpu_progbuf(3) <= instr_ebreak_c; -- implicit ebreak instruction
|
526 |
|
|
|
527 |
|
|
-- DMI status --
|
528 |
|
|
dmi_resp_err_o <= '0'; -- what can go wrong?
|
529 |
|
|
dmi_req_ready_o <= '1'; -- always ready for new read/write accesses
|
530 |
|
|
|
531 |
|
|
|
532 |
|
|
-- Debug Module Interface - Read Access ---------------------------------------------------
|
533 |
|
|
-- -------------------------------------------------------------------------------------------
|
534 |
|
|
dmi_read_access: process(clk_i)
|
535 |
|
|
begin
|
536 |
|
|
if rising_edge(clk_i) then
|
537 |
|
|
dmi_resp_valid_o <= dmi_req_valid_i; -- DMI transfer ack
|
538 |
|
|
dmi_resp_data_o <= (others => '0'); -- default
|
539 |
|
|
dm_reg.rd_acc_err <= '0';
|
540 |
|
|
dm_reg.autoexec_rd <= '0';
|
541 |
|
|
|
542 |
|
|
case dmi_req_addr_i is
|
543 |
|
|
|
544 |
|
|
-- debug module status register --
|
545 |
|
|
when addr_dmstatus_c =>
|
546 |
|
|
dmi_resp_data_o(31 downto 23) <= (others => '0'); -- reserved (r/-)
|
547 |
|
|
dmi_resp_data_o(22) <= '1'; -- impebreak (r/-): there is an implicit ebreak instruction after the program visible buffer
|
548 |
|
|
dmi_resp_data_o(21 downto 20) <= (others => '0'); -- reserved (r/-)
|
549 |
|
|
dmi_resp_data_o(19) <= dm_ctrl.hart_reset; -- allhavereset (r/-): there is only one hart that can be reset
|
550 |
|
|
dmi_resp_data_o(18) <= dm_ctrl.hart_reset; -- anyhavereset (r/-): there is only one hart that can be reset
|
551 |
|
|
dmi_resp_data_o(17) <= dm_ctrl.hart_resume_ack; -- allresumeack (r/-): there is only one hart that can acknowledge resume request
|
552 |
|
|
dmi_resp_data_o(16) <= dm_ctrl.hart_resume_ack; -- anyresumeack (r/-): there is only one hart that can acknowledge resume request
|
553 |
|
|
dmi_resp_data_o(15) <= '0'; -- allnonexistent (r/-): there is only one hart that is always existent
|
554 |
|
|
dmi_resp_data_o(14) <= '0'; -- anynonexistent (r/-): there is only one hart that is always existent
|
555 |
|
|
dmi_resp_data_o(13) <= dm_reg.dmcontrol_ndmreset; -- allunavail (r/-): there is only one hart that is unavailable during reset
|
556 |
|
|
dmi_resp_data_o(12) <= dm_reg.dmcontrol_ndmreset; -- anyunavail (r/-): there is only one hart that is unavailable during reset
|
557 |
|
|
dmi_resp_data_o(11) <= not dm_ctrl.hart_halted; -- allrunning (r/-): there is only one hart that can be RUNNING or HALTED
|
558 |
|
|
dmi_resp_data_o(10) <= not dm_ctrl.hart_halted; -- anyrunning (r/-): there is only one hart that can be RUNNING or HALTED
|
559 |
|
|
dmi_resp_data_o(09) <= dm_ctrl.hart_halted; -- allhalted (r/-): there is only one hart that can be RUNNING or HALTED
|
560 |
|
|
dmi_resp_data_o(08) <= dm_ctrl.hart_halted; -- anyhalted (r/-): there is only one hart that can be RUNNING or HALTED
|
561 |
|
|
dmi_resp_data_o(07) <= '1'; -- authenticated (r/-): authentication passed since there is no authentication
|
562 |
|
|
dmi_resp_data_o(06) <= '0'; -- authbusy (r/-): always ready since there is no authentication
|
563 |
|
|
dmi_resp_data_o(05) <= '0'; -- hasresethaltreq (r/-): halt-on-reset not implemented
|
564 |
|
|
dmi_resp_data_o(04) <= '0'; -- confstrptrvalid (r/-): no configuration string available
|
565 |
|
|
dmi_resp_data_o(03 downto 00) <= "0010"; -- version (r/-): compatible to version 0.13
|
566 |
|
|
|
567 |
|
|
-- debug module control --
|
568 |
|
|
when addr_dmcontrol_c =>
|
569 |
|
|
dmi_resp_data_o(31) <= '0'; -- haltreq (-/w): write-only
|
570 |
|
|
dmi_resp_data_o(30) <= '0'; -- resumereq (-/w1): write-only
|
571 |
|
|
dmi_resp_data_o(29) <= '0'; -- hartreset (r/w): not supported
|
572 |
|
|
dmi_resp_data_o(28) <= '0'; -- ackhavereset (-/w1): write-only
|
573 |
|
|
dmi_resp_data_o(27) <= '0'; -- reserved (r/-)
|
574 |
|
|
dmi_resp_data_o(26) <= '0'; -- hasel (r/-) - there is a single currently selected hart
|
575 |
|
|
dmi_resp_data_o(25 downto 16) <= (others => '0'); -- hartsello (r/-) - there is only one hart
|
576 |
|
|
dmi_resp_data_o(15 downto 06) <= (others => '0'); -- hartselhi (r/-) - there is only one hart
|
577 |
|
|
dmi_resp_data_o(05 downto 04) <= (others => '0'); -- reserved (r/-)
|
578 |
|
|
dmi_resp_data_o(03) <= '0'; -- setresethaltreq (-/w1): halt-on-reset request - halt-on-reset not implemented
|
579 |
|
|
dmi_resp_data_o(02) <= '0'; -- clrresethaltreq (-/w1): halt-on-reset ack - halt-on-reset not implemented
|
580 |
|
|
dmi_resp_data_o(01) <= dm_reg.dmcontrol_ndmreset; -- ndmreset (r/w): soc reset
|
581 |
|
|
dmi_resp_data_o(00) <= dm_reg.dmcontrol_dmactive; -- dmactive (r/w): DM reset
|
582 |
|
|
|
583 |
|
|
-- hart info --
|
584 |
|
|
when addr_hartinfo_c =>
|
585 |
|
|
dmi_resp_data_o(31 downto 24) <= (others => '0'); -- reserved (r/-)
|
586 |
|
|
dmi_resp_data_o(23 downto 20) <= nscratch_c; -- nscratch (r/-): number of dscratch CSRs
|
587 |
|
|
dmi_resp_data_o(19 downto 17) <= (others => '0'); -- reserved (r/-)
|
588 |
|
|
dmi_resp_data_o(16) <= dataaccess_c; -- dataaccess (r/-): 1: data registers are memory-mapped, 0: data reisters are CSR-mapped
|
589 |
|
|
dmi_resp_data_o(15 downto 12) <= datasize_c; -- datasize (r/-): number data registers in memory/CSR space
|
590 |
|
|
dmi_resp_data_o(11 downto 00) <= dataaddr_c; -- dataaddr (r/-): data registers base address (memory/CSR)
|
591 |
|
|
|
592 |
|
|
-- abstract control and status --
|
593 |
|
|
when addr_abstractcs_c =>
|
594 |
|
|
dmi_resp_data_o(31 downto 24) <= (others => '0'); -- reserved (r/-)
|
595 |
|
|
dmi_resp_data_o(28 downto 24) <= "00010"; -- progbufsize (r/-): number of words in program buffer = 2
|
596 |
|
|
dmi_resp_data_o(12) <= dm_ctrl.busy; -- busy (r/-): abstract command in progress (1) / idle (0)
|
597 |
|
|
dmi_resp_data_o(11) <= '0'; -- reserved (r/-)
|
598 |
|
|
dmi_resp_data_o(10 downto 08) <= dm_ctrl.cmderr; -- cmderr (r/w1c): any error during execution?
|
599 |
|
|
dmi_resp_data_o(07 downto 04) <= (others => '0'); -- reserved (r/-)
|
600 |
|
|
dmi_resp_data_o(03 downto 00) <= "0001"; -- datacount (r/-): number of implemented data registers = 1
|
601 |
|
|
|
602 |
|
|
-- -- abstract command (-/w) --
|
603 |
|
|
-- when addr_command_c =>
|
604 |
|
|
-- dmi_resp_data_o <= (others => '0'); -- register is write-only
|
605 |
|
|
|
606 |
|
|
-- abstract command autoexec (r/w) --
|
607 |
|
|
when addr_abstractauto_c =>
|
608 |
|
|
dmi_resp_data_o(00) <= dm_reg.abstractauto_autoexecdata; -- autoexecdata(0): read/write access to data0 triggers execution of program buffer
|
609 |
|
|
dmi_resp_data_o(16) <= dm_reg.abstractauto_autoexecprogbuf(0); -- autoexecprogbuf(0): read/write access to progbuf0 triggers execution of program buffer
|
610 |
|
|
dmi_resp_data_o(17) <= dm_reg.abstractauto_autoexecprogbuf(1); -- autoexecprogbuf(1): read/write access to progbuf1 triggers execution of program buffer
|
611 |
|
|
|
612 |
|
|
-- -- next debug module (r/-) --
|
613 |
|
|
-- when addr_nextdm_c =>
|
614 |
|
|
-- dmi_resp_data_o <= (others => '0'); -- this is the only DM
|
615 |
|
|
|
616 |
|
|
-- abstract data 0 (r/w) --
|
617 |
|
|
when addr_data0_c =>
|
618 |
|
|
dmi_resp_data_o <= dci.rdata;
|
619 |
|
|
|
620 |
|
|
-- program buffer (r/w) --
|
621 |
|
|
when addr_progbuf0_c =>
|
622 |
|
|
dmi_resp_data_o <= dm_reg.progbuf(0); -- program buffer 0
|
623 |
|
|
when addr_progbuf1_c =>
|
624 |
|
|
dmi_resp_data_o <= dm_reg.progbuf(1); -- program buffer 1
|
625 |
|
|
|
626 |
|
|
-- system bus access control and status (r/-) --
|
627 |
|
|
when addr_sbcs_c =>
|
628 |
|
|
dmi_resp_data_o <= (others => '0'); -- bus access not implemented
|
629 |
|
|
|
630 |
|
|
-- halt summary 0 (r/-) --
|
631 |
|
|
when addr_haltsum0_c =>
|
632 |
|
|
dmi_resp_data_o(0) <= dm_ctrl.hart_halted; -- hart is halted
|
633 |
|
|
|
634 |
|
|
-- not implemented (r/-) --
|
635 |
|
|
when others =>
|
636 |
|
|
dmi_resp_data_o <= (others => '0');
|
637 |
|
|
end case;
|
638 |
|
|
|
639 |
|
|
-- invalid read access (while command is executing)
|
640 |
|
|
-- ------------------------------------------------------------
|
641 |
|
|
if (dmi_req_valid_i = '1') and (dmi_req_op_i = '0') then -- valid DMI read request
|
642 |
|
|
if (dm_ctrl.busy = '1') then -- busy
|
643 |
|
|
if (dmi_req_addr_i = addr_data0_c) or
|
644 |
|
|
(dmi_req_addr_i = addr_progbuf0_c) or
|
645 |
|
|
(dmi_req_addr_i = addr_progbuf1_c) then
|
646 |
|
|
dm_reg.rd_acc_err <= '1';
|
647 |
|
|
end if;
|
648 |
|
|
end if;
|
649 |
|
|
end if;
|
650 |
|
|
|
651 |
|
|
-- auto execution trigger --
|
652 |
|
|
-- ------------------------------------------------------------
|
653 |
|
|
if (dmi_req_valid_i = '1') and (dmi_req_op_i = '0') then -- valid DMI read request
|
654 |
|
|
if ((dmi_req_addr_i = addr_data0_c) and (dm_reg.abstractauto_autoexecdata = '1')) or
|
655 |
|
|
((dmi_req_addr_i = addr_progbuf0_c) and (dm_reg.abstractauto_autoexecprogbuf(0) = '1')) or
|
656 |
|
|
((dmi_req_addr_i = addr_progbuf1_c) and (dm_reg.abstractauto_autoexecprogbuf(1) = '1')) then
|
657 |
|
|
dm_reg.autoexec_rd <= '1';
|
658 |
|
|
end if;
|
659 |
|
|
end if;
|
660 |
|
|
|
661 |
|
|
end if;
|
662 |
|
|
end process dmi_read_access;
|
663 |
|
|
|
664 |
|
|
|
665 |
|
|
-- **************************************************************************************************************************
|
666 |
|
|
-- CPU Bus Interface
|
667 |
|
|
-- **************************************************************************************************************************
|
668 |
|
|
|
669 |
|
|
-- Access Control ------------------------------------------------------------------------
|
670 |
|
|
-- -------------------------------------------------------------------------------------------
|
671 |
|
|
acc_en <= '1' when (cpu_addr_i(hi_abb_c downto lo_abb_c) = dm_base_c(hi_abb_c downto lo_abb_c)) else '0';
|
672 |
|
|
maddr <= cpu_addr_i(lo_abb_c-1 downto lo_abb_c-2);
|
673 |
|
|
rden <= acc_en and cpu_rden_i;
|
674 |
|
|
wren <= acc_en and cpu_wren_i;
|
675 |
|
|
|
676 |
|
|
|
677 |
|
|
-- Write Access ---------------------------------------------------------------------------
|
678 |
|
|
-- -------------------------------------------------------------------------------------------
|
679 |
|
|
write_access: process(clk_i)
|
680 |
|
|
begin
|
681 |
|
|
if rising_edge(clk_i) then
|
682 |
|
|
-- Data buffer --
|
683 |
|
|
if (dci.data_we = '1') then -- DM write access
|
684 |
|
|
data_buf <= dci.wdata;
|
685 |
|
|
elsif (acc_en = '1') and (maddr = "10") and (wren = '1') then -- BUS write access
|
686 |
|
|
data_buf <= cpu_data_i;
|
687 |
|
|
end if;
|
688 |
|
|
-- Control and Status Register --
|
689 |
|
|
dci.halt_ack <= '0'; -- all writable flags auto-clear
|
690 |
|
|
dci.resume_ack <= '0';
|
691 |
|
|
dci.execute_ack <= '0';
|
692 |
|
|
dci.exception_ack <= '0';
|
693 |
|
|
if (acc_en = '1') and (maddr = "11") and (wren = '1') then
|
694 |
|
|
dci.halt_ack <= cpu_data_i(sreg_halt_ack_c);
|
695 |
|
|
dci.resume_ack <= cpu_data_i(sreg_resume_ack_c);
|
696 |
|
|
dci.execute_ack <= cpu_data_i(sreg_execute_ack_c);
|
697 |
|
|
dci.exception_ack <= cpu_data_i(sreg_exception_ack_c);
|
698 |
|
|
end if;
|
699 |
|
|
end if;
|
700 |
|
|
end process write_access;
|
701 |
|
|
|
702 |
|
|
-- DM data buffer read access --
|
703 |
|
|
dci.rdata <= data_buf;
|
704 |
|
|
|
705 |
|
|
|
706 |
|
|
-- Read Access ----------------------------------------------------------------------------
|
707 |
|
|
-- -------------------------------------------------------------------------------------------
|
708 |
|
|
read_access: process(clk_i)
|
709 |
|
|
begin
|
710 |
|
|
if rising_edge(clk_i) then
|
711 |
|
|
cpu_ack_o <= rden or wren;
|
712 |
|
|
cpu_data_o <= (others => '0');
|
713 |
|
|
if (rden = '1') then -- output gate
|
714 |
|
|
case maddr is -- read data select
|
715 |
|
|
when "00" => -- code ROM
|
716 |
|
|
cpu_data_o <= code_rom_file(to_integer(unsigned(cpu_addr_i(6 downto 2))));
|
717 |
|
|
when "01" => -- program buffer
|
718 |
|
|
cpu_data_o <= cpu_progbuf(to_integer(unsigned(cpu_addr_i(3 downto 2))));
|
719 |
|
|
when "10" => -- data buffer
|
720 |
|
|
cpu_data_o <= data_buf;
|
721 |
|
|
when others => -- status/control register
|
722 |
|
|
cpu_data_o(sreg_resume_req_c) <= dci.resume_req;
|
723 |
|
|
cpu_data_o(sreg_execute_req_c) <= dci.execute_req;
|
724 |
|
|
end case;
|
725 |
|
|
end if;
|
726 |
|
|
end if;
|
727 |
|
|
end process read_access;
|
728 |
|
|
|
729 |
|
|
|
730 |
|
|
end neorv32_debug_dm_rtl;
|