Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add RISC-V debug module to FPGA example #1218

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions examples/fpga/artya7/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,19 @@ fusesoc --cores-root=. run --target=synth --run lowrisc:ibex:top_artya7
```

LED1/LED3 and LED0/LED2 should alternately be on after the FPGA programming is finished.

## Debug

By default, a debug unit compliant with the [RISC-V debug specification](https://github.com/riscv/riscv-debug-spec) v0.13.1 is integrated and is available via JTAG pins on PMOD header JD; the pinouts are:

| PMOD header JD | |
| ------------ | ------------ |
| 1 : TDO | 7 : TDI |
| 2 : TRST_N | 8 : TMS |
| 3 : TCK | 9 : RESET_N |
| 4 | 10 : |
| 5 : GND | 11 : GND |
| 6 : VREF | 12 : VREF |

The Arty board JTAG pinout is a defacto standard by SiFive promulgated in their documents [SiFive Freedom E310 Arty FPGA Dev Kit Getting Started Guide](https://www.sifive.com/documentation/freedom-soc/freedom-e300-arty-fpga-dev-kit-getting-started-guide/) (see Section 2.2), [SiFive Core IP FPGA Eval Kit User Guide Version v2019p05](https://sifive.cdn.prismic.io/sifive%2Fa76dc011-5d11-4d73-9e7a-900640d76f3d_fpga-getting-started_v2019p05.pdf) (see Section 3.2), and [SiFive Core IP FPGA Eval Kit User Guide Version v19.08p0](https://sifive.cdn.prismic.io/sifive%2Ff290f543-87e9-4e0b-8a4a-6287217f79bc_coreip-fpga-eval-userguide-v19_08.pdf) (see Section 3.2).

18 changes: 12 additions & 6 deletions examples/fpga/artya7/data/pins_artya7.xdc
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,21 @@ set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { LED[3]
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L23N_T3_A02_D18_14 Sch=jc_n[4]

## Pmod Header JD
#set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L11N_T1_SRCC_35 Sch=jd[1]
#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L12N_T1_MRCC_35 Sch=jd[2]
#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L13P_T2_MRCC_35 Sch=jd[3]
set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { JTAG_TDO }]; #IO_L11N_T1_SRCC_35 Sch=jd[1]
set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { JTAG_TRST_N }]; #IO_L12N_T1_MRCC_35 Sch=jd[2]
set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { JTAG_TCK }]; #IO_L13P_T2_MRCC_35 Sch=jd[3]
#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L13N_T2_MRCC_35 Sch=jd[4]
#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L14P_T2_SRCC_35 Sch=jd[7]
#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L14N_T2_SRCC_35 Sch=jd[8]
#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15P_T2_DQS_35 Sch=jd[9]
set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { JTAG_TDI }]; #IO_L14P_T2_SRCC_35 Sch=jd[7]
set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { JTAG_TMS }]; #IO_L14N_T2_SRCC_35 Sch=jd[8]
set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { JTAG_RESET_N }]; #IO_L15P_T2_DQS_35 Sch=jd[9]
#set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L15N_T2_DQS_35 Sch=jd[10]

set_property PULLUP true [get_ports { JTAG_TRST_N }];
set_property PULLUP true [get_ports { JTAG_TCK }];
set_property PULLUP true [get_ports { JTAG_TDI }];
set_property PULLUP true [get_ports { JTAG_TMS }];
set_property PULLUP true [get_ports { JTAG_RESET_N }];

## USB-UART Interface
#set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L19N_T3_VREF_16 Sch=uart_rxd_out
#set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L14N_T2_SRCC_16 Sch=uart_txd_in
Expand Down
260 changes: 260 additions & 0 deletions examples/fpga/artya7/rtl/dm_top.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// Top-level debug module (DM)
//
// This module implements the RISC-V debug specification version 0.13,
//
// This toplevel wraps the PULP debug module available from
// https://github.com/pulp-platform/riscv-dbg to match the needs of
// the TL-UL-based lowRISC chip design.

`include "prim_assert.sv"

module dm_top #(
parameter int NrHarts = 1,
parameter logic [31:0] IdcodeValue = 32'h 0000_0001
) (
input logic clk_i, // clock
input logic rst_ni, // asynchronous reset active low, connect PoR
// here, not the system reset
input logic testmode_i,
output logic ndmreset_o, // non-debug module reset
output logic dmactive_o, // debug module is active
output logic [NrHarts-1:0] debug_req_o, // async debug request
input logic [NrHarts-1:0] unavailable_i, // communicate whether the hart is unavailable
// (e.g.: power down)

// bus device with debug memory, for an execution based technique
input logic slave_req_i,
input logic slave_we_i,
input logic [BusWidth-1:0] slave_addr_i,
input logic [BusWidth/8-1:0] slave_be_i,
input logic [BusWidth-1:0] slave_wdata_i,
output logic [BusWidth-1:0] slave_rdata_o,

// bus host, for system bus accesses
output logic master_req_o,
output logic [BusWidth-1:0] master_add_o,
output logic master_we_o,
output logic [BusWidth-1:0] master_wdata_o,
output logic [BusWidth/8-1:0] master_be_o,
input logic master_gnt_i,
input logic master_r_valid_i,
input logic [BusWidth-1:0] master_r_rdata_i,

input jtag_pkg::jtag_req_t jtag_req_i,
output jtag_pkg::jtag_rsp_t jtag_rsp_o
);

`ASSERT_INIT(paramCheckNrHarts, NrHarts > 0)

localparam int BusWidth = 32;
// all harts have contiguous IDs
localparam logic [NrHarts-1:0] SelectableHarts = {NrHarts{1'b1}};

// Debug CSRs
dm::hartinfo_t [NrHarts-1:0] hartinfo;
logic [NrHarts-1:0] halted;
// logic [NrHarts-1:0] running;
logic [NrHarts-1:0] resumeack;
logic [NrHarts-1:0] haltreq;
logic [NrHarts-1:0] resumereq;
logic clear_resumeack;
logic cmd_valid;
dm::command_t cmd;

logic cmderror_valid;
dm::cmderr_e cmderror;
logic cmdbusy;
logic [dm::ProgBufSize-1:0][31:0] progbuf;
logic [dm::DataCount-1:0][31:0] data_csrs_mem;
logic [dm::DataCount-1:0][31:0] data_mem_csrs;
logic data_valid;
logic [19:0] hartsel;
// System Bus Access Module
logic [BusWidth-1:0] sbaddress_csrs_sba;
logic [BusWidth-1:0] sbaddress_sba_csrs;
logic sbaddress_write_valid;
logic sbreadonaddr;
logic sbautoincrement;
logic [2:0] sbaccess;
logic sbreadondata;
logic [BusWidth-1:0] sbdata_write;
logic sbdata_read_valid;
logic sbdata_write_valid;
logic [BusWidth-1:0] sbdata_read;
logic sbdata_valid;
logic sbbusy;
logic sberror_valid;
logic [2:0] sberror;

dm::dmi_req_t dmi_req;
dm::dmi_resp_t dmi_rsp;
logic dmi_req_valid, dmi_req_ready;
logic dmi_rsp_valid, dmi_rsp_ready;
logic dmi_rst_n;

// static debug hartinfo
localparam dm::hartinfo_t DebugHartInfo = '{
zero1: '0,
nscratch: 2, // Debug module needs at least two scratch regs
zero0: 0,
dataaccess: 1'b1, // data registers are memory mapped in the debugger
datasize: dm::DataCount,
dataaddr: dm::DataAddr
};
for (genvar i = 0; i < NrHarts; i++) begin : gen_dm_hart_ctrl
assign hartinfo[i] = DebugHartInfo;
end

dm_csrs #(
.NrHarts(NrHarts),
.BusWidth(BusWidth),
.SelectableHarts(SelectableHarts)
) i_dm_csrs (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.testmode_i ( testmode_i ),
.dmi_rst_ni ( dmi_rst_n ),
.dmi_req_valid_i ( dmi_req_valid ),
.dmi_req_ready_o ( dmi_req_ready ),
.dmi_req_i ( dmi_req ),
.dmi_resp_valid_o ( dmi_rsp_valid ),
.dmi_resp_ready_i ( dmi_rsp_ready ),
.dmi_resp_o ( dmi_rsp ),
.ndmreset_o ( ndmreset_o ),
.dmactive_o ( dmactive_o ),
.hartsel_o ( hartsel ),
.hartinfo_i ( hartinfo ),
.halted_i ( halted ),
.unavailable_i,
.resumeack_i ( resumeack ),
.haltreq_o ( haltreq ),
.resumereq_o ( resumereq ),
.clear_resumeack_o ( clear_resumeack ),
.cmd_valid_o ( cmd_valid ),
.cmd_o ( cmd ),
.cmderror_valid_i ( cmderror_valid ),
.cmderror_i ( cmderror ),
.cmdbusy_i ( cmdbusy ),
.progbuf_o ( progbuf ),
.data_i ( data_mem_csrs ),
.data_valid_i ( data_valid ),
.data_o ( data_csrs_mem ),
.sbaddress_o ( sbaddress_csrs_sba ),
.sbaddress_i ( sbaddress_sba_csrs ),
.sbaddress_write_valid_o ( sbaddress_write_valid ),
.sbreadonaddr_o ( sbreadonaddr ),
.sbautoincrement_o ( sbautoincrement ),
.sbaccess_o ( sbaccess ),
.sbreadondata_o ( sbreadondata ),
.sbdata_o ( sbdata_write ),
.sbdata_read_valid_o ( sbdata_read_valid ),
.sbdata_write_valid_o ( sbdata_write_valid ),
.sbdata_i ( sbdata_read ),
.sbdata_valid_i ( sbdata_valid ),
.sbbusy_i ( sbbusy ),
.sberror_valid_i ( sberror_valid ),
.sberror_i ( sberror )
);

dm_sba #(
.BusWidth(BusWidth)
) i_dm_sba (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.master_req_o ( master_req_o ),
.master_add_o ( master_add_o ),
.master_we_o ( master_we_o ),
.master_wdata_o ( master_wdata_o ),
.master_be_o ( master_be_o ),
.master_gnt_i ( master_gnt_i ),
.master_r_valid_i ( master_r_valid_i ),
.master_r_rdata_i ( master_r_rdata_i ),
.dmactive_i ( dmactive_o ),
.sbaddress_i ( sbaddress_csrs_sba ),
.sbaddress_o ( sbaddress_sba_csrs ),
.sbaddress_write_valid_i ( sbaddress_write_valid ),
.sbreadonaddr_i ( sbreadonaddr ),
.sbautoincrement_i ( sbautoincrement ),
.sbaccess_i ( sbaccess ),
.sbreadondata_i ( sbreadondata ),
.sbdata_i ( sbdata_write ),
.sbdata_read_valid_i ( sbdata_read_valid ),
.sbdata_write_valid_i ( sbdata_write_valid ),
.sbdata_o ( sbdata_read ),
.sbdata_valid_o ( sbdata_valid ),
.sbbusy_o ( sbbusy ),
.sberror_valid_o ( sberror_valid ),
.sberror_o ( sberror )
);

dm_mem #(
.NrHarts(NrHarts),
.BusWidth(BusWidth),
.SelectableHarts(SelectableHarts),
// The debug module provides a simplified ROM for systems that map the debug ROM to offset 0x0
// on the system bus. In that case, only one scratch register has to be implemented in the core.
// However, we require that the DM can be placed at arbitrary offsets in the system, which
// requires the generalized debug ROM implementation and two scratch registers. We hence set
// this parameter to a non-zero value (inside dm_mem, this just feeds into a comparison with 0).
.DmBaseAddress(1)
) i_dm_mem (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.debug_req_o ( debug_req_o ),
.hartsel_i ( hartsel ),
.haltreq_i ( haltreq ),
.resumereq_i ( resumereq ),
.clear_resumeack_i ( clear_resumeack ),
.halted_o ( halted ),
.resuming_o ( resumeack ),
.cmd_valid_i ( cmd_valid ),
.cmd_i ( cmd ),
.cmderror_valid_o ( cmderror_valid ),
.cmderror_o ( cmderror ),
.cmdbusy_o ( cmdbusy ),
.progbuf_i ( progbuf ),
.data_i ( data_csrs_mem ),
.data_o ( data_mem_csrs ),
.data_valid_o ( data_valid ),
.req_i ( slave_req_i ),
.we_i ( slave_we_i ),
.addr_i ( slave_addr_i ),
.wdata_i ( slave_wdata_i ),
.be_i ( slave_be_i ),
.rdata_o ( slave_rdata_o )
);

// Bound-in DPI module replaces the TAP
`ifndef DMIDirectTAP
// JTAG TAP
dmi_jtag #(
.IdcodeValue (IdcodeValue)
) dap (
.clk_i (clk_i),
.rst_ni (rst_ni),
.testmode_i (testmode_i),

.dmi_rst_no (dmi_rst_n),
.dmi_req_o (dmi_req),
.dmi_req_valid_o (dmi_req_valid),
.dmi_req_ready_i (dmi_req_ready),

.dmi_resp_i (dmi_rsp ),
.dmi_resp_ready_o (dmi_rsp_ready),
.dmi_resp_valid_i (dmi_rsp_valid),

//JTAG
.tck_i (jtag_req_i.tck),
.tms_i (jtag_req_i.tms),
.trst_ni (jtag_req_i.trst_n),
.td_i (jtag_req_i.tdi),
.td_o (jtag_rsp_o.tdo),
.tdo_oe_o (jtag_rsp_o.tdo_oe)
);
`endif

endmodule
24 changes: 24 additions & 0 deletions examples/fpga/artya7/rtl/jtag_pkg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//

package jtag_pkg;

typedef struct packed {
logic tck;
logic tms;
logic trst_n;
logic tdi;
} jtag_req_t;

parameter jtag_req_t JTAG_REQ_DEFAULT = '0;

typedef struct packed {
logic tdo;
logic tdo_oe;
} jtag_rsp_t;

parameter jtag_rsp_t JTAG_RSP_DEFAULT = '0;

endpackage : jtag_pkg
Loading