mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-20 03:57:18 -04:00
Initial Debug Module commit
This commit is contained in:
parent
0002d36eac
commit
d54a684966
6 changed files with 1109 additions and 0 deletions
171
debug_module/debug_cfg_types.sv
Normal file
171
debug_module/debug_cfg_types.sv
Normal file
|
@ -0,0 +1,171 @@
|
|||
package debug_cfg_types;
|
||||
|
||||
parameter DTMCS_USER_REG = 3;
|
||||
parameter DMI_USER_REG = 4;
|
||||
parameter HARTSELLEN = 9; //hartselo + hartselhi
|
||||
parameter NUM_CPUS = 4;
|
||||
//parameter integer ASYNC_CPU [NUM_CPUS-1 : 0] = {1,1,1,0};
|
||||
typedef struct packed{
|
||||
logic [31:29] zero1;
|
||||
logic [28:24] progsize;
|
||||
logic [23:13] zero2;
|
||||
logic busy;
|
||||
logic zero3;
|
||||
logic[10:8] cmderr;
|
||||
logic [7:4] zero4;
|
||||
logic [3:0] datacount;
|
||||
} abstract_control_and_status_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic [13:0] zero1;
|
||||
logic dmihardreset;
|
||||
logic dmireset;
|
||||
logic zero2;
|
||||
logic [2:0] idle;
|
||||
logic [1:0] dmistat;
|
||||
logic [5:0] abits;
|
||||
logic [3:0] version;
|
||||
} dtmcs_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic [6:0] address;
|
||||
logic [31:0] data;
|
||||
logic [1:0] op;
|
||||
} dmi_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic [7:0] cmdtype;
|
||||
logic zero1;
|
||||
logic [2:0] size;
|
||||
logic zero2;
|
||||
logic postexec;
|
||||
logic transfer;
|
||||
logic write;
|
||||
logic [15:0] regno;
|
||||
} abstract_command_t;
|
||||
|
||||
//Address map
|
||||
typedef enum bit [6:0] {
|
||||
ABSTRACT_DATA0 = 7'h04,
|
||||
ABSTRACT_DATA1 = 7'h05,
|
||||
ABSTRACT_DATA2 = 7'h06,
|
||||
DEBUG_MODULE_CONTROL = 7'h10,
|
||||
DEBUG_MODULE_STATUS = 7'h11,
|
||||
HART_INFO = 7'h12,
|
||||
HALT_SUMMARY = 7'h13,
|
||||
HART_ARRAY_WINDOW_SELECT = 7'h14,
|
||||
HART_ARRAY_WINDOW = 7'h15,
|
||||
ABSTRACT_CONTROL_AND_STATUS = 7'h16,
|
||||
ABSTRACT_COMMAND = 7'h17,
|
||||
ABSTRACT_COMMAND_AUTOEXEC = 7'h18,
|
||||
CONFIG_STRING_ADDR0 = 7'h19,
|
||||
CONFIG_STRING_ADDR1 = 7'h1a,
|
||||
CONFIG_STRING_ADDR2 = 7'h1b,
|
||||
CONFIG_STRING_ADDR3 = 7'h1c,
|
||||
PROGRAM_BUFFER0 = 7'h20,
|
||||
PROGRAM_BUFFER1 = 7'h21,
|
||||
PROGRAM_BUFFER2 = 7'h22,
|
||||
PROGRAM_BUFFER3 = 7'h23,
|
||||
PROGRAM_BUFFER4 = 7'h24,
|
||||
PROGRAM_BUFFER5 = 7'h25,
|
||||
PROGRAM_BUFFER6 = 7'h26,
|
||||
PROGRAM_BUFFER7 = 7'h27,
|
||||
PROGRAM_BUFFER8 = 7'h28,
|
||||
PROGRAM_BUFFER9 = 7'h29,
|
||||
PROGRAM_BUFFER10 = 7'h2a,
|
||||
PROGRAM_BUFFER11 = 7'h2b,
|
||||
PROGRAM_BUFFER12 = 7'h2c,
|
||||
PROGRAM_BUFFER13 = 7'h2d,
|
||||
PROGRAM_BUFFER14 = 7'h2e,
|
||||
PROGRAM_BUFFER15 = 7'h2f
|
||||
//auth, serial, system bus unused
|
||||
} dm_addr_map_t;
|
||||
|
||||
typedef enum bit [15:0] {
|
||||
DEBUG_CSR = 16'h7b0,
|
||||
DEBUG_PC = 16'h7b1,
|
||||
DEBUG_SCRATCH1 = 16'h7b2,
|
||||
DEBUG_SCRATCH2 = 16'h7b3
|
||||
} riscv_debug_addr_map_t;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
DMI_OP_NOP = 2'b00,
|
||||
DMI_OP_READ = 2'b01,
|
||||
DMI_OP_WRITE = 2'b10,
|
||||
DMI_OP_RESERVED = 2'b11
|
||||
} dmi_jtag_op_t;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
DMI_STATUS_SUCCESS = 2'b00,
|
||||
DMI_STATUS_RESERVED = 2'b01,
|
||||
DMI_STATUS_FAILED = 2'b10,
|
||||
DMI_STATUS_BUSY = 2'b11
|
||||
} dmi_response_op_t;
|
||||
|
||||
//Read only status register
|
||||
typedef struct packed{
|
||||
logic[31:23] zero1;
|
||||
logic impebreak;
|
||||
logic[21:20] zero2;
|
||||
logic allhavereset;
|
||||
logic anyhavereset;
|
||||
logic allresumeack;
|
||||
logic anyresumeack;
|
||||
logic allnonexistent;
|
||||
logic anynonexistent;
|
||||
logic allunavail;
|
||||
logic anyunavail;
|
||||
logic allrunning;
|
||||
logic anyrunning;
|
||||
logic allhalted;
|
||||
logic anyhalted;
|
||||
logic authenticated;
|
||||
logic authbusy;
|
||||
logic zero3;//5
|
||||
logic cfgstrvalid;
|
||||
logic [3:0] version;
|
||||
} DM_Status_t;
|
||||
|
||||
//read-write register
|
||||
typedef struct packed{
|
||||
logic haltreq;
|
||||
logic resumereq;
|
||||
logic hartreset;
|
||||
logic ackhavereset;
|
||||
logic zero1;
|
||||
logic hasel;
|
||||
logic [25:16] hartsello;
|
||||
logic [15:6] hartselhi;
|
||||
logic [5:2] zero2;
|
||||
logic ndmreset;
|
||||
logic dmactive;
|
||||
} DM_control_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic [31:24] zero1;
|
||||
logic [23:20] nscratch;
|
||||
logic [19:17] zero2;
|
||||
logic dataaccess;
|
||||
logic [15:12] datasize;
|
||||
logic [11:0] dataaddr;
|
||||
} hart_info_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [6:0] address;
|
||||
logic [31:0] jtag_data;
|
||||
logic [31:0] dmi_data;
|
||||
logic new_request;
|
||||
logic rnw;
|
||||
logic handled;
|
||||
logic [1:0] response;
|
||||
}dmi_interface_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic [6:0] address;
|
||||
logic [31:0] jtag_data;
|
||||
logic new_request;
|
||||
logic rnw;
|
||||
} jtag_commands_t;
|
||||
endpackage
|
||||
|
||||
|
45
debug_module/debug_interfaces.sv
Normal file
45
debug_module/debug_interfaces.sv
Normal file
|
@ -0,0 +1,45 @@
|
|||
interface dmi_interface;
|
||||
logic [6:0] address;
|
||||
logic [31:0] jtag_data;
|
||||
logic [31:0] dmi_data;
|
||||
logic new_request;
|
||||
logic rnw;
|
||||
logic handled;
|
||||
logic [1:0] response;
|
||||
|
||||
modport jtag (
|
||||
input handled, response, dmi_data,
|
||||
output address, jtag_data, new_request, rnw);
|
||||
modport dmi (
|
||||
output handled, response, dmi_data,
|
||||
input address, jtag_data, new_request, rnw);
|
||||
endinterface
|
||||
|
||||
|
||||
interface dmi_cpu_interface;
|
||||
logic halt;
|
||||
logic resume;
|
||||
logic reset;
|
||||
logic halt_ack;
|
||||
logic resume_ack;
|
||||
logic reset_ack;
|
||||
logic halt_ack_recv;
|
||||
logic resume_ack_recv;
|
||||
logic running;
|
||||
logic [31:0] read_data;
|
||||
logic [31:0] write_data;
|
||||
logic [31:0] read_write_addr;
|
||||
logic [3:0] program_buffer_addr;
|
||||
logic [31:0] program_buffer_data;
|
||||
logic rnw;
|
||||
logic rnw_ack;
|
||||
logic rnw_new_request;
|
||||
|
||||
|
||||
modport dmi (
|
||||
input halt_ack, resume_ack,program_buffer_addr, reset_ack,running,halt_ack_recv,resume_ack_recv,read_data,rnw_ack,
|
||||
output halt, resume,program_buffer_data,reset,write_data,rnw_new_request,rnw,read_write_addr);
|
||||
modport cpu (
|
||||
output halt_ack, resume_ack,program_buffer_addr, reset_ack,running,halt_ack_recv,resume_ack_recv,read_data,rnw_ack,
|
||||
input halt, resume, program_buffer_data,reset,write_data,rnw_new_request,rnw,read_write_addr);
|
||||
endinterface
|
627
debug_module/debug_module.sv
Normal file
627
debug_module/debug_module.sv
Normal file
|
@ -0,0 +1,627 @@
|
|||
import debug_cfg_types::*;
|
||||
|
||||
module debug_module (
|
||||
input logic rst,
|
||||
input logic clk,
|
||||
|
||||
dmi_cpu_interface.dmi debug[NUM_CPUS-1:0],
|
||||
dmi_interface.dmi jtag,
|
||||
|
||||
//SIMULATION ONLY:
|
||||
output DM_Status_t DMS_out,
|
||||
output DM_control_t DMC_out,
|
||||
output abstract_control_and_status_t ACS_out
|
||||
);
|
||||
|
||||
genvar index;
|
||||
DM_Status_t DMS;
|
||||
|
||||
assign DMS.zero1 = 0;
|
||||
assign DMS.zero2 = 0;
|
||||
assign DMS.zero3 = 0;
|
||||
assign DMS.cfgstrvalid = 0;
|
||||
assign DMS.impebreak = 0;
|
||||
//DMS Constants
|
||||
assign DMS.authenticated = 1;//no authentication
|
||||
assign DMS.authbusy = 0;
|
||||
assign DMS.version = 2; //version 0.13
|
||||
assign DMS_out = DMS;
|
||||
DM_control_t DMC;
|
||||
//assign DMC.zero1 = 0;
|
||||
//assign DMC.zero2 = 0;
|
||||
|
||||
//read-only reg
|
||||
//same for all Taiga cores
|
||||
|
||||
hart_info_t hart_info;
|
||||
assign hart_info.zero1 = 0;
|
||||
assign hart_info.zero2 = 0;
|
||||
assign hart_info.nscratch = 2;
|
||||
assign hart_info.dataaccess = 0;
|
||||
assign hart_info.datasize = 3;
|
||||
assign hart_info.dataaddr = 0;
|
||||
|
||||
assign DMC_out = DMC;
|
||||
//read-only reg
|
||||
//Only support < 32 cores
|
||||
logic [31:0] halt_summary;
|
||||
assign halt_summary[31:1] = '0;
|
||||
assign halt_summary[0] = DMS.anyhalted;
|
||||
|
||||
//read-write reg
|
||||
//Only support < 32 cores
|
||||
logic [31:0] hart_array_window_select;
|
||||
//assign hart_array_window_select = 0;
|
||||
|
||||
//read-write reg
|
||||
logic [31:0] hart_array_window;
|
||||
|
||||
//read-only and read-write reg
|
||||
|
||||
abstract_control_and_status_t ABS_CS;
|
||||
assign ABS_CS.zero1 = 0;
|
||||
assign ABS_CS.zero2 = 0;
|
||||
assign ABS_CS.zero3 = 0;
|
||||
assign ABS_CS.zero4 = 0;
|
||||
assign ABS_CS.datacount = 2;
|
||||
assign ABS_CS.progsize = 16;
|
||||
assign ACS_out = ABS_CS;
|
||||
//write-only reg
|
||||
typedef struct packed{
|
||||
logic [31:24] cmdtype;
|
||||
logic [23:0] control;
|
||||
} abstract_command_t;
|
||||
abstract_command_t ABS_COMMAND;
|
||||
|
||||
//abstract command autoexec, unused
|
||||
|
||||
//read-only
|
||||
logic[31:0] cfg_addr0;
|
||||
|
||||
//read-write
|
||||
logic[31:0] abstract_data [2:0];
|
||||
|
||||
//LUT-RAM
|
||||
logic[31:0] program_buffer [7:0];
|
||||
logic[31:0] program_buffer_output;
|
||||
|
||||
logic [31:0] data_out;
|
||||
|
||||
logic write_request;
|
||||
logic new_DMC_req;
|
||||
//Implementation
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
assign write_request = jtag.new_request & ~jtag.rnw;
|
||||
|
||||
|
||||
//DMC
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
DMC.dmactive <= 0;
|
||||
DMC <= 0;
|
||||
new_DMC_req <= 0;
|
||||
end
|
||||
else begin
|
||||
DMC.dmactive <= 1;
|
||||
if (write_request) begin
|
||||
if (jtag.address == DEBUG_MODULE_CONTROL) begin
|
||||
DMC <= jtag.jtag_data;
|
||||
new_DMC_req <= 1;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
new_DMC_req <= 0;
|
||||
end
|
||||
end;
|
||||
end
|
||||
//Write to registers
|
||||
//////////////////
|
||||
//HART_ARRAY_WINDOW_SELECT
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
hart_array_window_select <= 0;
|
||||
else
|
||||
if(write_request & jtag.address == HART_ARRAY_WINDOW_SELECT)
|
||||
hart_array_window_select <= jtag.jtag_data;
|
||||
end
|
||||
|
||||
//HART_ARRAY_WINDOW
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
hart_array_window <= 0;
|
||||
else
|
||||
if(write_request & jtag.address == HART_ARRAY_WINDOW)
|
||||
hart_array_window <= jtag.jtag_data;
|
||||
end
|
||||
//Selected Harts (hasel,hartsel)-----------------------------------------
|
||||
logic[31:0] hartsel_mask;
|
||||
logic[HARTSELLEN:0] selected_hart;
|
||||
assign selected_hart = {DMC.hartselhi,DMC.hartsello}; //Index-based
|
||||
generate
|
||||
|
||||
//for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
for (index = 0; index < 32; index=index+1) begin
|
||||
always_comb begin
|
||||
if(selected_hart == index)
|
||||
hartsel_mask[index] <= 1; //convert index to mask
|
||||
else
|
||||
hartsel_mask[index] <= 0;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
logic[31:0] selected_harts;
|
||||
always_comb begin
|
||||
if(~DMC.hasel)
|
||||
selected_harts <= hartsel_mask;
|
||||
else
|
||||
selected_harts <= hartsel_mask | hart_array_window;
|
||||
end
|
||||
|
||||
//ABS_COMMAND
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
ABS_COMMAND <= 0;
|
||||
else
|
||||
if(write_request & jtag.address == ABSTRACT_COMMAND)
|
||||
ABS_COMMAND <= jtag.jtag_data;
|
||||
end
|
||||
//ABS_DATA0------------return data for abstract commands
|
||||
logic[31:0][NUM_CPUS-1:0] abs_cmd_return;
|
||||
logic[NUM_CPUS-1:0] abs_cmd_sig;
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
abs_cmd_return[index] <= 0;
|
||||
abs_cmd_sig[index] <= 0;
|
||||
end
|
||||
else begin
|
||||
if(debug[index].rnw_ack && debug[index].rnw) begin
|
||||
abs_cmd_return[index] <= debug[index].read_data;
|
||||
abs_cmd_sig[index] <= 1;
|
||||
end
|
||||
else begin
|
||||
abs_cmd_return[index] <= 0;
|
||||
abs_cmd_sig[index] <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
abstract_data[0] <= 0;
|
||||
else
|
||||
if(write_request & jtag.address == ABSTRACT_DATA0)
|
||||
abstract_data[0] <= jtag.jtag_data;
|
||||
else if(|abs_cmd_sig)
|
||||
abstract_data[0] <= abs_cmd_return[selected_hart]; //PROBLEM: THIS NEEDS TO BE OBTAINED FROM THE CORRECT PROCESSOR
|
||||
end
|
||||
//ABS_DATA1
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
abstract_data[1] <= 0;
|
||||
else
|
||||
if(write_request & jtag.address == ABSTRACT_DATA1)
|
||||
abstract_data[1] <= jtag.jtag_data;
|
||||
end
|
||||
|
||||
//ABS_DATA2
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
abstract_data[2] <= 0;
|
||||
else
|
||||
if(write_request & jtag.address == ABSTRACT_DATA2)
|
||||
abstract_data[2] <= jtag.jtag_data;
|
||||
end
|
||||
//////////////////
|
||||
|
||||
//program_buffer
|
||||
always_ff @ (posedge clk) begin
|
||||
if (write_request && jtag.address >= 7'h20 && jtag.address < 7'h30)
|
||||
program_buffer[jtag.address[3:0]] <= jtag.jtag_data;
|
||||
end
|
||||
assign program_buffer_output = program_buffer[jtag.address[3:0]];
|
||||
|
||||
//read mux
|
||||
always_comb begin
|
||||
case(jtag.address)
|
||||
ABSTRACT_DATA0 : data_out <= abstract_data[0];
|
||||
ABSTRACT_DATA1 : data_out <= abstract_data[1];
|
||||
ABSTRACT_DATA2 : data_out <= abstract_data[2];
|
||||
DEBUG_MODULE_CONTROL : data_out <= DMC;
|
||||
DEBUG_MODULE_STATUS : data_out <= DMS;
|
||||
HART_INFO : data_out <= hart_info;
|
||||
HALT_SUMMARY : data_out <= halt_summary;
|
||||
HART_ARRAY_WINDOW_SELECT : data_out <= hart_array_window_select;
|
||||
HART_ARRAY_WINDOW : data_out <= hart_array_window;
|
||||
ABSTRACT_CONTROL_AND_STATUS : data_out <= ABS_CS;
|
||||
ABSTRACT_COMMAND : data_out <= ABS_COMMAND;
|
||||
ABSTRACT_COMMAND_AUTOEXEC : data_out <= '0;
|
||||
CONFIG_STRING_ADDR0 : data_out <= '0;
|
||||
CONFIG_STRING_ADDR1 : data_out <= '0;
|
||||
CONFIG_STRING_ADDR2 : data_out <= '0;
|
||||
CONFIG_STRING_ADDR3 : data_out <= '0;
|
||||
PROGRAM_BUFFER0 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER1 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER2 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER3 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER4 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER5 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER6 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER7 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER8 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER9 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER10 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER11 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER12 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER13 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER14 : data_out <= program_buffer_output;
|
||||
PROGRAM_BUFFER15 : data_out <= program_buffer_output;
|
||||
default : data_out <= '0;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
jtag.handled <= jtag.new_request;
|
||||
end
|
||||
|
||||
assign jtag.response = DMI_STATUS_SUCCESS;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
jtag.dmi_data <= data_out;
|
||||
end
|
||||
|
||||
|
||||
|
||||
//Are Cores Running Check-------------------------------------------------------------------------
|
||||
logic [NUM_CPUS-1:0] all_running_array;
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_comb begin
|
||||
all_running_array[index] <= debug[index].running;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
DMS.allrunning <= 0;
|
||||
DMS.anyrunning <= 0;
|
||||
end
|
||||
else
|
||||
DMS.allrunning <= &(all_running_array | ~selected_harts) && |selected_harts;
|
||||
DMS.anyrunning <= |(all_running_array & selected_harts);
|
||||
end
|
||||
|
||||
//Hart Resets Requests-------------------------------------------------------------------------
|
||||
//Requests & Acknowledgements-----------------
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
debug[index].reset <= 0;
|
||||
else begin
|
||||
if(DMC.hartreset && new_DMC_req) begin //Send New Requests
|
||||
debug[index].reset <= selected_harts[index];
|
||||
|
||||
end
|
||||
else if(debug[index].reset_ack == 1 || DMC.hartreset == 0) begin //Wait for Ack OR Debugger has unset the reset bit
|
||||
debug[index].reset <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
//Status Register Updates-----------------
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
DMS.allhavereset <= 0;
|
||||
DMS.anyhavereset <= 0;
|
||||
end
|
||||
else
|
||||
if(DMC.hartreset) begin
|
||||
DMS.allhavereset <= 1;
|
||||
DMS.anyhavereset <= 1;
|
||||
end
|
||||
else if(DMC.ackhavereset)begin //clear only if Debugger has acknowledge the reset
|
||||
DMS.allhavereset <= 0;
|
||||
DMS.anyhavereset <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
//Halt RequestsRequests-------------------------------------------------------------------------
|
||||
//Requests & Acknowledgements-----------------
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
debug[index].halt <= 0;
|
||||
else begin
|
||||
if(DMC.haltreq && new_DMC_req) begin //Send New Requests
|
||||
debug[index].halt <= selected_harts[index];
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 1 && debug[index].running) //From Abstract Command
|
||||
debug[index].halt <= hartsel_mask[index];
|
||||
else if(debug[index].halt_ack == 1) begin //Wait for Ack
|
||||
debug[index].halt <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
//Status Register Updates--------------------
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
DMS.allhalted <= 0;
|
||||
DMS.anyhalted <= 0;
|
||||
end
|
||||
else
|
||||
DMS.allhalted <= &(~all_running_array | ~selected_harts) && |selected_harts;
|
||||
DMS.anyhalted <= |(~all_running_array & selected_harts);
|
||||
end
|
||||
|
||||
//Resume Requests-------------------------------------------------------------------------
|
||||
//Requests & Acknowledgements-----------------
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
debug[index].resume <= 0;
|
||||
else begin
|
||||
if(DMC.resumereq && new_DMC_req && ~DMC.haltreq) begin //Send New Requests
|
||||
debug[index].resume <= selected_harts[index];
|
||||
|
||||
end
|
||||
else if(debug[index].resume_ack == 1) begin //Wait for Ack
|
||||
debug[index].resume <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
//Status Register Updates--------------------NOTE: This checks for the ACKS not the current status
|
||||
logic [NUM_CPUS-1:0] all_resume_ack_array;
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_comb begin
|
||||
if(DMC.resumereq && selected_harts[index] && ~DMC.haltreq && new_DMC_req) //if a new request is sent, reset the bit
|
||||
all_resume_ack_array[index] <= 0;
|
||||
if(debug[index].resume_ack) //only set bit if the ack has been recieved
|
||||
all_resume_ack_array[index] <= 1;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
DMS.allresumeack <= 0;
|
||||
DMS.anyresumeack <= 0;
|
||||
end
|
||||
else
|
||||
if(DMC.resumereq) begin
|
||||
DMS.allresumeack <= &(all_resume_ack_array|~selected_harts) && |selected_harts;
|
||||
DMS.anyresumeack <= |(all_resume_ack_array & selected_harts);
|
||||
end
|
||||
else begin // Do I need to set this to 0?
|
||||
DMS.allresumeack <= 0;
|
||||
DMS.anyresumeack <= 0;
|
||||
end
|
||||
|
||||
end
|
||||
//ALL/ANY nonexistent,allunavailallunavail------------
|
||||
|
||||
logic [31:0] non_exist_array;
|
||||
generate
|
||||
for (index = 0; index < 32; index=index+1) begin
|
||||
always_comb begin
|
||||
if(index > NUM_CPUS)
|
||||
non_exist_array[index] <= 1;
|
||||
else
|
||||
non_exist_array[index] <= 0;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
DMS.allnonexistent <= 0;
|
||||
DMS.anynonexistent <= 0;
|
||||
DMS.allunavail <= 0;
|
||||
DMS.anyunavail <= 0;
|
||||
end
|
||||
else begin
|
||||
DMS.allnonexistent <= &(non_exist_array|~selected_harts) && |selected_harts;
|
||||
DMS.anynonexistent <= |(non_exist_array & selected_harts);
|
||||
//DMS.allunavail <= &(non_exist_array|~selected_harts) && |selected_harts;
|
||||
//DMS.anyunavail <= |(non_exist_array & selected_harts);
|
||||
end
|
||||
end
|
||||
|
||||
//Abtract Commands----------------------------------------------------------------
|
||||
//TO-DO: DID WE IMPLEMENT POSTEXEC
|
||||
logic new_ABSTRACT_req;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
new_ABSTRACT_req <= 0;
|
||||
end
|
||||
else begin
|
||||
if (write_request && jtag.address == ABSTRACT_COMMAND) begin
|
||||
new_ABSTRACT_req <= 1;
|
||||
end
|
||||
else begin
|
||||
new_ABSTRACT_req <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
logic [NUM_CPUS-1:0] abstract_ack_array;
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_comb begin
|
||||
if(new_ABSTRACT_req && hartsel_mask[index]) //if a new request is sent, reset the bit
|
||||
abstract_ack_array[index] <= 0;
|
||||
if(debug[index].rnw_ack) //only set bit if the ack has been recieved
|
||||
abstract_ack_array[index] <= 1;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//Requests-----------------
|
||||
logic[31:0][NUM_CPUS-1:0] program_buffer_addr;
|
||||
logic execute_program_buffer;
|
||||
logic [NUM_CPUS-1:0]execute_program_buffer_postexec;
|
||||
logic [NUM_CPUS-1:0]execute_program_buffer_auto;
|
||||
logic [NUM_CPUS-1:0]new_execute_program_buffer_req;
|
||||
assign execute_program_buffer = |execute_program_buffer_postexec | |execute_program_buffer_auto; //note do we need a hartsel_mask here?
|
||||
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_comb begin
|
||||
program_buffer_addr[index] <= debug[index].program_buffer_addr;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
logic halted_hartsel;
|
||||
assign halted_hartsel = |(hartsel_mask && ~all_running_array);
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
ABS_CS.busy <= 0;
|
||||
ABS_CS.cmderr <= 0;
|
||||
end
|
||||
else begin
|
||||
if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[22:20] != 2 && new_ABSTRACT_req) begin //If the size of the command is > 32
|
||||
ABS_CS.busy <= 0;
|
||||
ABS_CS.cmderr <= 2;
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 0 && (ABS_COMMAND[15:0] != DEBUG_CSR && ABS_COMMAND[15:0] != DEBUG_PC && ABS_COMMAND[15:0] != DEBUG_SCRATCH1 && ABS_COMMAND[15:0] != DEBUG_SCRATCH2) && new_ABSTRACT_req) begin //Address not readable
|
||||
ABS_CS.busy <= 0;
|
||||
ABS_CS.cmderr <= 2;
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 1 && halted_hartsel) begin //If quick access is the abstract command, but the core is already halted
|
||||
ABS_CS.busy <= 0;
|
||||
ABS_CS.cmderr <= 2;
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[17] && ~ABS_COMMAND[16] && new_ABSTRACT_req) begin //Transfer
|
||||
ABS_CS.busy <= 1;
|
||||
ABS_CS.cmderr <= 0;
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[17] && ABS_COMMAND[16] && new_ABSTRACT_req) begin //Write
|
||||
ABS_CS.busy <= 1;
|
||||
ABS_CS.cmderr <= 0;
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 1 && ABS_COMMAND[17] && ABS_COMMAND[16] && new_ABSTRACT_req) begin //Write
|
||||
ABS_CS.busy <= 1;
|
||||
ABS_CS.cmderr <= 0;
|
||||
end
|
||||
else if(|abstract_ack_array && ~ABS_COMMAND[18]) begin //CASE 1: no execution of program buffer
|
||||
ABS_CS.busy <= 0;
|
||||
ABS_CS.cmderr <= 0;
|
||||
end
|
||||
else if(|abstract_ack_array && ABS_COMMAND[18] && program_buffer_addr[selected_hart] == 31'h2F) begin //CASE 2: execution of program buffer. WE have finished the Program Buffer
|
||||
ABS_CS.busy <= 0;
|
||||
ABS_CS.cmderr <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
debug[index].rnw <= 0;
|
||||
debug[index].rnw_new_request <= 0;
|
||||
execute_program_buffer_postexec[index] <= 0;
|
||||
execute_program_buffer_auto [index] <= 0;
|
||||
debug[index].write_data <= 0;
|
||||
debug[index].read_write_addr <= 0;
|
||||
end
|
||||
else begin
|
||||
execute_program_buffer_postexec[index] <= 0; //Only 1 when rnw_ack has been recieved for the first time and postexec is true
|
||||
if(execute_program_buffer) begin //happens in the next cycle after directly above code
|
||||
debug[index].write_data <= 31'h20; //write data always comes from data0 register for 32-bits
|
||||
debug[index].read_write_addr <= 16'h7b1;
|
||||
debug[index].rnw <= 0;
|
||||
debug[index].rnw_new_request <= hartsel_mask[index];
|
||||
new_execute_program_buffer_req[index] <= 0;
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[17] && ~ABS_COMMAND[16] && new_ABSTRACT_req) begin //Read/Transfer
|
||||
debug[index].rnw <= 1;
|
||||
debug[index].rnw_new_request <= hartsel_mask[index]; //WE HAVE TO USE ONLY THE HARTSEL MASK AND NOT THE ARRAY MASK
|
||||
debug[index].write_data <= abstract_data[0]; //write data always comes from data0 register for 32-bits
|
||||
debug[index].read_write_addr <= ABS_COMMAND[15:0];
|
||||
if(ABS_COMMAND[18])
|
||||
new_execute_program_buffer_req[index] <= 1;
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[17] && ABS_COMMAND[16] && new_ABSTRACT_req) begin //Write
|
||||
debug[index].rnw <= 0;
|
||||
debug[index].rnw_new_request <= hartsel_mask[index]; //WE HAVE TO USE ONLY THE HARTSEL MASK AND NOT THE ARRAY MASK
|
||||
debug[index].write_data <= abstract_data[0]; //write data always comes from data0 register for 32-bits
|
||||
debug[index].read_write_addr <= ABS_COMMAND[15:0];
|
||||
if(ABS_COMMAND[18])
|
||||
new_execute_program_buffer_req[index] <= 1;
|
||||
end
|
||||
else if(debug[index].rnw_ack) begin
|
||||
debug[index].rnw_new_request <= 0;
|
||||
if(ABS_COMMAND[18]) begin //postexec
|
||||
if(execute_program_buffer_postexec[index] == 0 && execute_program_buffer_auto [index]== 0 && new_execute_program_buffer_req[index]) begin
|
||||
execute_program_buffer_postexec[index] <= 1; // activation signal
|
||||
new_execute_program_buffer_req[index] <= 0;
|
||||
//execute_program_buffer <= 1; //CANT DO THIS SINCE IT'S A FOR LOOP
|
||||
end
|
||||
else begin
|
||||
//execute_program_buffer <= 1; //CAN'T DO THIS SINCE IT'S A FOR LOOP
|
||||
execute_program_buffer_postexec[index]<= 0; //program bufer execution started
|
||||
end
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 1) begin //Quick access
|
||||
execute_program_buffer_auto[index]<= 0; //program bufer execution started //ERROR ITS IN A FOR LOOP
|
||||
//execute_program_buffer <= 1;
|
||||
end
|
||||
end
|
||||
else if(ABS_COMMAND.cmdtype == 1 && ~debug[index].running && new_ABSTRACT_req) begin
|
||||
execute_program_buffer_auto[index] <= 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//Program Buffer - Processor Interface
|
||||
generate
|
||||
for (index = 0; index < NUM_CPUS; index=index+1) begin
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
debug[index].program_buffer_data <= 0;
|
||||
end
|
||||
else begin
|
||||
case(debug[index].program_buffer_addr)
|
||||
31'h20 : debug[index].program_buffer_data <= PROGRAM_BUFFER0;
|
||||
31'h21 : debug[index].program_buffer_data <= PROGRAM_BUFFER1;
|
||||
31'h22 : debug[index].program_buffer_data <= PROGRAM_BUFFER2;
|
||||
31'h23 : debug[index].program_buffer_data <= PROGRAM_BUFFER3;
|
||||
31'h24 : debug[index].program_buffer_data <= PROGRAM_BUFFER4;
|
||||
31'h25 : debug[index].program_buffer_data <= PROGRAM_BUFFER5;
|
||||
31'h26 : debug[index].program_buffer_data <= PROGRAM_BUFFER6;
|
||||
31'h27 : debug[index].program_buffer_data <= PROGRAM_BUFFER7;
|
||||
31'h28 : debug[index].program_buffer_data <= PROGRAM_BUFFER8;
|
||||
31'h29 : debug[index].program_buffer_data <= PROGRAM_BUFFER9;
|
||||
31'h2A : debug[index].program_buffer_data <= PROGRAM_BUFFER10;
|
||||
31'h2B : debug[index].program_buffer_data <= PROGRAM_BUFFER11;
|
||||
31'h2C : debug[index].program_buffer_data <= PROGRAM_BUFFER12;
|
||||
31'h2D : debug[index].program_buffer_data <= PROGRAM_BUFFER13;
|
||||
31'h2E : debug[index].program_buffer_data <= PROGRAM_BUFFER14;
|
||||
31'h2F : debug[index].program_buffer_data <= PROGRAM_BUFFER15;
|
||||
default : debug[index].program_buffer_data <= 0;
|
||||
endcase
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
125
debug_module/jtag_module.sv
Normal file
125
debug_module/jtag_module.sv
Normal file
|
@ -0,0 +1,125 @@
|
|||
import debug_cfg_types::*;
|
||||
|
||||
module jtag_module (
|
||||
input logic clk,
|
||||
output logic reset,
|
||||
|
||||
dmi_interface.jtag dm
|
||||
);
|
||||
|
||||
dtmcs_t dtmcs, dtmcs_jtag;
|
||||
dmi_t dmi, dmi_jtag;
|
||||
|
||||
logic dtmcs_write;
|
||||
logic dmi_write;
|
||||
|
||||
logic dmi_busy;
|
||||
logic dmi_error;
|
||||
|
||||
jtag_registers jtag_regs(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.current_dtmcs(dtmcs),
|
||||
.updated_dtmcs(dtmcs_jtag),
|
||||
.update_dtmcs(dtmcs_write),
|
||||
|
||||
.current_dmi(dmi),
|
||||
.updated_dmi(dmi_jtag),
|
||||
.update_dmi(dmi_write)
|
||||
);
|
||||
|
||||
//dtmcs register
|
||||
assign dtmcs.zero1 = 0;
|
||||
assign dtmcs.dmihardreset = 0;
|
||||
assign dtmcs.dmireset = 0;
|
||||
assign dtmcs.zero2 = 0;
|
||||
assign dtmcs.idle = 20;
|
||||
//dmistat
|
||||
assign dtmcs.abits = 7;
|
||||
assign dtmcs.version = 1;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (reset)
|
||||
dtmcs.dmistat <= DMI_STATUS_SUCCESS;
|
||||
else if (dtmcs_write & (dtmcs_jtag.dmireset | dtmcs_jtag.dmihardreset)) //clear error status
|
||||
dtmcs.dmistat <= DMI_STATUS_SUCCESS;
|
||||
else if (dmi_write & dmi_busy)
|
||||
dtmcs.dmistat <= DMI_STATUS_BUSY;
|
||||
else if (dm.handled & ~dmi_error)
|
||||
dtmcs.dmistat <= dm.response;
|
||||
end
|
||||
////////////////////////////////////////
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (reset)
|
||||
dmi_busy <= 0;
|
||||
else if (dtmcs_write & (dtmcs_jtag.dmireset | dtmcs_jtag.dmihardreset))
|
||||
dmi_busy <= 0;
|
||||
else if (dmi_write & ~dmi_busy)
|
||||
dmi_busy <= 1;
|
||||
else if (dm.handled)
|
||||
dmi_busy <= 0;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (reset)
|
||||
dmi_error <= 0;
|
||||
else if (dtmcs_write & (dtmcs_jtag.dmireset | dtmcs_jtag.dmihardreset))
|
||||
dmi_error <= 0;
|
||||
else if ((dmi_write & dmi_busy) ||
|
||||
(dm.handled && dm.response == DMI_STATUS_FAILED))
|
||||
dmi_error <= 1;
|
||||
//dmi_error <= 0; //Test
|
||||
|
||||
end
|
||||
|
||||
//dmi reg
|
||||
always_ff @ (posedge clk) begin
|
||||
if (reset)
|
||||
dmi.address <= 0;
|
||||
else if (dmi_write & ~(dmi_busy | dmi_error))
|
||||
dmi.address <= dmi_jtag.address;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (reset)
|
||||
dmi.data <= 0;
|
||||
else if (dmi_write & ~(dmi_busy | dmi_error) && (dmi_jtag.op == DMI_OP_WRITE))
|
||||
dmi.data <= dmi_jtag.data;
|
||||
else if (dm.handled)
|
||||
dmi.data <= dm.dmi_data;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (reset)
|
||||
dmi.op <= DMI_STATUS_SUCCESS;
|
||||
else if (dtmcs_write & (dtmcs_jtag.dmireset | dtmcs_jtag.dmihardreset))
|
||||
dmi.op <= DMI_STATUS_SUCCESS;
|
||||
else if (dmi_write & ~(dmi_busy | dmi_error))
|
||||
dmi.op <= dmi_jtag.op;
|
||||
else if (dmi_write & dmi_busy & ~dmi_error)
|
||||
dmi.op <= DMI_STATUS_BUSY;
|
||||
else if (dm.handled & ~dmi_error)
|
||||
dmi.op <= dm.response;
|
||||
end
|
||||
|
||||
//Output logic
|
||||
assign dm.address = dmi.address;
|
||||
assign dm.jtag_data = dmi.data;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (dmi_write & ~(dmi_busy | dmi_error))
|
||||
dm.rnw <= (dmi_jtag.op == DMI_OP_READ) || (dmi_jtag.op == DMI_OP_NOP);
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (reset)
|
||||
dm.new_request <= 0;
|
||||
else if (dmi_write & ~(dmi_busy | dmi_error))
|
||||
dm.new_request <= (dmi_jtag.op == DMI_OP_READ) || (dmi_jtag.op == DMI_OP_WRITE) || (dmi_jtag.op == DMI_OP_NOP);
|
||||
else
|
||||
dm.new_request <= 0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
101
debug_module/jtag_register.sv
Normal file
101
debug_module/jtag_register.sv
Normal file
|
@ -0,0 +1,101 @@
|
|||
|
||||
module jtag_register
|
||||
#(
|
||||
parameter C_WIDTH = 32,
|
||||
parameter C_ID = 3
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
output logic reset_out,
|
||||
input logic [C_WIDTH-1:0] data_in,
|
||||
output logic [C_WIDTH-1:0] data_out,
|
||||
output logic new_data
|
||||
);
|
||||
|
||||
logic capture, drck_i, tck, drck, reset, sel, shift, tdi, update, tdo;
|
||||
logic [C_WIDTH-1:0] captured_data;
|
||||
logic [C_WIDTH-1:0] jtag_data;
|
||||
logic ack;
|
||||
|
||||
localparam SYNC_STAGES = 3;
|
||||
logic new_data_sync [SYNC_STAGES-1:0];
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
BUFG drck_bufg (.O(drck), .I(drck_i));
|
||||
|
||||
BSCANE2 #( .JTAG_CHAIN(C_ID))
|
||||
bscan (
|
||||
.CAPTURE (capture),
|
||||
.DRCK (drck_i),
|
||||
.RESET (reset),
|
||||
.RUNTEST (),
|
||||
.SEL (sel),
|
||||
.SHIFT (shift),
|
||||
.TCK (tck),
|
||||
.TDI (tdi),
|
||||
.TMS (),
|
||||
.UPDATE (update),
|
||||
.TDO (tdo)
|
||||
);
|
||||
|
||||
assign reset_out = reset;
|
||||
|
||||
//X stage Synchronizers for handshaking
|
||||
always_ff @(posedge update or posedge reset or posedge ack) begin
|
||||
if (reset | ack)
|
||||
new_data_sync[0] <= 0;
|
||||
else begin
|
||||
if (sel)
|
||||
new_data_sync[0] <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i=1; i < SYNC_STAGES; i++) begin
|
||||
always_ff @(posedge clk or posedge reset) begin
|
||||
if (reset)
|
||||
new_data_sync[i] <= 0;
|
||||
else begin
|
||||
new_data_sync[i] <= new_data_sync[i-1];
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_ff @(posedge clk or posedge reset) begin
|
||||
if (reset)
|
||||
ack <= 0;
|
||||
else begin
|
||||
ack <= new_data_sync[SYNC_STAGES-1];
|
||||
end
|
||||
end
|
||||
|
||||
assign new_data = ack & ~new_data_sync[SYNC_STAGES-1];
|
||||
|
||||
//JTAG Data Register logic as per XAPP139
|
||||
always_ff @(posedge drck or posedge reset) begin
|
||||
if (reset)
|
||||
captured_data <= '0;
|
||||
else begin
|
||||
if (capture & sel)
|
||||
captured_data <= data_in;
|
||||
else if (shift & sel)
|
||||
captured_data <= {tdi, captured_data[C_WIDTH-1:1]};
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge update or posedge reset) begin
|
||||
if (reset)
|
||||
jtag_data <= 0;
|
||||
else begin
|
||||
if (sel)
|
||||
jtag_data <= captured_data;
|
||||
end
|
||||
end
|
||||
assign data_out = jtag_data;
|
||||
assign tdo = captured_data[0];
|
||||
|
||||
|
||||
endmodule
|
||||
|
40
debug_module/jtag_registers.sv
Normal file
40
debug_module/jtag_registers.sv
Normal file
|
@ -0,0 +1,40 @@
|
|||
import debug_cfg_types::*;
|
||||
|
||||
module jtag_registers (
|
||||
input logic clk,
|
||||
output logic reset,
|
||||
|
||||
input dtmcs_t current_dtmcs,
|
||||
output dtmcs_t updated_dtmcs,
|
||||
output update_dtmcs,
|
||||
|
||||
input dmi_t current_dmi,
|
||||
output dmi_t updated_dmi,
|
||||
output update_dmi
|
||||
);
|
||||
|
||||
jtag_register
|
||||
#( .C_WIDTH($bits(dtmcs_t)), .C_ID(DTMCS_USER_REG))
|
||||
dtmcs_jtag_block
|
||||
(
|
||||
.clk (clk),
|
||||
.reset_out(reset),
|
||||
.data_in(current_dtmcs),
|
||||
.data_out(updated_dtmcs),
|
||||
.new_data(update_dtmcs)
|
||||
);
|
||||
|
||||
jtag_register
|
||||
#( .C_WIDTH($bits(dmi_t)), .C_ID(DMI_USER_REG))
|
||||
dmi_jtag_block
|
||||
(
|
||||
.clk (clk),
|
||||
.reset_out(),
|
||||
.data_in(current_dmi),
|
||||
.data_out(updated_dmi),
|
||||
.new_data(update_dmi)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue