Switch CDC implementation to safer variant

This commit is contained in:
Florian Zaruba 2018-09-07 17:01:59 +02:00
parent af3182b860
commit 9ab76b9243
No known key found for this signature in database
GPG key ID: E742FFE8EC38A792
11 changed files with 174 additions and 645 deletions

View file

@ -9,7 +9,7 @@ dependencies:
axi_node: { git: "git@iis-git.ee.ethz.ch:pulp-open/axi_node.git", version: 1.0.3 }
axi_slice: { git: "git@iis-git.ee.ethz.ch:sasa/axi_slice.git", version: 1.1.2 }
tech_cells_generic: { git: "git@iis-git.ee.ethz.ch:pulp-open/tech_cells_generic.git", rev: master }
common_cells: { git: "git@iis-git.ee.ethz.ch:sasa/common_cells.git", version: v1.7.0 }
common_cells: { git: "git@iis-git.ee.ethz.ch:sasa/common_cells.git", version: v1.7.4 }
fpga-support: { git: "https://github.com/pulp-platform/fpga-support.git", version: v0.3.2 }
sources:
- include/riscv_pkg.sv

View file

@ -51,7 +51,7 @@ src := $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv)) \
src/axi/src/axi_join.sv \
src/fpga-support/rtl/SyncSpRamBeNx64.sv \
src/common_cells/src/deprecated/generic_fifo.sv \
src/common_cells/src/sync.sv \
src/common_cells/src/cdc_2phase.sv \
src/common_cells/src/spill_register.sv \
src/common_cells/src/sync_wedge.sv \
src/common_cells/src/fifo_v2.sv \

View file

@ -26,7 +26,6 @@ module ariane #(
)(
input logic clk_i,
input logic rst_ni,
input logic test_en_i, // enable all clock gates for testing
// Core ID, Cluster ID and boot address are considered more or less static
input logic [63:0] boot_addr_i, // reset boot address
input logic [ 3:0] core_id_i, // core id in a multicore environment (reflected in a CSR)

View file

@ -24,14 +24,11 @@ module dm_csrs #(
input logic dmi_rst_ni, // Debug Module Interface reset, active-low
input logic dmi_req_valid_i,
output logic dmi_req_ready_o,
input logic [ 6:0] dmi_req_bits_addr_i,
input logic [ 1:0] dmi_req_bits_op_i, // 0 = nop, 1 = read, 2 = write
input logic [31:0] dmi_req_bits_data_i,
input dm::dmi_req_t dmi_req_i,
// every request needs a response one cycle later
output logic dmi_resp_valid_o,
input logic dmi_resp_ready_i,
output logic [ 1:0] dmi_resp_bits_resp_o,
output logic [31:0] dmi_resp_bits_data_o,
output dm::dmi_resp_t dmi_resp_o,
// global ctrl
output logic ndmreset_o, // non-debug module reset, active-high
output logic dmactive_o, // 1 -> debug-module is active, 0 -> synchronous re-set
@ -80,7 +77,7 @@ module dm_csrs #(
// the amount of bits we need to represent all harts
localparam HartSelLen = (NrHarts == 1) ? 1 : $clog2(NrHarts);
dm::dtm_op_t dtm_op;
assign dtm_op = dm::dtm_op_t'(dmi_req_bits_op_i);
assign dtm_op = dm::dtm_op_t'(dmi_req_i.op);
logic resp_queue_full;
logic resp_queue_empty;
@ -121,7 +118,7 @@ module dm_csrs #(
logic [NrHarts-1:0] selected_hart;
// a successful response returns zero
assign dmi_resp_bits_resp_o = dm::DTM_SUCCESS;
assign dmi_resp_o.resp = dm::DTM_SUCCESS;
assign dmi_resp_valid_o = ~resp_queue_empty;
assign dmi_req_ready_o = ~resp_queue_full;
assign resp_queue_push = dmi_req_valid_i & dmi_req_ready_o;
@ -197,14 +194,14 @@ module dm_csrs #(
// reads
if (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_READ) begin
unique case ({1'b0, dmi_req_bits_addr_i}) inside
unique case ({1'b0, dmi_req_i.addr}) inside
[(dm::Data0):DataEnd]: begin
if (dm::DataCount > 0) begin
resp_queue_data = data_q[dmi_req_bits_addr_i[4:0]];
resp_queue_data = data_q[dmi_req_i.addr[4:0]];
end
if (!cmdbusy_i) begin
// check whether we need to re-execute the command (just give a cmd_valid)
cmd_valid_o = abstractauto_q.autoexecdata[dmi_req_bits_addr_i[3:0] - dm::Data0];
cmd_valid_o = abstractauto_q.autoexecdata[dmi_req_i.addr[3:0] - dm::Data0];
end
end
dm::DMControl: resp_queue_data = dmcontrol_q;
@ -215,10 +212,10 @@ module dm_csrs #(
// command is read-only
dm::Command: resp_queue_data = '0;
[(dm::ProgBuf0):ProgBufEnd]: begin
resp_queue_data = progbuf_q[dmi_req_bits_addr_i[4:0]];
resp_queue_data = progbuf_q[dmi_req_i.addr[4:0]];
if (!cmdbusy_i) begin
// check whether we need to re-execute the command (just give a cmd_valid)
cmd_valid_o = abstractauto_q.autoexecprogbuf[dmi_req_bits_addr_i[3:0]];
cmd_valid_o = abstractauto_q.autoexecprogbuf[dmi_req_i.addr[3:0]];
end
end
dm::HaltSum0: resp_queue_data = haltsum0;
@ -269,23 +266,23 @@ module dm_csrs #(
// write
if (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_WRITE) begin
unique case (dm::dm_csr_t'({1'b0, dmi_req_bits_addr_i})) inside
unique case (dm::dm_csr_t'({1'b0, dmi_req_i.addr})) inside
[(dm::Data0):DataEnd]: begin
// attempts to write them while busy is set does not change their value
if (!cmdbusy_i && dm::DataCount > 0) begin
data_d[dmi_req_bits_addr_i[4:0]] = dmi_req_bits_data_i;
data_d[dmi_req_i.addr[4:0]] = dmi_req_i.data;
// check whether we need to re-execute the command (just give a cmd_valid)
cmd_valid_o = abstractauto_q.autoexecdata[dmi_req_bits_addr_i[3:0] - dm::Data0];
cmd_valid_o = abstractauto_q.autoexecdata[dmi_req_i.addr[3:0] - dm::Data0];
end
end
dm::DMControl: begin
automatic dm::dmcontrol_t dmcontrol;
dmcontrol = dm::dmcontrol_t'(dmi_req_bits_data_i);
dmcontrol = dm::dmcontrol_t'(dmi_req_i.data);
// clear the havreset of the selected hart
if (dmcontrol.ackhavereset) begin
havereset_d[selected_hart] = 1'b0;
end
dmcontrol_d = dmi_req_bits_data_i;
dmcontrol_d = dmi_req_i.data;
end
dm::DMStatus:; // write are ignored to R/O register
dm::Hartinfo:; // hartinfo is R/O
@ -296,7 +293,7 @@ module dm_csrs #(
// them. No abstract command is started until the value is
// reset to 0.
automatic dm::abstractcs_t a_abstractcs;
a_abstractcs = dm::abstractcs_t'(dmi_req_bits_data_i);
a_abstractcs = dm::abstractcs_t'(dmi_req_i.data);
// reads during abstract command execution are not allowed
if (!cmdbusy_i) begin
cmderr_d = dm::cmderr_t'(~a_abstractcs.cmderr & cmderr_q);
@ -309,7 +306,7 @@ module dm_csrs #(
// writes are ignored if a command is already busy
if (!cmdbusy_i) begin
cmd_valid_o = 1'b1;
command_d = dm::command_t'(dmi_req_bits_data_i);
command_d = dm::command_t'(dmi_req_i.data);
// if there was an attempted to write during a busy execution
// and the cmderror field is zero set the busy error
end else if (cmderr_q == dm::CmdErrNone) begin
@ -319,7 +316,7 @@ module dm_csrs #(
dm::AbstractAuto: begin
// this field can only be written legally when there is no command executing
if (!cmdbusy_i) begin
abstractauto_d = {dmi_req_bits_data_i[31:16], 4'b0, dmi_req_bits_data_i[11:0]};
abstractauto_d = {dmi_req_i.data[31:16], 4'b0, dmi_req_i.data[11:0]};
end else if (cmderr_q == dm::CmdErrNone) begin
cmderr_d = dm::CmdErrBusy;
end
@ -327,10 +324,10 @@ module dm_csrs #(
[(dm::ProgBuf0):ProgBufEnd]: begin
// attempts to write them while busy is set does not change their value
if (!cmdbusy_i) begin
progbuf_d[dmi_req_bits_addr_i[4:0]] = dmi_req_bits_data_i;
progbuf_d[dmi_req_i.addr[4:0]] = dmi_req_i.data;
// check whether we need to re-execute the command (just give a cmd_valid)
// this should probably throw an error if executed during another command was busy
cmd_valid_o = abstractauto_q.autoexecprogbuf[dmi_req_bits_addr_i[3:0]];
cmd_valid_o = abstractauto_q.autoexecprogbuf[dmi_req_i.addr[3:0]];
end
end
dm::SBCS: begin
@ -338,7 +335,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
automatic dm::sbcs_t sbcs = dm::sbcs_t'(dmi_req_bits_data_i);
automatic dm::sbcs_t sbcs = dm::sbcs_t'(dmi_req_i.data);
sbcs_d = sbcs;
// R/W1C
sbcs_d.sbbusyerror = sbcs_q.sbbusyerror & (~sbcs.sbbusyerror);
@ -350,7 +347,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
sbaddr_d[31:0] = dmi_req_bits_data_i;
sbaddr_d[31:0] = dmi_req_i.data;
sbaddress_write_valid_o = (sbcs_q.sberror == '0);
end
end
@ -359,7 +356,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
sbaddr_d[63:32] = dmi_req_bits_data_i;
sbaddr_d[63:32] = dmi_req_i.data;
end
end
dm::SBData0: begin
@ -367,7 +364,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
sbdata_d[31:0] = dmi_req_bits_data_i;
sbdata_d[31:0] = dmi_req_i.data;
sbdata_write_valid_o = (sbcs_q.sberror == '0);
end
end
@ -376,7 +373,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
sbdata_d[63:32] = dmi_req_bits_data_i;
sbdata_d[63:32] = dmi_req_i.data;
end
end
default:;
@ -448,7 +445,7 @@ module dm_csrs #(
assign data_o = data_q;
assign resp_queue_pop = dmi_resp_ready_i & ~resp_queue_empty;
// response FIFO
fifo_v2 #(
.dtype ( logic [31:0] ),
@ -464,7 +461,7 @@ module dm_csrs #(
.alm_empty_o ( ),
.data_i ( resp_queue_data ),
.push_i ( resp_queue_push ),
.data_o ( dmi_resp_bits_data_o ),
.data_o ( dmi_resp_o.data ),
.pop_i ( resp_queue_pop )
);

View file

@ -203,4 +203,15 @@ package dm;
localparam logic[1:0] DTM_SUCCESS = 2'h0;
typedef struct packed {
logic [6:0] addr;
dtm_op_t op;
logic [31:0] data;
} dmi_req_t;
typedef struct packed {
logic [31:0] data;
logic [1:0] resp;
} dmi_resp_t;
endpackage

View file

@ -38,14 +38,11 @@ module dm_top #(
input logic dmi_rst_ni,
input logic dmi_req_valid_i,
output logic dmi_req_ready_o,
input logic [ 6:0] dmi_req_bits_addr_i,
input logic [ 1:0] dmi_req_bits_op_i, // 0 = nop, 1 = read, 2 = write
input logic [31:0] dmi_req_bits_data_i,
input dm::dmi_req_t dmi_req_i,
output logic dmi_resp_valid_o,
input logic dmi_resp_ready_i,
output logic [ 1:0] dmi_resp_bits_resp_o,
output logic [31:0] dmi_resp_bits_data_o
output dm::dmi_resp_t dmi_resp_o
);
// Debug CSRs
@ -102,16 +99,13 @@ module dm_top #(
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.testmode_i ( testmode_i ),
.dmi_rst_ni ( dmi_rst_ni ),
.dmi_req_valid_i ( dmi_req_valid_i ),
.dmi_req_ready_o ( dmi_req_ready_o ),
.dmi_req_bits_addr_i ( dmi_req_bits_addr_i ),
.dmi_req_bits_op_i ( dmi_req_bits_op_i ),
.dmi_req_bits_data_i ( dmi_req_bits_data_i ),
.dmi_resp_valid_o ( dmi_resp_valid_o ),
.dmi_resp_ready_i ( dmi_resp_ready_i ),
.dmi_resp_bits_resp_o ( dmi_resp_bits_resp_o ),
.dmi_resp_bits_data_o ( dmi_resp_bits_data_o ),
.dmi_rst_ni,
.dmi_req_valid_i,
.dmi_req_ready_o,
.dmi_req_i,
.dmi_resp_valid_o,
.dmi_resp_ready_i,
.dmi_resp_o,
.ndmreset_o ( ndmreset_o ),
.dmactive_o ( dmactive_o ),
.hartsel_o ( hartsel ),

View file

@ -18,510 +18,53 @@
*/
module dmi_cdc (
// JTAG side (master side)
input logic tck_i,
input logic trst_ni,
input logic tck_i,
input logic trst_ni,
input logic mem_valid_i,
output logic mem_gnt_o,
input logic [6:0] mem_addr_i,
input logic mem_we_i,
input logic [31:0] mem_wdata_i,
output logic [31:0] mem_rdata_o,
output logic mem_rvalid_o,
input dm::dmi_req_t jtag_dmi_req_i,
output logic jtag_dmi_ready_o,
input logic jtag_dmi_valid_i,
output dm::dmi_resp_t jtag_dmi_resp_o,
output logic jtag_dmi_valid_o,
input logic jtag_dmi_ready_i,
// Memory -> Slave side
input logic clk_i,
input logic rst_ni,
// core side (slave side)
input logic clk_i,
input logic rst_ni,
output logic dmi_req_valid_o,
input logic dmi_req_ready_i,
output dm::dmi_req_t core_dmi_req_o,
output logic core_dmi_valid_o,
input logic core_dmi_ready_i,
input dm::dmi_resp_t core_dmi_resp_i,
output logic core_dmi_ready_o,
input logic core_dmi_valid_i
);
output logic [ 6:0] dmi_req_bits_addr_o,
output logic [ 1:0] dmi_req_bits_op_o,
output logic [31:0] dmi_req_bits_data_o,
cdc_2phase #(.T(dm::dmi_req_t)) i_cdc_req (
.src_rst_ni ( trst_ni ),
.src_clk_i ( tck_i ),
.src_data_i ( jtag_dmi_req_i ),
.src_valid_i ( jtag_dmi_valid_i ),
.src_ready_o ( jtag_dmi_ready_o ),
input logic dmi_resp_valid_i,
output logic dmi_resp_ready_o,
input logic [ 1:0] dmi_resp_bits_resp_i,
input logic [31:0] dmi_resp_bits_data_i
);
.dst_rst_ni ( rst_ni ),
.dst_clk_i ( clk_i ),
.dst_data_o ( core_dmi_valid_o ),
.dst_valid_o ( core_dmi_valid_o ),
.dst_ready_i ( core_dmi_ready_i )
);
logic mem_we;
// we will always be ready to receive the request we made
assign dmi_resp_ready_o = 1'b1;
// very "cheap" protocol conversion
assign dmi_req_bits_op_o = (mem_we) ? dm::DTM_WRITE : dm::DTM_READ;
cdc_2phase #(.T(dm::dmi_resp_t)) i_cdc_resp (
.src_rst_ni ( rst_ni ),
.src_clk_i ( clk_i ),
.src_data_i ( core_dmi_resp_i ),
.src_valid_i ( core_dmi_valid_i ),
.src_ready_o ( core_dmi_ready_o ),
localparam int unsigned AddrWidth = 7;
localparam int unsigned DataWidth = 32;
logic cdc_req_a;
logic cdc_ack_a;
logic [AddrWidth-1:0] cdc_addr_a;
logic cdc_we_a;
logic [DataWidth/8-1:0] cdc_be_a;
logic [DataWidth-1:0] cdc_wdata_a;
logic cdc_clear_a;
logic cdc_rreq_a;
logic cdc_rack_a;
logic [DataWidth-1:0] cdc_rdata_a;
logic cdc_rerror_a;
// lets re-use most of the debug facilities which are already in PULP
dmi_cdc_jtag #(
.ADDR_WIDTH (AddrWidth),
.DATA_WIDTH (DataWidth)
) i_dmi_cdc_jtag (
.tck_i,
.trst_ni,
.mem_req_i ( mem_valid_i ),
.mem_gnt_o,
.mem_addr_i,
.mem_we_i,
.mem_be_i ( '1 ),
.mem_wdata_i,
.mem_rdata_o,
.mem_rvalid_o,
// we are not managing any errors here
// a more elaborate implementation should probably handle this more gracefully
.mem_rerror_o ( ),
.mem_clear_i ( 1'b0 ),
.cdc_req_ao ( cdc_req_a ),
.cdc_ack_ai ( cdc_ack_a ),
.cdc_addr_ao ( cdc_addr_a ),
.cdc_we_ao ( cdc_we_a ),
.cdc_be_ao ( cdc_be_a ),
.cdc_wdata_ao ( cdc_wdata_a ),
.cdc_clear_ao ( cdc_clear_a ),
.cdc_rreq_ai ( cdc_rreq_a ),
.cdc_rack_ao ( cdc_rack_a ),
.cdc_rdata_ai ( cdc_rdata_a ),
.cdc_rerror_ai ( cdc_rerror_a )
);
dmi_cdc_mem #(
.ADDR_WIDTH (AddrWidth),
.DATA_WIDTH (DataWidth)
) i_dmi_cdc_mem (
.clk_i,
.rst_ni,
.mem_req_o ( dmi_req_valid_o ),
.mem_gnt_i ( dmi_req_ready_i ),
.mem_addr_o ( dmi_req_bits_addr_o ),
.mem_we_o ( mem_we ),
// don't care we always write whole words
.mem_be_o ( ),
.mem_wdata_o ( dmi_req_bits_data_o ),
.mem_rdata_i ( dmi_resp_bits_data_i ),
.mem_rvalid_i ( dmi_resp_valid_i ),
// don't care about clearing an error flag
// that is handled differently in the RISC-V implementation
.mem_rerror_i ( 1'b0 ),
.mem_clear_o ( ),
.cdc_req_ai ( cdc_req_a ),
.cdc_ack_ao ( cdc_ack_a ),
.cdc_addr_ai ( cdc_addr_a ),
.cdc_we_ai ( cdc_we_a ),
.cdc_be_ai ( cdc_be_a ),
.cdc_wdata_ai ( cdc_wdata_a ),
.cdc_clear_ai ( cdc_clear_a ),
.cdc_rreq_ao ( cdc_rreq_a ),
.cdc_rack_ai ( cdc_rack_a ),
.cdc_rdata_ao ( cdc_rdata_a ),
.cdc_rerror_ao ( cdc_rerror_a )
);
endmodule
module dmi_cdc_jtag #(
parameter int unsigned ADDR_WIDTH = 32,
parameter int unsigned DATA_WIDTH = 64
)(
// JTAG side
input logic tck_i,
input logic trst_ni,
input logic mem_req_i,
output logic mem_gnt_o,
input logic [ADDR_WIDTH-1:0] mem_addr_i,
input logic mem_we_i,
input logic [DATA_WIDTH/8-1:0] mem_be_i,
input logic [DATA_WIDTH-1:0] mem_wdata_i,
output logic [DATA_WIDTH-1:0] mem_rdata_o,
output logic mem_rvalid_o,
output logic mem_rerror_o,
input logic mem_clear_i,
// CDC side
output logic cdc_req_ao,
input logic cdc_ack_ai,
output logic [ADDR_WIDTH-1:0] cdc_addr_ao,
output logic cdc_we_ao,
output logic [DATA_WIDTH/8-1:0] cdc_be_ao,
output logic [DATA_WIDTH-1:0] cdc_wdata_ao,
output logic cdc_clear_ao,
input logic cdc_rreq_ai,
output logic cdc_rack_ao,
input logic [DATA_WIDTH-1:0] cdc_rdata_ai,
input logic cdc_rerror_ai
);
enum logic [1:0] { IDLE, WAIT_ACK_LOW, WAIT_ACK_HIGH, READY_ACK_LOW } req_state_p, req_state_n;
enum logic [0:0] { RIDLE, WAIT_REQ_LOW } resp_state_p, resp_state_n;
logic [ADDR_WIDTH-1:0] cdc_addr_p;
logic cdc_we_p;
logic [DATA_WIDTH/8-1:0] cdc_be_p;
logic [DATA_WIDTH-1:0] cdc_wdata_p;
logic cdc_req_n;
logic cdc_clear_p;
logic cdc_ack;
logic cdc_rreq;
always_comb
begin
req_state_n = req_state_p;
mem_gnt_o = 1'b0;
cdc_req_n = 1'b0;
unique case (req_state_p)
IDLE: begin
if (mem_req_i) begin
req_state_n = WAIT_ACK_HIGH;
mem_gnt_o = 1'b1;
end
end
WAIT_ACK_HIGH: begin
cdc_req_n = 1'b1;
if (cdc_ack) begin
req_state_n = WAIT_ACK_LOW;
end
end
WAIT_ACK_LOW: begin
if (mem_req_i)
mem_gnt_o = 1'b1;
if (~cdc_ack) begin
if (mem_req_i)
req_state_n = WAIT_ACK_HIGH;
else
req_state_n = IDLE;
end else begin
if (mem_req_i)
req_state_n = READY_ACK_LOW;
end
end
READY_ACK_LOW: begin
if (~cdc_ack) begin
req_state_n = WAIT_ACK_HIGH;
end
end
default:; // make unique case happy during reset
endcase
end
always_comb
begin
resp_state_n = resp_state_p;
mem_rvalid_o = 1'b0;
cdc_rack_ao = 1'b0;
unique case (resp_state_p)
RIDLE: begin
if (cdc_rreq) begin
resp_state_n = WAIT_REQ_LOW;
mem_rvalid_o = 1'b1;
end
end
WAIT_REQ_LOW: begin
cdc_rack_ao = 1'b1;
if (~cdc_rreq) begin
resp_state_n = RIDLE;
end
end
default:; // make unique case happy during reset
endcase
end
always_ff @(posedge tck_i, negedge trst_ni) begin
if (~trst_ni) begin
req_state_p <= IDLE;
resp_state_p <= RIDLE;
cdc_addr_p <= '0;
cdc_we_p <= '0;
cdc_be_p <= '0;
cdc_wdata_p <= '0;
cdc_clear_p <= '0;
cdc_req_ao <= 1'b0;
end else begin
req_state_p <= req_state_n;
resp_state_p <= resp_state_n;
cdc_req_ao <= cdc_req_n;
if (mem_gnt_o) begin
cdc_addr_p <= mem_addr_i;
cdc_we_p <= mem_we_i;
cdc_be_p <= mem_be_i;
cdc_wdata_p <= mem_wdata_i;
cdc_clear_p <= mem_clear_i;
end
end
end
assign cdc_addr_ao = cdc_addr_p;
assign cdc_we_ao = cdc_we_p;
assign cdc_be_ao = cdc_be_p;
assign cdc_wdata_ao = cdc_wdata_p;
assign cdc_clear_ao = cdc_clear_p;
(* ASYNC_REG = "TRUE" *)
sync i_sync_ack (
.clk_i ( tck_i ),
.rst_ni ( trst_ni ) ,
.serial_i ( cdc_ack_ai ),
.serial_o ( cdc_ack )
);
(* ASYNC_REG = "TRUE" *)
sync i_sync_rreq (
.clk_i ( tck_i ),
.rst_ni ( trst_ni ) ,
.serial_i ( cdc_rreq_ai ),
.serial_o ( cdc_rreq )
);
assign mem_rerror_o = cdc_rerror_ai;
assign mem_rdata_o = cdc_rdata_ai;
endmodule
module dmi_cdc_mem #(
parameter int unsigned ADDR_WIDTH = 32,
parameter int unsigned DATA_WIDTH = 64
)(
// mem side
input logic clk_i,
input logic rst_ni,
output logic mem_req_o,
input logic mem_gnt_i,
output logic [ADDR_WIDTH-1:0] mem_addr_o,
output logic mem_we_o,
output logic [DATA_WIDTH/8-1:0] mem_be_o,
output logic [DATA_WIDTH-1:0] mem_wdata_o,
input logic [DATA_WIDTH-1:0] mem_rdata_i,
input logic mem_rvalid_i,
input logic mem_rerror_i,
output logic mem_clear_o,
// CDC side
input logic cdc_req_ai,
output logic cdc_ack_ao,
input logic [ADDR_WIDTH-1:0] cdc_addr_ai,
input logic cdc_we_ai,
input logic [DATA_WIDTH/8-1:0] cdc_be_ai,
input logic [DATA_WIDTH-1:0] cdc_wdata_ai,
input logic cdc_clear_ai,
output logic cdc_rreq_ao,
input logic cdc_rack_ai,
output logic [DATA_WIDTH-1:0] cdc_rdata_ao,
output logic cdc_rerror_ao
);
enum logic [1:0] { IDLE, REQUEST, WAIT_REQ_LOW } req_state_p, req_state_n;
enum logic [1:0] { RIDLE, WAIT_ACK_HIGH, WAIT_ACK_LOW } resp_state_p, resp_state_n;
logic [ADDR_WIDTH-1:0] mem_addr_p;
logic mem_we_p;
logic [DATA_WIDTH/8-1:0] mem_be_p;
logic [DATA_WIDTH-1:0] mem_wdata_p;
logic mem_clear_p;
logic cdc_req;
logic cdc_clear;
logic cdc_sample;
logic cdc_rack;
logic [DATA_WIDTH-1:0] cdc_rdata_p;
logic cdc_rerror_p;
logic cdc_rreq_n;
logic cdc_ack_n;
always_comb begin
req_state_n = req_state_p;
cdc_ack_n = 1'b0;
cdc_sample = 1'b0;
mem_req_o = 1'b0;
unique case (req_state_p)
IDLE: begin
if (cdc_req) begin
req_state_n = REQUEST;
cdc_sample = 1'b1;
end
end
REQUEST: begin
mem_req_o = 1'b1;
cdc_ack_n = 1'b1;
if (mem_gnt_i) begin
req_state_n = WAIT_REQ_LOW;
end
end
WAIT_REQ_LOW: begin
cdc_ack_n = 1'b1;
if (~cdc_req) begin
req_state_n = IDLE;
end
end
default:; // make unique case happy during reset
endcase
if (cdc_clear)
req_state_n = IDLE;
end
always_comb begin
resp_state_n = resp_state_p;
cdc_rreq_n = 1'b0;
unique case (resp_state_p)
RIDLE: begin
if (mem_rvalid_i) begin
resp_state_n = WAIT_ACK_HIGH;
end
end
WAIT_ACK_HIGH: begin
cdc_rreq_n = 1'b1;
if (cdc_rack) begin
resp_state_n = WAIT_ACK_LOW;
end
end
WAIT_ACK_LOW: begin
cdc_rreq_n = 1'b0;
if (~cdc_rack) begin
resp_state_n = RIDLE;
end
end
default:; // make unique case happy during reset
endcase
if (cdc_clear)
resp_state_n = RIDLE;
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (~rst_ni) begin
req_state_p <= IDLE;
resp_state_p <= RIDLE;
mem_addr_p <= '0;
mem_we_p <= '0;
mem_be_p <= '0;
mem_wdata_p <= '0;
mem_clear_p <= '0;
cdc_rdata_p <= '0;
cdc_rerror_p <= '0;
cdc_rreq_ao <= 1'b0;
cdc_ack_ao <= 1'b0;
end else begin
req_state_p <= req_state_n;
resp_state_p <= resp_state_n;
cdc_rreq_ao <= cdc_rreq_n;
cdc_ack_ao <= cdc_ack_n;
if (cdc_sample) begin
mem_addr_p <= cdc_addr_ai;
mem_we_p <= cdc_we_ai;
mem_be_p <= cdc_be_ai;
mem_wdata_p <= cdc_wdata_ai;
mem_clear_p <= cdc_clear_ai;
end else begin
mem_clear_p <= '0;
end
if (mem_rvalid_i) begin
cdc_rdata_p <= mem_rdata_i;
cdc_rerror_p <= mem_rerror_i;
end
end
end
assign mem_addr_o = mem_addr_p;
assign mem_we_o = mem_we_p;
assign mem_be_o = mem_be_p;
assign mem_wdata_o = mem_wdata_p;
assign mem_clear_o = mem_clear_p;
assign cdc_rdata_ao = cdc_rdata_p;
assign cdc_rerror_ao = cdc_rerror_p;
(* ASYNC_REG = "TRUE" *)
sync i_sync_req (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ) ,
.serial_i ( cdc_req_ai ),
.serial_o ( cdc_req )
);
(* ASYNC_REG = "TRUE" *)
sync i_sync_clear (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.serial_i ( cdc_clear_ai ),
.serial_o ( cdc_clear )
);
(* ASYNC_REG = "TRUE" *)
sync i_sync_rack (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ) ,
.serial_i ( cdc_rack_ai ),
.serial_o ( cdc_rack )
);
//----------------------------------------------------------------------------
// Assertions
//----------------------------------------------------------------------------
`ifndef SYNTHESIS
`ifndef verilator
assert property (
@(posedge clk_i) (mem_req_o) |-> (!$isunknown(mem_addr_o) && !$isunknown(mem_we_o)
&& !$isunknown(mem_be_o) && !$isunknown(mem_wdata_o)))
else $warning("mem request data may never be unknown");
assert property (
@(posedge clk_i) (!$isunknown(mem_gnt_i))) else $warning("memory grant may never be unknown");
`endif
`endif
.dst_rst_ni ( trst_ni ),
.dst_clk_i ( tck_i ),
.dst_data_o ( jtag_dmi_resp_o ),
.dst_valid_o ( jtag_dmi_valid_o ),
.dst_ready_i ( jtag_dmi_ready_i )
);
endmodule

View file

@ -17,27 +17,25 @@
*/
module dmi_jtag (
input logic clk_i, // DMI Clock
input logic rst_ni, // Asynchronous reset active low
input logic clk_i, // DMI Clock
input logic rst_ni, // Asynchronous reset active low
output logic dmi_rst_no, // hard reset
output logic dmi_rst_no, // hard reset
output logic dmi_req_valid_o,
input logic dmi_req_ready_i,
output logic [ 6:0] dmi_req_bits_addr_o,
output logic [ 1:0] dmi_req_bits_op_o, // 0 = nop, 1 = read, 2 = write
output logic [31:0] dmi_req_bits_data_o,
input logic dmi_resp_valid_i,
output logic dmi_resp_ready_o,
input logic [ 1:0] dmi_resp_bits_resp_i,
input logic [31:0] dmi_resp_bits_data_i,
output dm::dmi_req_t dmi_req_o,
output logic dmi_req_valid_o,
input logic dmi_req_ready_i,
input logic tck_i, // JTAG test clock pad
input logic tms_i, // JTAG test mode select pad
input logic trst_ni, // JTAG test reset pad
input logic td_i, // JTAG test data input pad
output logic td_o, // JTAG test data output pad
output logic tdo_oe_o // Data out output enable
input dm::dmi_resp_t dmi_resp_i,
output logic dmi_resp_ready_o,
input logic dmi_resp_valid_i,
input logic tck_i, // JTAG test clock pad
input logic tms_i, // JTAG test mode select pad
input logic trst_ni, // JTAG test reset pad
input logic td_i, // JTAG test data input pad
output logic td_o, // JTAG test data output pad
output logic tdo_oe_o // Data out output enable
);
assign dmi_rst_no = 1'b1;
@ -51,13 +49,13 @@ module dmi_jtag (
logic dmi_tdi;
logic dmi_tdo;
logic mem_valid;
logic mem_gnt;
logic [6:0] mem_addr;
logic mem_we;
logic [31:0] mem_wdata;
logic [31:0] mem_rdata;
logic mem_rvalid;
dm::dmi_req_t dmi_req;
logic dmi_req_ready;
logic dmi_req_valid;
dm::dmi_resp_t dmi_resp;
logic dmi_resp_valid;
logic dmi_resp_ready;
typedef struct packed {
logic [6:0] address;
@ -77,10 +75,12 @@ module dmi_jtag (
logic [31:0] data_d, data_q;
dmi_t dmi;
assign dmi = dmi_t'(dr_q);
assign mem_addr = address_q;
assign mem_wdata = data_q;
assign mem_we = (state_q == Write);
assign dmi = dmi_t'(dr_q);
assign dmi_req.addr = address_q;
assign dmi_req.data = data_q;
assign dmi_req.op = (state_q == Write) ? dm::DTM_WRITE : dm::DTM_READ;
// we'will always be ready to accept the data we requested
assign dmi_resp_ready = 1'b1;
logic error_dmi_busy;
dmi_error_t error_d, error_q;
@ -93,7 +93,7 @@ module dmi_jtag (
data_d = data_q;
error_d = error_q;
mem_valid = 1'b0;
dmi_req_valid = 1'b0;
case (state_q)
Idle: begin
@ -112,31 +112,31 @@ module dmi_jtag (
end
Read: begin
mem_valid = 1'b1;
if (mem_gnt) begin
dmi_req_valid = 1'b1;
if (dmi_req_ready) begin
state_d = WaitReadValid;
end
end
WaitReadValid: begin
// load data into register and shift out
if (mem_rvalid) begin
data_d = mem_rdata;
if (dmi_resp_valid) begin
data_d = dmi_resp.data;
state_d = Idle;
end
end
Write: begin
mem_valid = 1'b1;
dmi_req_valid = 1'b1;
// got a valid answer go back to idle
if (mem_gnt) begin
if (dmi_req_ready) begin
state_d = Idle;
end
end
WaitWriteValid: begin
// just wait for idle here
if (mem_rvalid) begin
if (dmi_resp_valid) begin
state_d = Idle;
end
end
@ -237,26 +237,21 @@ module dmi_jtag (
// JTAG side (master side)
.tck_i,
.trst_ni,
.mem_valid_i ( mem_valid ),
.mem_gnt_o ( mem_gnt ),
.mem_addr_i ( mem_addr ),
.mem_we_i ( mem_we ),
.mem_wdata_i ( mem_wdata ),
.mem_rdata_o ( mem_rdata ),
.mem_rvalid_o ( mem_rvalid ),
.jtag_dmi_req_i ( dmi_req ),
.jtag_dmi_ready_o ( dmi_req_ready ),
.jtag_dmi_valid_i ( dmi_req_valid ),
.jtag_dmi_resp_o ( dmi_resp ),
.jtag_dmi_valid_o ( dmi_resp_valid ),
.jtag_dmi_ready_i ( dmi_resp_ready ),
// core side
.clk_i,
.rst_ni,
.dmi_req_valid_o,
.dmi_req_ready_i,
.dmi_req_bits_addr_o,
.dmi_req_bits_op_o,
.dmi_req_bits_data_o,
.dmi_resp_valid_i,
.dmi_resp_ready_o,
.dmi_resp_bits_resp_i,
.dmi_resp_bits_data_i
.core_dmi_req_o ( dmi_req_o ),
.core_dmi_valid_o ( dmi_req_valid_o ),
.core_dmi_ready_i ( dmi_req_ready_i ),
.core_dmi_resp_i ( dmi_resp_i ),
.core_dmi_ready_o ( dmi_resp_ready_o ),
.core_dmi_valid_i ( dmi_resp_valid_i )
);
endmodule

View file

@ -20,7 +20,6 @@ module issue_read_operands #(
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic test_en_i,
// flush
input logic flush_i,
// coming from rename
@ -282,7 +281,7 @@ module issue_read_operands #(
// Clock and Reset
.clk ( clk_i ),
.rst_n ( rst_ni ),
.test_en_i ( test_en_i ),
.test_en_i ( 1'b0 ),
.raddr_a_i ( issue_instr_i.rs1[4:0] ),
.rdata_a_o ( operand_a_regfile ),

View file

@ -22,7 +22,6 @@ module issue_stage #(
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic test_en_i, // Test Enable
input logic flush_unissued_instr_i,
input logic flush_i,

View file

@ -30,7 +30,7 @@ module ariane_testharness #(
logic test_en;
logic ndmreset;
logic ndmreset_n;
logic debug_req;
logic debug_req_core;
int jtag_enable;
logic init_done;
@ -45,9 +45,6 @@ module ariane_testharness #(
logic debug_req_valid;
logic debug_req_ready;
logic [6:0] debug_req_bits_addr;
logic [1:0] debug_req_bits_op;
logic [31:0] debug_req_bits_data;
logic debug_resp_valid;
logic debug_resp_ready;
logic [1:0] debug_resp_bits_resp;
@ -98,12 +95,16 @@ module ariane_testharness #(
if (!$value$plusargs("jtag_rbb_enable=%b", jtag_enable)) jtag_enable = 'h0;
end
dm::dmi_req_t jtag_dmi_req;
dm::dmi_req_t dmi_req;
dm::dmi_req_t debug_req;
dm::dmi_resp_t debug_resp;
// debug if MUX
assign debug_req_valid = (jtag_enable[0]) ? jtag_req_valid : dmi_req_valid;
assign debug_req_bits_addr = (jtag_enable[0]) ? jtag_req_bits_addr : dmi_req_bits_addr;
assign debug_req_bits_op = (jtag_enable[0]) ? jtag_req_bits_op : dmi_req_bits_op;
assign debug_req_bits_data = (jtag_enable[0]) ? jtag_req_bits_data : dmi_req_bits_data;
assign debug_resp_ready = (jtag_enable[0]) ? jtag_resp_ready : dmi_resp_ready;
assign debug_req = (jtag_enable[0]) ? jtag_dmi_req : dmi_req;
assign exit_o = (jtag_enable[0]) ? jtag_exit : dmi_exit;
assign jtag_resp_valid = (jtag_enable[0]) ? debug_resp_valid : 1'b0;
assign dmi_resp_valid = (jtag_enable[0]) ? 1'b0 : debug_resp_valid;
@ -125,26 +126,21 @@ module ariane_testharness #(
);
dmi_jtag i_dmi_jtag (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.dmi_rst_no ( ),
.dmi_req_valid_o ( jtag_req_valid ),
.dmi_req_ready_i ( debug_req_ready ),
.dmi_req_bits_addr_o ( jtag_req_bits_addr ),
.dmi_req_bits_op_o ( jtag_req_bits_op ),
.dmi_req_bits_data_o ( jtag_req_bits_data ),
.dmi_resp_valid_i ( jtag_resp_valid ),
.dmi_resp_ready_o ( jtag_resp_ready ),
.dmi_resp_bits_resp_i ( debug_resp_bits_resp ),
.dmi_resp_bits_data_i ( debug_resp_bits_data ),
.tck_i ( jtag_TCK ),
.tms_i ( jtag_TMS ),
.trst_ni ( jtag_TRSTn ),
.td_i ( jtag_TDI ),
.td_o ( jtag_TDO_data ),
.tdo_oe_o ( jtag_TDO_driven )
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.dmi_req_o ( jtag_dmi_req ),
.dmi_req_valid_o ( jtag_req_valid ),
.dmi_req_ready_i ( debug_req_ready ),
.dmi_resp_i ( debug_resp ),
.dmi_resp_ready_o ( jtag_resp_ready ),
.dmi_resp_valid_i ( jtag_resp_valid ),
.dmi_rst_no ( ), // not connected
.tck_i ( jtag_TCK ),
.tms_i ( jtag_TMS ),
.trst_ni ( jtag_TRSTn ),
.td_i ( jtag_TDI ),
.td_o ( jtag_TDO_data ),
.tdo_oe_o ( jtag_TDO_driven )
);
// SiFive's SimDTM Module
@ -154,13 +150,13 @@ module ariane_testharness #(
.reset ( ~rst_ni ),
.debug_req_valid ( dmi_req_valid ),
.debug_req_ready ( debug_req_ready ),
.debug_req_bits_addr ( dmi_req_bits_addr ),
.debug_req_bits_op ( dmi_req_bits_op ),
.debug_req_bits_data ( dmi_req_bits_data ),
.debug_req_bits_addr ( dmi_req.addr ),
.debug_req_bits_op ( dmi_req.op ),
.debug_req_bits_data ( dmi_req.data ),
.debug_resp_valid ( dmi_resp_valid ),
.debug_resp_ready ( dmi_resp_ready ),
.debug_resp_bits_resp ( debug_resp_bits_resp ),
.debug_resp_bits_data ( debug_resp_bits_data ),
.debug_resp_bits_resp ( debug_resp.resp ),
.debug_resp_bits_data ( debug_resp.data ),
.exit ( dmi_exit )
);
@ -178,20 +174,17 @@ module ariane_testharness #(
.testmode_i ( test_en ),
.ndmreset_o ( ndmreset ),
.dmactive_o ( ), // active debug session
.debug_req_o ( debug_req ),
.debug_req_o ( debug_req_core ),
.unavailable_i ( '0 ),
.axi_master ( slave[3] ),
.axi_slave ( master[3] ),
.dmi_rst_ni ( rst_ni ),
.dmi_req_valid_i ( debug_req_valid ),
.dmi_req_ready_o ( debug_req_ready ),
.dmi_req_bits_addr_i ( debug_req_bits_addr ),
.dmi_req_bits_op_i ( debug_req_bits_op ),
.dmi_req_bits_data_i ( debug_req_bits_data ),
.dmi_req_i ( debug_req ),
.dmi_resp_valid_o ( debug_resp_valid ),
.dmi_resp_ready_i ( debug_resp_ready ),
.dmi_resp_bits_resp_o ( debug_resp_bits_resp ),
.dmi_resp_bits_data_o ( debug_resp_bits_data )
.dmi_resp_o ( debug_resp )
);
// ---------------
@ -303,7 +296,7 @@ module ariane_testharness #(
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.slave ( master[1] ),
.rtc_i ( 1'b0 ),
.rtc_i ( 1'b0 ),
.timer_irq_o ( timer_irq ),
.ipi_o ( ipi )
);
@ -318,14 +311,13 @@ module ariane_testharness #(
) i_ariane (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.test_en_i ( test_en ),
.boot_addr_i ( 64'h10000 ), // start fetching from ROM
.core_id_i ( '0 ),
.cluster_id_i ( '0 ),
.irq_i ( '0 ), // we do not specify other interrupts in this TB
.ipi_i ( ipi ),
.time_irq_i ( timer_irq ),
.debug_req_i ( debug_req ),
.debug_req_i ( debug_req_core ),
.data_if ( slave[2] ),
.bypass_if ( slave[1] ),
.instr_if ( slave[0] )