Line 1... |
Line 1... |
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// dbg_cpu.v ////
|
//// dbg_cpu.v ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//// This file is part of the SoC/OpenRISC Development Interface ////
|
//// This file is part of the SoC Debug Interface. ////
|
//// http://www.opencores.org/projects/DebugInterface/ ////
|
//// http://www.opencores.org/projects/DebugInterface/ ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// Igor Mohor (igorm@opencores.org) ////
|
//// Igor Mohor (igorm@opencores.org) ////
|
//// ////
|
//// ////
|
Line 41... |
Line 41... |
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//
|
//
|
// CVS Revision History
|
// CVS Revision History
|
//
|
//
|
// $Log: not supported by cvs2svn $
|
// $Log: not supported by cvs2svn $
|
|
// Revision 1.7 2004/01/25 14:04:18 mohor
|
|
// All flipflops are reset.
|
|
//
|
// Revision 1.6 2004/01/22 13:58:53 mohor
|
// Revision 1.6 2004/01/22 13:58:53 mohor
|
// Port signals are all set to zero after reset.
|
// Port signals are all set to zero after reset.
|
//
|
//
|
// Revision 1.5 2004/01/19 07:32:41 simons
|
// Revision 1.5 2004/01/19 07:32:41 simons
|
// Reset values width added because of FV, a good sentence changed because some tools can not handle it.
|
// Reset values width added because of FV, a good sentence changed because some tools can not handle it.
|
Line 85... |
Line 88... |
crc_match_i,
|
crc_match_i,
|
crc_en_o,
|
crc_en_o,
|
shift_crc_o,
|
shift_crc_o,
|
rst_i,
|
rst_i,
|
|
|
// CPU signals
|
// CPU
|
cpu_clk_i,
|
cpu_clk_i,
|
cpu_addr_o,
|
cpu_addr_o, cpu_data_i, cpu_data_o, cpu_bp_i, cpu_stall_o,
|
cpu_data_i,
|
|
cpu_data_o,
|
|
cpu_bp_i,
|
|
cpu_stall_o,
|
|
cpu_stall_all_o,
|
|
cpu_stb_o,
|
cpu_stb_o,
|
cpu_sel_o, // Not synchronized
|
cpu_we_o, cpu_ack_i, cpu_rst_o
|
cpu_we_o,
|
|
cpu_ack_i,
|
|
cpu_rst_o
|
|
|
|
|
|
);
|
);
|
|
|
// JTAG signals
|
// JTAG signals
|
input tck_i;
|
input tck_i;
|
Line 118... |
Line 112... |
input crc_match_i;
|
input crc_match_i;
|
output crc_en_o;
|
output crc_en_o;
|
output shift_crc_o;
|
output shift_crc_o;
|
input rst_i;
|
input rst_i;
|
|
|
|
// CPU
|
// CPU signals
|
|
input cpu_clk_i;
|
input cpu_clk_i;
|
output [31:0] cpu_addr_o;
|
output [31:0] cpu_addr_o;
|
input [31:0] cpu_data_i;
|
|
output [31:0] cpu_data_o;
|
output [31:0] cpu_data_o;
|
input cpu_bp_i;
|
input cpu_bp_i;
|
output cpu_stall_o;
|
output cpu_stall_o;
|
output cpu_stall_all_o;
|
input [31:0] cpu_data_i;
|
output cpu_stb_o;
|
output cpu_stb_o;
|
output [`CPU_NUM -1:0] cpu_sel_o;
|
|
output cpu_we_o;
|
output cpu_we_o;
|
input cpu_ack_i;
|
input cpu_ack_i;
|
output cpu_rst_o;
|
output cpu_rst_o;
|
|
|
|
reg cpu_stb_o;
|
|
wire cpu_reg_stall;
|
reg tdo_o;
|
reg tdo_o;
|
|
reg cpu_ack_q;
|
|
reg cpu_ack_csff;
|
|
reg cpu_ack_tck;
|
|
|
|
reg [31:0] cpu_dat_tmp, cpu_data_dsff;
|
|
reg [31:0] cpu_addr_dsff;
|
|
reg cpu_we_dsff;
|
|
reg [`DBG_CPU_DR_LEN -1 :0] dr;
|
|
wire enable;
|
wire cmd_cnt_en;
|
wire cmd_cnt_en;
|
reg [1:0] cmd_cnt;
|
reg [`DBG_CPU_CMD_CNT_WIDTH -1:0] cmd_cnt;
|
wire cmd_cnt_end;
|
wire cmd_cnt_end;
|
reg cmd_cnt_end_q;
|
reg cmd_cnt_end_q;
|
wire addr_cnt_en;
|
reg addr_len_cnt_en;
|
reg [5:0] addr_cnt;
|
reg [5:0] addr_len_cnt;
|
reg [5:0] addr_cnt_limit;
|
wire addr_len_cnt_end;
|
wire addr_cnt_end;
|
reg addr_len_cnt_end_q;
|
wire crc_cnt_en;
|
reg crc_cnt_en;
|
reg [5:0] crc_cnt;
|
reg [`DBG_CPU_CRC_CNT_WIDTH -1:0] crc_cnt;
|
wire crc_cnt_end;
|
wire crc_cnt_end;
|
reg crc_cnt_end_q;
|
reg crc_cnt_end_q;
|
wire data_cnt_en;
|
reg data_cnt_en;
|
reg [5:0] data_cnt;
|
reg [`DBG_CPU_DATA_CNT_WIDTH:0] data_cnt;
|
reg [5:0] data_cnt_limit;
|
reg [`DBG_CPU_DATA_CNT_WIDTH:0] data_cnt_limit;
|
wire data_cnt_end;
|
wire data_cnt_end;
|
reg data_cnt_end_q;
|
reg data_cnt_end_q;
|
|
reg crc_match_reg;
|
|
|
|
reg [`DBG_CPU_ACC_TYPE_LEN -1:0] acc_type;
|
|
reg [`DBG_CPU_ADR_LEN -1:0] adr;
|
|
reg [`DBG_CPU_LEN_LEN -1:0] len;
|
|
reg [`DBG_CPU_LEN_LEN:0] len_var;
|
|
wire [`DBG_CPU_CTRL_LEN -1:0]ctrl_reg;
|
|
reg start_rd_tck;
|
|
reg rd_tck_started;
|
|
reg start_rd_csff;
|
|
reg start_cpu_rd;
|
|
reg start_cpu_rd_q;
|
|
reg start_wr_tck;
|
|
reg start_wr_csff;
|
|
reg start_cpu_wr;
|
|
reg start_cpu_wr_q;
|
|
|
|
reg status_cnt_en;
|
wire status_cnt_end;
|
wire status_cnt_end;
|
reg status_cnt1, status_cnt2, status_cnt3, status_cnt4;
|
|
reg [3:0] status;
|
|
|
|
reg crc_match_reg;
|
wire half, long;
|
wire enable;
|
reg half_q, long_q;
|
|
|
reg read_cycle_reg;
|
reg [`DBG_CPU_STATUS_CNT_WIDTH -1:0] status_cnt;
|
reg read_cycle_reg_q;
|
|
reg read_cycle_cpu;
|
|
reg read_cycle_cpu_q;
|
|
reg write_cycle_reg;
|
|
reg write_cycle_cpu;
|
|
wire read_cycle;
|
|
wire write_cycle;
|
|
|
|
reg [31:0] dr;
|
|
wire [7:0] reg_data_out;
|
|
|
|
wire dr_read_reg;
|
|
wire dr_write_reg;
|
|
wire dr_read_cpu8;
|
|
wire dr_read_cpu32;
|
|
wire dr_write_cpu8;
|
|
wire dr_write_cpu32;
|
|
wire dr_go;
|
|
|
|
reg dr_read_reg_latched;
|
|
reg dr_write_reg_latched;
|
|
reg dr_read_cpu8_latched;
|
|
reg dr_read_cpu32_latched;
|
|
reg dr_write_cpu8_latched;
|
|
reg dr_write_cpu32_latched;
|
|
reg dr_go_latched;
|
|
|
|
reg cmd_read_reg;
|
|
reg cmd_read_cpu;
|
|
reg cmd_write_reg;
|
|
reg cmd_write_cpu;
|
|
reg cycle_32_bit;
|
|
reg reg_access;
|
|
|
|
reg [31:0] adr;
|
reg [`DBG_CPU_STATUS_LEN -1:0] status;
|
reg cpu_ack_sync;
|
|
reg cpu_ack_tck;
|
|
reg cpu_ack_tck_q;
|
|
reg cpu_stb;
|
|
reg cpu_stb_sync;
|
|
reg cpu_stb_o;
|
|
wire cpu_stall_tmp;
|
|
|
|
wire go_prelim;
|
reg cpu_overrun, cpu_overrun_csff, cpu_overrun_tck;
|
|
reg underrun_tck;
|
|
|
|
reg busy_cpu;
|
|
reg busy_tck;
|
|
reg cpu_end;
|
|
reg cpu_end_rst;
|
|
reg cpu_end_rst_csff;
|
|
reg cpu_end_csff;
|
|
reg cpu_end_tck, cpu_end_tck_q;
|
|
reg busy_csff;
|
|
reg latch_data;
|
|
reg update_dr_csff, update_dr_cpu;
|
|
wire [`DBG_CPU_CTRL_LEN -1:0] cpu_reg_data_i;
|
|
wire cpu_reg_we;
|
|
|
|
reg set_addr, set_addr_csff, set_addr_cpu, set_addr_cpu_q;
|
|
wire [31:0] input_data;
|
|
|
|
wire len_eq_0;
|
wire crc_cnt_31;
|
wire crc_cnt_31;
|
|
|
|
reg fifo_full;
|
|
reg [7:0] mem [0:3];
|
|
reg cpu_ce_csff;
|
|
reg mem_ptr_init;
|
|
reg [`DBG_CPU_CMD_LEN -1: 0] curr_cmd;
|
|
wire curr_cmd_go;
|
|
reg curr_cmd_go_q;
|
|
wire curr_cmd_wr_comm;
|
|
wire curr_cmd_wr_ctrl;
|
|
wire curr_cmd_rd_comm;
|
|
wire curr_cmd_rd_ctrl;
|
|
wire acc_type_read;
|
|
wire acc_type_write;
|
|
|
|
|
assign enable = cpu_ce_i & shift_dr_i;
|
assign enable = cpu_ce_i & shift_dr_i;
|
assign crc_en_o = enable & crc_cnt_end & (~status_cnt_end);
|
assign crc_en_o = enable & crc_cnt_end & (~status_cnt_end);
|
assign shift_crc_o = enable & status_cnt_end; // Signals dbg module to shift out the CRC
|
assign shift_crc_o = enable & status_cnt_end; // Signals dbg module to shift out the CRC
|
|
|
|
assign curr_cmd_go = (curr_cmd == `DBG_CPU_GO) && cmd_cnt_end;
|
|
assign curr_cmd_wr_comm = (curr_cmd == `DBG_CPU_WR_COMM) && cmd_cnt_end;
|
|
assign curr_cmd_wr_ctrl = (curr_cmd == `DBG_CPU_WR_CTRL) && cmd_cnt_end;
|
|
assign curr_cmd_rd_comm = (curr_cmd == `DBG_CPU_RD_COMM) && cmd_cnt_end;
|
|
assign curr_cmd_rd_ctrl = (curr_cmd == `DBG_CPU_RD_CTRL) && cmd_cnt_end;
|
|
|
|
assign acc_type_read = (acc_type == `DBG_CPU_READ);
|
|
assign acc_type_write = (acc_type == `DBG_CPU_WRITE);
|
|
|
|
|
|
|
|
reg [799:0] dr_text;
|
|
// Shift register for shifting in and out the data
|
|
always @ (posedge tck_i or posedge rst_i)
|
|
begin
|
|
if (rst_i)
|
|
begin
|
|
latch_data <= #1 1'b0;
|
|
dr <= #1 {`DBG_CPU_DR_LEN{1'b0}};
|
|
dr_text = "reset";
|
|
end
|
|
else if (curr_cmd_rd_comm && crc_cnt_31) // Latching data (from internal regs)
|
|
begin
|
|
dr[`DBG_CPU_ACC_TYPE_LEN + `DBG_CPU_ADR_LEN + `DBG_CPU_LEN_LEN -1:0] <= #1 {acc_type, adr, len};
|
|
dr_text = "latch reg data";
|
|
end
|
|
else if (curr_cmd_rd_ctrl && crc_cnt_31) // Latching data (from control regs)
|
|
begin
|
|
dr[`DBG_CPU_DR_LEN -1:`DBG_CPU_DR_LEN -`DBG_CPU_CTRL_LEN] <= #1 ctrl_reg;
|
|
dr_text = "latch ctrl reg data";
|
|
end
|
|
else if (acc_type_read && curr_cmd_go && crc_cnt_31) // Latchind first data (from WB)
|
|
begin
|
|
dr[31:0] <= #1 input_data[31:0];
|
|
latch_data <= #1 1'b1;
|
|
dr_text = "latch first data";
|
|
end
|
|
else if (acc_type_read && curr_cmd_go && crc_cnt_end) // Latching data (from WB)
|
|
begin
|
|
case (acc_type) // synthesis parallel_case full_case
|
|
`DBG_CPU_READ: begin
|
|
if(long & (~long_q))
|
|
begin
|
|
dr[31:0] <= #1 input_data[31:0];
|
|
latch_data <= #1 1'b1;
|
|
dr_text = "latch_data word";
|
|
end
|
|
else
|
|
begin
|
|
dr[31:0] <= #1 {dr[30:0], 1'b0};
|
|
latch_data <= #1 1'b0;
|
|
dr_text = "shift word";
|
|
end
|
|
end
|
|
endcase
|
|
end
|
|
else if (enable && (!addr_len_cnt_end))
|
|
begin
|
|
dr <= #1 {dr[`DBG_CPU_DR_LEN -2:0], tdi_i};
|
|
dr_text = "shift dr";
|
|
end
|
|
end
|
|
|
|
|
|
|
assign cmd_cnt_en = enable & (~cmd_cnt_end);
|
assign cmd_cnt_en = enable & (~cmd_cnt_end);
|
|
|
|
|
// Command counter
|
// Command counter
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
cmd_cnt <= #1 2'h0;
|
cmd_cnt <= #1 {`DBG_CPU_CMD_CNT_WIDTH{1'b0}};
|
else if (update_dr_i)
|
else if (update_dr_i)
|
cmd_cnt <= #1 2'h0;
|
cmd_cnt <= #1 {`DBG_CPU_CMD_CNT_WIDTH{1'b0}};
|
else if (cmd_cnt_en)
|
else if (cmd_cnt_en)
|
cmd_cnt <= #1 cmd_cnt + 1'b1;
|
cmd_cnt <= #1 cmd_cnt + 1'b1;
|
end
|
end
|
|
|
|
|
assign addr_cnt_en = enable & cmd_cnt_end & (~addr_cnt_end);
|
// Assigning current command
|
|
always @ (posedge tck_i or posedge rst_i)
|
|
begin
|
|
if (rst_i)
|
|
curr_cmd <= #1 {`DBG_CPU_CMD_LEN{1'b0}};
|
|
else if (update_dr_i)
|
|
curr_cmd <= #1 {`DBG_CPU_CMD_LEN{1'b0}};
|
|
else if (cmd_cnt == (`DBG_CPU_CMD_LEN -1))
|
|
curr_cmd <= #1 {dr[`DBG_CPU_CMD_LEN-2 :0], tdi_i};
|
|
end
|
|
|
|
|
|
// Assigning current command
|
|
always @ (posedge tck_i or posedge rst_i)
|
|
begin
|
|
if (rst_i)
|
|
curr_cmd_go_q <= #1 1'b0;
|
|
else
|
|
curr_cmd_go_q <= #1 curr_cmd_go;
|
|
end
|
|
|
|
|
|
always @ (enable or cmd_cnt_end or addr_len_cnt_end or curr_cmd_wr_comm or curr_cmd_wr_ctrl or curr_cmd_rd_comm or curr_cmd_rd_ctrl or crc_cnt_end)
|
|
begin
|
|
if (enable && (!addr_len_cnt_end))
|
|
begin
|
|
if (cmd_cnt_end && (curr_cmd_wr_comm || curr_cmd_wr_ctrl))
|
|
addr_len_cnt_en = 1'b1;
|
|
else if (crc_cnt_end && (curr_cmd_rd_comm || curr_cmd_rd_ctrl))
|
|
addr_len_cnt_en = 1'b1;
|
|
else
|
|
addr_len_cnt_en = 1'b0;
|
|
end
|
|
else
|
|
addr_len_cnt_en = 1'b0;
|
|
end
|
|
|
|
|
// Address/length counter
|
// Address/length counter
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
addr_cnt <= #1 6'h0;
|
addr_len_cnt <= #1 6'h0;
|
else if (update_dr_i)
|
else if (update_dr_i)
|
addr_cnt <= #1 6'h0;
|
addr_len_cnt <= #1 6'h0;
|
else if (addr_cnt_en)
|
else if (addr_len_cnt_en)
|
addr_cnt <= #1 addr_cnt + 1'b1;
|
addr_len_cnt <= #1 addr_len_cnt + 1'b1;
|
end
|
end
|
|
|
|
|
assign data_cnt_en = enable & (~data_cnt_end) & (cmd_cnt_end & write_cycle | crc_cnt_end & read_cycle);
|
always @ (enable or data_cnt_end or cmd_cnt_end or curr_cmd_go or acc_type_write or acc_type_read or crc_cnt_end)
|
|
begin
|
|
if (enable && (!data_cnt_end))
|
|
begin
|
|
if (cmd_cnt_end && curr_cmd_go && acc_type_write)
|
|
data_cnt_en = 1'b1;
|
|
else if (crc_cnt_end && curr_cmd_go && acc_type_read)
|
|
data_cnt_en = 1'b1;
|
|
else
|
|
data_cnt_en = 1'b0;
|
|
end
|
|
else
|
|
data_cnt_en = 1'b0;
|
|
end
|
|
|
|
|
// Data counter
|
// Data counter
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
data_cnt <= #1 6'h0;
|
data_cnt <= #1 {`DBG_CPU_DATA_CNT_WIDTH{1'b0}};
|
else if (update_dr_i)
|
else if (update_dr_i)
|
data_cnt <= #1 6'h0;
|
data_cnt <= #1 {`DBG_CPU_DATA_CNT_WIDTH{1'b0}};
|
else if (data_cnt_en)
|
else if (data_cnt_en)
|
data_cnt <= #1 data_cnt + 1'b1;
|
data_cnt <= #1 data_cnt + 1'b1;
|
end
|
end
|
|
|
|
|
assign crc_cnt_en = enable & (~crc_cnt_end) & (cmd_cnt_end & addr_cnt_end & (~write_cycle) | (data_cnt_end & write_cycle));
|
|
|
|
|
|
// crc counter
|
// Upper limit. Data counter counts until this value is reached.
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
crc_cnt <= #1 6'h0;
|
data_cnt_limit <= #1 {`DBG_CPU_DATA_CNT_WIDTH{1'b0}};
|
else if(crc_cnt_en)
|
|
crc_cnt <= #1 crc_cnt + 1'b1;
|
|
else if (update_dr_i)
|
else if (update_dr_i)
|
crc_cnt <= #1 6'h0;
|
data_cnt_limit <= #1 {len + 1'b1, 3'b000};
|
end
|
end
|
|
|
|
|
// Upper limit. Address/length counter counts until this value is reached
|
always @ (enable or crc_cnt_end or curr_cmd_rd_comm or curr_cmd_rd_ctrl or curr_cmd_wr_comm or curr_cmd_wr_ctrl or curr_cmd_go or addr_len_cnt_end or data_cnt_end or acc_type_write or acc_type_read or cmd_cnt_end)
|
always @ (posedge tck_i or posedge rst_i)
|
|
begin
|
begin
|
if (rst_i)
|
if (enable && (!crc_cnt_end) && cmd_cnt_end)
|
addr_cnt_limit = 6'd0;
|
|
else if (cmd_cnt == 2'h2)
|
|
begin
|
begin
|
if ((~dr[0]) & (~tdi_i)) // (current command is WB_STATUS or WB_GO)
|
if (addr_len_cnt_end && (curr_cmd_wr_comm || curr_cmd_wr_ctrl))
|
addr_cnt_limit = 6'd0;
|
crc_cnt_en = 1'b1;
|
else // (current command is WB_WRITEx or WB_READx)
|
else if (data_cnt_end && curr_cmd_go && acc_type_write)
|
addr_cnt_limit = 6'd32;
|
crc_cnt_en = 1'b1;
|
|
else if (cmd_cnt_end && (curr_cmd_go && acc_type_read || curr_cmd_rd_comm || curr_cmd_rd_ctrl))
|
|
crc_cnt_en = 1'b1;
|
|
else
|
|
crc_cnt_en = 1'b0;
|
end
|
end
|
|
else
|
|
crc_cnt_en = 1'b0;
|
end
|
end
|
|
|
|
|
assign cmd_cnt_end = cmd_cnt == 2'h3;
|
// crc counter
|
assign addr_cnt_end = addr_cnt == addr_cnt_limit;
|
always @ (posedge tck_i or posedge rst_i)
|
assign crc_cnt_end = crc_cnt == 6'd32;
|
begin
|
assign crc_cnt_31 = crc_cnt == 6'd31;
|
if (rst_i)
|
|
crc_cnt <= #1 {`DBG_CPU_CRC_CNT_WIDTH{1'b0}};
|
|
else if(crc_cnt_en)
|
|
crc_cnt <= #1 crc_cnt + 1'b1;
|
|
else if (update_dr_i)
|
|
crc_cnt <= #1 {`DBG_CPU_CRC_CNT_WIDTH{1'b0}};
|
|
end
|
|
|
|
assign cmd_cnt_end = cmd_cnt == `DBG_CPU_CMD_LEN;
|
|
assign addr_len_cnt_end = addr_len_cnt == `DBG_CPU_DR_LEN;
|
|
assign crc_cnt_end = crc_cnt == `DBG_CPU_CRC_CNT_WIDTH'd32;
|
|
assign crc_cnt_31 = crc_cnt == `DBG_CPU_CRC_CNT_WIDTH'd31;
|
assign data_cnt_end = (data_cnt == data_cnt_limit);
|
assign data_cnt_end = (data_cnt == data_cnt_limit);
|
|
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
begin
|
begin
|
crc_cnt_end_q <= #1 1'b0;
|
crc_cnt_end_q <= #1 1'b0;
|
cmd_cnt_end_q <= #1 1'b0;
|
cmd_cnt_end_q <= #1 1'b0;
|
data_cnt_end_q <= #1 1'b0;
|
data_cnt_end_q <= #1 1'b0;
|
|
addr_len_cnt_end_q <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
crc_cnt_end_q <= #1 crc_cnt_end;
|
crc_cnt_end_q <= #1 crc_cnt_end;
|
cmd_cnt_end_q <= #1 cmd_cnt_end;
|
cmd_cnt_end_q <= #1 cmd_cnt_end;
|
data_cnt_end_q <= #1 data_cnt_end;
|
data_cnt_end_q <= #1 data_cnt_end;
|
|
addr_len_cnt_end_q <= #1 addr_len_cnt_end;
|
end
|
end
|
end
|
end
|
|
|
|
|
// Status counter is made of 4 serialy connected registers
|
// Status counter is made of 4 serialy connected registers
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
status_cnt1 <= #1 1'b0;
|
status_cnt <= #1 {`DBG_CPU_STATUS_CNT_WIDTH{1'b0}};
|
else if (update_dr_i)
|
else if (update_dr_i)
|
status_cnt1 <= #1 1'b0;
|
status_cnt <= #1 {`DBG_CPU_STATUS_CNT_WIDTH{1'b0}};
|
else if (data_cnt_end & read_cycle |
|
else if (status_cnt_en)
|
crc_cnt_end & (~read_cycle)
|
status_cnt <= #1 status_cnt + 1'b1;
|
)
|
end
|
status_cnt1 <= #1 1'b1;
|
|
|
|
|
always @ (enable or status_cnt_end or crc_cnt_end or curr_cmd_rd_comm or curr_cmd_rd_ctrl or curr_cmd_wr_comm or curr_cmd_wr_ctrl or curr_cmd_go or acc_type_write or data_cnt_end or addr_len_cnt_end)
|
|
begin
|
|
if (enable && (!status_cnt_end))
|
|
begin
|
|
if (crc_cnt_end && (curr_cmd_wr_comm || curr_cmd_wr_ctrl))
|
|
status_cnt_en = 1'b1;
|
|
else if (crc_cnt_end && curr_cmd_go && acc_type_write)
|
|
status_cnt_en = 1'b1;
|
|
else if (data_cnt_end && curr_cmd_go && acc_type_read)
|
|
status_cnt_en = 1'b1;
|
|
else if (addr_len_cnt_end && (curr_cmd_rd_comm || curr_cmd_rd_ctrl))
|
|
status_cnt_en = 1'b1;
|
|
else
|
|
status_cnt_en = 1'b0;
|
|
end
|
|
else
|
|
status_cnt_en = 1'b0;
|
end
|
end
|
|
|
|
|
|
assign status_cnt_end = status_cnt == `DBG_CPU_STATUS_LEN;
|
|
|
|
|
|
// Latching acc_type, address and length
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
begin
|
begin
|
status_cnt2 <= #1 1'b0;
|
acc_type <= #1 {`DBG_CPU_ACC_TYPE_LEN{1'b0}};
|
status_cnt3 <= #1 1'b0;
|
adr <= #1 {`DBG_CPU_ADR_LEN{1'b0}};
|
status_cnt4 <= #1 1'b0;
|
len <= #1 {`DBG_CPU_LEN_LEN{1'b0}};
|
|
set_addr <= #1 1'b0;
|
end
|
end
|
else if (update_dr_i)
|
else if(crc_cnt_end && (!crc_cnt_end_q) && crc_match_i && curr_cmd_wr_comm)
|
begin
|
begin
|
status_cnt2 <= #1 1'b0;
|
acc_type <= #1 dr[`DBG_CPU_ACC_TYPE_LEN + `DBG_CPU_ADR_LEN + `DBG_CPU_LEN_LEN -1 : `DBG_CPU_ADR_LEN + `DBG_CPU_LEN_LEN];
|
status_cnt3 <= #1 1'b0;
|
adr <= #1 dr[`DBG_CPU_ADR_LEN + `DBG_CPU_LEN_LEN -1 : `DBG_CPU_LEN_LEN];
|
status_cnt4 <= #1 1'b0;
|
len <= #1 dr[`DBG_CPU_LEN_LEN -1:0];
|
|
set_addr <= #1 1'b1;
|
end
|
end
|
else
|
else if(cpu_end_tck) // Writing back the address
|
begin
|
begin
|
status_cnt2 <= #1 status_cnt1;
|
adr <= #1 cpu_addr_dsff;
|
status_cnt3 <= #1 status_cnt2;
|
|
status_cnt4 <= #1 status_cnt3;
|
|
end
|
end
|
|
else
|
|
set_addr <= #1 1'b0;
|
end
|
end
|
|
|
|
|
assign status_cnt_end = status_cnt4;
|
|
|
|
|
|
|
|
|
|
// Latching address
|
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
adr <= #1 32'h0;
|
crc_match_reg <= #1 1'b0;
|
else if(crc_cnt_end & (~crc_cnt_end_q) & crc_match_i & (~dr_go_latched))
|
else if(crc_cnt_end & (~crc_cnt_end_q))
|
adr <= #1 dr[31:0];
|
crc_match_reg <= #1 crc_match_i;
|
end
|
end
|
|
|
|
|
assign cpu_addr_o = adr;
|
// Length counter
|
|
|
|
|
// Shift register for shifting in and out the data
|
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
dr <= #1 32'h0;
|
len_var <= #1 {1'b0, {`DBG_CPU_LEN_LEN{1'b0}}};
|
else if (reg_access)
|
else if(update_dr_i)
|
dr[31:24] <= #1 reg_data_out;
|
len_var <= #1 len + 1'b1;
|
else if (cpu_ack_tck & (~cpu_ack_tck_q) & read_cycle_cpu)
|
else if (start_rd_tck)
|
begin
|
begin
|
if (cycle_32_bit)
|
if (len_var > 'd4)
|
dr[31:0] <= #1 cpu_data_i;
|
len_var <= #1 len_var - 3'd4;
|
else
|
else
|
dr[31:24] <= #1 cpu_data_i[7:0];
|
len_var <= #1 {1'b0, {`DBG_CPU_LEN_LEN{1'b0}}};
|
end
|
|
else if (enable & ((~addr_cnt_end) | (~cmd_cnt_end) | ((~data_cnt_end) & write_cycle) | (crc_cnt_end & (~data_cnt_end) & read_cycle)))
|
|
begin
|
|
dr <= #1 {dr[30:0], tdi_i};
|
|
end
|
end
|
end
|
end
|
|
|
|
|
assign dr_read_reg = dr[2:0] == `CPU_READ_REG;
|
assign len_eq_0 = len_var == 'h0;
|
assign dr_write_reg = dr[2:0] == `CPU_WRITE_REG;
|
|
assign dr_read_cpu8 = dr[2:0] == `CPU_READ8;
|
|
assign dr_read_cpu32 = dr[2:0] == `CPU_READ32;
|
assign half = data_cnt[3:0] == 4'd15;
|
assign dr_write_cpu8 = dr[2:0] == `CPU_WRITE8;
|
assign long = data_cnt[4:0] == 5'd31;
|
assign dr_write_cpu32 = dr[2:0] == `CPU_WRITE32;
|
|
assign dr_go = dr[2:0] == `CPU_GO;
|
|
|
|
|
|
// Latching instruction
|
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
begin
|
begin
|
dr_read_reg_latched <= #1 1'b0;
|
half_q <= #1 1'b0;
|
dr_read_cpu8_latched <= #1 1'b0;
|
long_q <= #1 1'b0;
|
dr_read_cpu32_latched <= #1 1'b0;
|
|
dr_write_reg_latched <= #1 1'b0;
|
|
dr_write_cpu8_latched <= #1 1'b0;
|
|
dr_write_cpu32_latched <= #1 1'b0;
|
|
dr_go_latched <= #1 1'b0;
|
|
end
|
end
|
else if (update_dr_i)
|
else
|
begin
|
|
dr_read_reg_latched <= #1 1'b0;
|
|
dr_read_cpu8_latched <= #1 1'b0;
|
|
dr_read_cpu32_latched <= #1 1'b0;
|
|
dr_write_reg_latched <= #1 1'b0;
|
|
dr_write_cpu8_latched <= #1 1'b0;
|
|
dr_write_cpu32_latched <= #1 1'b0;
|
|
dr_go_latched <= #1 1'b0;
|
|
end
|
|
else if (cmd_cnt_end & (~cmd_cnt_end_q))
|
|
begin
|
begin
|
dr_read_reg_latched <= #1 dr_read_reg;
|
half_q <= #1 half;
|
dr_read_cpu8_latched <= #1 dr_read_cpu8;
|
long_q <= #1 long;
|
dr_read_cpu32_latched <= #1 dr_read_cpu32;
|
|
dr_write_reg_latched <= #1 dr_write_reg;
|
|
dr_write_cpu8_latched <= #1 dr_write_cpu8;
|
|
dr_write_cpu32_latched <= #1 dr_write_cpu32;
|
|
dr_go_latched <= #1 dr_go;
|
|
end
|
end
|
end
|
end
|
|
|
// Latching instruction
|
|
|
// Start cpu write cycle
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
begin
|
begin
|
cmd_read_reg <= #1 1'b0;
|
start_wr_tck <= #1 1'b0;
|
cmd_read_cpu <= #1 1'b0;
|
cpu_dat_tmp <= #1 32'h0;
|
cmd_write_reg <= #1 1'b0;
|
end
|
cmd_write_cpu <= #1 1'b0;
|
else if (curr_cmd_go && acc_type_write)
|
cycle_32_bit <= #1 1'b0;
|
begin
|
|
if (long_q)
|
|
begin
|
|
start_wr_tck <= #1 1'b1;
|
|
cpu_dat_tmp <= #1 dr[31:0];
|
end
|
end
|
else if(crc_cnt_end & (~crc_cnt_end_q) & crc_match_i)
|
else
|
begin
|
begin
|
cmd_read_reg <= #1 dr_read_reg_latched;
|
start_wr_tck <= #1 1'b0;
|
cmd_read_cpu <= #1 dr_read_cpu8_latched | dr_read_cpu32_latched;
|
end
|
cmd_write_reg <= #1 dr_write_reg_latched;
|
|
cmd_write_cpu <= #1 dr_write_cpu8_latched | dr_write_cpu32_latched;
|
|
cycle_32_bit <= #1 dr_read_cpu32_latched | dr_write_cpu32_latched;
|
|
end
|
end
|
|
else
|
|
start_wr_tck <= #1 1'b0;
|
end
|
end
|
|
|
|
|
// Upper limit. Data counter counts until this value is reached.
|
// cpu_data_o in WB clk domain
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge cpu_clk_i)
|
begin
|
|
if (rst_i)
|
|
data_cnt_limit <= #1 6'h0;
|
|
else if(crc_cnt_end & (~crc_cnt_end_q) & crc_match_i & (~dr_go_latched))
|
|
begin
|
begin
|
if (dr_read_cpu32_latched | dr_write_cpu32_latched)
|
cpu_data_dsff <= #1 cpu_dat_tmp;
|
data_cnt_limit <= #1 6'd32;
|
|
else
|
|
data_cnt_limit <= #1 6'd8;
|
|
end
|
|
end
|
end
|
|
|
|
assign cpu_data_o = cpu_data_dsff;
|
assign go_prelim = (cmd_cnt == 2'h2) & dr[1] & (~dr[0]) & (~tdi_i);
|
|
|
|
|
|
|
// Start cpu read cycle
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
read_cycle_reg <= #1 1'b0;
|
start_rd_tck <= #1 1'b0;
|
else if (update_dr_i)
|
else if (curr_cmd_go && (!curr_cmd_go_q) && acc_type_read) // First read after cmd is entered
|
read_cycle_reg <= #1 1'b0;
|
start_rd_tck <= #1 1'b1;
|
else if (cmd_read_reg & go_prelim)
|
else if ((!start_rd_tck) && curr_cmd_go && acc_type_read && (!len_eq_0) && (!fifo_full) && (!rd_tck_started) && (!cpu_ack_tck))
|
read_cycle_reg <= #1 1'b1;
|
start_rd_tck <= #1 1'b1;
|
|
else
|
|
start_rd_tck <= #1 1'b0;
|
end
|
end
|
|
|
|
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
read_cycle_cpu <= #1 1'b0;
|
rd_tck_started <= #1 1'b0;
|
else if (update_dr_i)
|
else if (update_dr_i || cpu_end_tck && (!cpu_end_tck_q))
|
read_cycle_cpu <= #1 1'b0;
|
rd_tck_started <= #1 1'b0;
|
else if (cmd_read_cpu & go_prelim)
|
else if (start_rd_tck)
|
read_cycle_cpu <= #1 1'b1;
|
rd_tck_started <= #1 1'b1;
|
end
|
end
|
|
|
|
|
always @ (posedge tck_i or posedge rst_i)
|
|
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
begin
|
begin
|
read_cycle_reg_q <= #1 1'b0;
|
start_rd_csff <= #1 1'b0;
|
read_cycle_cpu_q <= #1 1'b0;
|
start_cpu_rd <= #1 1'b0;
|
|
start_cpu_rd_q <= #1 1'b0;
|
|
|
|
start_wr_csff <= #1 1'b0;
|
|
start_cpu_wr <= #1 1'b0;
|
|
start_cpu_wr_q <= #1 1'b0;
|
|
|
|
set_addr_csff <= #1 1'b0;
|
|
set_addr_cpu <= #1 1'b0;
|
|
set_addr_cpu_q <= #1 1'b0;
|
|
|
|
cpu_ack_q <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
read_cycle_reg_q <= #1 read_cycle_reg;
|
start_rd_csff <= #1 start_rd_tck;
|
read_cycle_cpu_q <= #1 read_cycle_cpu;
|
start_cpu_rd <= #1 start_rd_csff;
|
|
start_cpu_rd_q <= #1 start_cpu_rd;
|
|
|
|
start_wr_csff <= #1 start_wr_tck;
|
|
start_cpu_wr <= #1 start_wr_csff;
|
|
start_cpu_wr_q <= #1 start_cpu_wr;
|
|
|
|
set_addr_csff <= #1 set_addr;
|
|
set_addr_cpu <= #1 set_addr_csff;
|
|
set_addr_cpu_q <= #1 set_addr_cpu;
|
|
|
|
cpu_ack_q <= #1 cpu_ack_i;
|
end
|
end
|
end
|
end
|
|
|
|
|
always @ (posedge tck_i or posedge rst_i)
|
// cpu_stb_o
|
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
write_cycle_reg <= #1 1'b0;
|
cpu_stb_o <= #1 1'b0;
|
else if (update_dr_i)
|
else if (cpu_ack_i)
|
write_cycle_reg <= #1 1'b0;
|
cpu_stb_o <= #1 1'b0;
|
else if (cmd_write_reg & go_prelim)
|
else if ((start_cpu_wr && (!start_cpu_wr_q)) || (start_cpu_rd && (!start_cpu_rd_q)))
|
write_cycle_reg <= #1 1'b1;
|
cpu_stb_o <= #1 1'b1;
|
end
|
end
|
|
|
|
|
always @ (posedge tck_i or posedge rst_i)
|
assign cpu_stall_o = cpu_stb_o | cpu_reg_stall;
|
|
|
|
|
|
// cpu_addr_o logic
|
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
write_cycle_cpu <= #1 1'b0;
|
cpu_addr_dsff <= #1 32'h0;
|
else if (update_dr_i)
|
else if (set_addr_cpu && (!set_addr_cpu_q)) // Setting starting address
|
write_cycle_cpu <= #1 1'b0;
|
cpu_addr_dsff <= #1 adr;
|
else if (cmd_write_cpu & go_prelim)
|
else if (cpu_ack_i && (!cpu_ack_q))
|
write_cycle_cpu <= #1 1'b1;
|
cpu_addr_dsff <= #1 cpu_addr_dsff + 3'd4;
|
end
|
end
|
|
|
|
|
assign read_cycle = read_cycle_reg | read_cycle_cpu;
|
assign cpu_addr_o = cpu_addr_dsff;
|
assign write_cycle = write_cycle_reg | write_cycle_cpu;
|
|
|
|
|
|
|
always @ (posedge cpu_clk_i)
|
|
begin
|
|
cpu_we_dsff <= #1 curr_cmd_go && acc_type_write;
|
|
end
|
|
|
// Start register access cycle
|
|
always @ (posedge tck_i or posedge rst_i)
|
assign cpu_we_o = cpu_we_dsff;
|
|
|
|
|
|
|
|
// Logic for detecting end of transaction
|
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
reg_access <= #1 1'b0;
|
cpu_end <= #1 1'b0;
|
else if (write_cycle_reg & data_cnt_end & (~data_cnt_end_q) | read_cycle_reg & (~read_cycle_reg_q))
|
else if (cpu_ack_i && (!cpu_ack_q))
|
reg_access <= #1 1'b1;
|
cpu_end <= #1 1'b1;
|
else
|
else if (cpu_end_rst)
|
reg_access <= #1 1'b0;
|
cpu_end <= #1 1'b0;
|
end
|
end
|
|
|
|
|
|
always @ (posedge tck_i or posedge rst_i)
|
// Connecting dbg_cpu_registers
|
begin
|
dbg_cpu_registers i_dbg_cpu_registers
|
if (rst_i)
|
(
|
begin
|
.data_i (dr[7:0]),
|
cpu_end_csff <= #1 1'b0;
|
.data_o (reg_data_out),
|
cpu_end_tck <= #1 1'b0;
|
.addr_i (adr[1:0]),
|
cpu_end_tck_q <= #1 1'b0;
|
.we_i (write_cycle_reg),
|
end
|
.en_i (reg_access),
|
else
|
.clk_i (tck_i),
|
begin
|
.bp_i (cpu_bp_i),
|
cpu_end_csff <= #1 cpu_end;
|
.rst_i (rst_i),
|
cpu_end_tck <= #1 cpu_end_csff;
|
.cpu_clk_i (cpu_clk_i),
|
cpu_end_tck_q <= #1 cpu_end_tck;
|
.cpu_stall_o (cpu_stall_tmp),
|
end
|
.cpu_stall_all_o (cpu_stall_all_o),
|
end
|
.cpu_sel_o (cpu_sel_o),
|
|
.cpu_rst_o (cpu_rst_o)
|
|
);
|
|
|
|
|
|
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
|
begin
|
|
if (rst_i)
|
|
begin
|
|
cpu_end_rst_csff <= #1 1'b0;
|
|
cpu_end_rst <= #1 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
cpu_end_rst_csff <= #1 cpu_end_tck;
|
|
cpu_end_rst <= #1 cpu_end_rst_csff;
|
|
end
|
|
end
|
|
|
assign cpu_we_o = write_cycle_cpu;
|
|
assign cpu_data_o = dr[31:0];
|
|
assign cpu_stall_o = cpu_stb_o | cpu_stall_tmp;
|
|
|
|
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
|
begin
|
|
if (rst_i)
|
|
busy_cpu <= #1 1'b0;
|
|
else if (cpu_end_rst)
|
|
busy_cpu <= #1 1'b0;
|
|
else if (cpu_stb_o)
|
|
busy_cpu <= #1 1'b1;
|
|
end
|
|
|
|
|
// Synchronizing ack signal from cpu
|
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
begin
|
begin
|
cpu_ack_sync <= #1 1'b0;
|
busy_csff <= #1 1'b0;
|
cpu_ack_tck <= #1 1'b0;
|
busy_tck <= #1 1'b0;
|
cpu_ack_tck_q <= #1 1'b0;
|
|
|
update_dr_csff <= #1 1'b0;
|
|
update_dr_cpu <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
cpu_ack_sync <= #1 cpu_ack_i;
|
busy_csff <= #1 busy_cpu;
|
cpu_ack_tck <= #1 cpu_ack_sync;
|
busy_tck <= #1 busy_csff;
|
cpu_ack_tck_q <= #1 cpu_ack_tck;
|
|
|
update_dr_csff <= #1 update_dr_i;
|
|
update_dr_cpu <= #1 update_dr_csff;
|
end
|
end
|
end
|
end
|
|
|
|
|
|
// Detecting overrun when write operation.
|
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
|
begin
|
|
if (rst_i)
|
|
cpu_overrun <= #1 1'b0;
|
|
else if(start_cpu_wr && (!start_cpu_wr_q) && cpu_ack_i)
|
|
cpu_overrun <= #1 1'b1;
|
|
else if(update_dr_cpu) // error remains active until update_dr arrives
|
|
cpu_overrun <= #1 1'b0;
|
|
end
|
|
|
|
|
// Start cpu access cycle
|
// Detecting underrun when read operation
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
cpu_stb <= #1 1'b0;
|
underrun_tck <= #1 1'b0;
|
else if (update_dr_i | cpu_ack_tck)
|
else if(latch_data && (!fifo_full) && (!data_cnt_end))
|
cpu_stb <= #1 1'b0;
|
underrun_tck <= #1 1'b1;
|
else if (write_cycle_cpu & data_cnt_end & (~data_cnt_end_q) | read_cycle_cpu & (~read_cycle_cpu_q))
|
else if(update_dr_i) // error remains active until update_dr arrives
|
cpu_stb <= #1 1'b1;
|
underrun_tck <= #1 1'b0;
|
|
end
|
|
|
|
|
|
always @ (posedge tck_i or posedge rst_i)
|
|
begin
|
|
if (rst_i)
|
|
begin
|
|
cpu_overrun_csff <= #1 1'b0;
|
|
cpu_overrun_tck <= #1 1'b0;
|
|
|
|
cpu_ack_csff <= #1 1'b0;
|
|
cpu_ack_tck <= #1 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
cpu_overrun_csff <= #1 cpu_overrun;
|
|
cpu_overrun_tck <= #1 cpu_overrun_csff;
|
|
|
|
cpu_ack_csff <= #1 cpu_ack_i;
|
|
cpu_ack_tck <= #1 cpu_ack_csff;
|
|
end
|
end
|
end
|
|
|
|
|
|
|
// Synchronizing cpu_stb to cpu_clk_i clock
|
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
always @ (posedge cpu_clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
begin
|
begin
|
cpu_stb_sync <= #1 1'b0;
|
cpu_ce_csff <= #1 1'b0;
|
cpu_stb_o <= #1 1'b0;
|
mem_ptr_init <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
cpu_stb_sync <= #1 cpu_stb;
|
cpu_ce_csff <= #1 cpu_ce_i;
|
cpu_stb_o <= #1 cpu_stb_sync;
|
mem_ptr_init <= #1 ~cpu_ce_csff;
|
end
|
end
|
end
|
end
|
|
|
|
|
// Latching crc
|
// Logic for latching data that is read from cpu
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge cpu_clk_i)
|
begin
|
begin
|
if (rst_i)
|
if (cpu_ack_i && (!cpu_ack_q))
|
crc_match_reg <= #1 1'b0;
|
begin
|
else if(crc_cnt_end & (~crc_cnt_end_q))
|
mem[0] <= #1 cpu_data_i[31:24];
|
crc_match_reg <= #1 crc_match_i;
|
mem[1] <= #1 cpu_data_i[23:16];
|
|
mem[2] <= #1 cpu_data_i[15:08];
|
|
mem[3] <= #1 cpu_data_i[07:00];
|
|
end
|
end
|
end
|
|
|
|
|
|
assign input_data = {mem[0], mem[1], mem[2], mem[3]};
|
|
|
// Status register
|
|
|
// Fifo counter and empty/full detection
|
always @ (posedge tck_i or posedge rst_i)
|
always @ (posedge tck_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
status <= #1 4'h0;
|
fifo_full <= #1 1'h0;
|
else if(crc_cnt_end & (~crc_cnt_end_q) & (~read_cycle))
|
else if (update_dr_i)
|
status <= #1 {crc_match_i, 1'b0, 1'b1, 1'b0};
|
fifo_full <= #1 1'h0;
|
else if (data_cnt_end & (~data_cnt_end_q) & read_cycle)
|
else if (cpu_end_tck && (!cpu_end_tck_q) && (!latch_data) && (!fifo_full)) // incrementing
|
status <= #1 {crc_match_reg, 1'b0, 1'b1, 1'b0};
|
fifo_full <= #1 1'b1;
|
else if (shift_dr_i & (~status_cnt_end))
|
else if (!(cpu_end_tck && (!cpu_end_tck_q)) && latch_data && (fifo_full)) // decrementing
|
status <= #1 {status[0], status[3:1]};
|
fifo_full <= #1 1'h0;
|
end
|
end
|
// Following status is shifted out:
|
|
// 1. bit: 1 if crc is OK, else 0
|
|
// 2. bit: 1'b0
|
|
// 3. bit: 1'b1
|
|
// 4. bit: 1'b0
|
|
|
|
|
|
|
reg [799:0] tdo_text;
|
|
|
// TDO multiplexer
|
// TDO multiplexer
|
always @ (crc_cnt_end or crc_cnt_end_q or crc_match_i or data_cnt_end or data_cnt_end_q or
|
always @ (pause_dr_i or busy_tck or crc_cnt_end or crc_cnt_end_q or curr_cmd_wr_comm or curr_cmd_wr_ctrl or curr_cmd_go or acc_type_write or acc_type_read or crc_match_i or data_cnt_end or dr or data_cnt_end_q or crc_match_reg or status_cnt_en or status or addr_len_cnt_end or addr_len_cnt_end_q or curr_cmd_rd_comm or curr_cmd_rd_ctrl)
|
read_cycle or crc_match_reg or status or dr)
|
|
begin
|
begin
|
if (crc_cnt_end & (~crc_cnt_end_q) & (~(read_cycle)))
|
if (pause_dr_i)
|
begin
|
begin
|
tdo_o = crc_match_i;
|
tdo_o = busy_tck;
|
|
tdo_text = "busy_tck";
|
end
|
end
|
else if (read_cycle & crc_cnt_end & (~data_cnt_end))
|
else if (crc_cnt_end && (!crc_cnt_end_q) && (curr_cmd_wr_comm || curr_cmd_wr_ctrl || curr_cmd_go && acc_type_write ))
|
|
begin
|
|
tdo_o = ~crc_match_i;
|
|
tdo_text = "crc_match_i";
|
|
end
|
|
else if (curr_cmd_go && acc_type_read && crc_cnt_end && (!data_cnt_end))
|
begin
|
begin
|
tdo_o = dr[31];
|
tdo_o = dr[31];
|
|
tdo_text = "dr[31]";
|
|
end
|
|
else if (curr_cmd_go && acc_type_read && data_cnt_end && (!data_cnt_end_q))
|
|
begin
|
|
tdo_o = ~crc_match_reg;
|
|
tdo_text = "crc_match_reg";
|
end
|
end
|
else if (read_cycle & data_cnt_end & (~data_cnt_end_q)) // cmd is already updated
|
else if ((curr_cmd_rd_comm || curr_cmd_rd_ctrl) && addr_len_cnt_end && (!addr_len_cnt_end_q))
|
begin
|
begin
|
tdo_o = crc_match_reg;
|
tdo_o = ~crc_match_reg;
|
|
tdo_text = "crc_match_reg_rd_comm";
|
end
|
end
|
else if (crc_cnt_end)
|
else if ((curr_cmd_rd_comm || curr_cmd_rd_ctrl) && crc_cnt_end && (!addr_len_cnt_end))
|
begin
|
begin
|
tdo_o = status[0];
|
tdo_o = dr[`DBG_CPU_ACC_TYPE_LEN + `DBG_CPU_ADR_LEN + `DBG_CPU_LEN_LEN -1];
|
|
tdo_text = "rd_comm | rd_ctrl data";
|
|
end
|
|
else if (status_cnt_en)
|
|
begin
|
|
tdo_o = status[3];
|
|
tdo_text = "status";
|
end
|
end
|
else
|
else
|
begin
|
begin
|
tdo_o = 1'b0;
|
tdo_o = 1'b0;
|
|
tdo_text = "zero";
|
|
end
|
|
end
|
|
|
|
reg [799:0] status_text;
|
|
// Status register
|
|
always @ (posedge tck_i or posedge rst_i)
|
|
begin
|
|
if (rst_i)
|
|
begin
|
|
status <= #1 {`DBG_CPU_STATUS_LEN{1'b0}};
|
|
status_text = "reset";
|
|
end
|
|
else if(crc_cnt_end && (!crc_cnt_end_q) && (!(curr_cmd_go && acc_type_read)))
|
|
begin
|
|
status <= #1 {1'b0, 1'b0, cpu_overrun_tck, crc_match_i};
|
|
status_text = "latch ni read";
|
|
end
|
|
else if (data_cnt_end && (!data_cnt_end_q) && curr_cmd_go && acc_type_read)
|
|
begin
|
|
status <= #1 {1'b0, 1'b0, underrun_tck, crc_match_reg};
|
|
status_text = "latch read";
|
|
end
|
|
else if (addr_len_cnt_end && (!addr_len_cnt_end) && (curr_cmd_rd_comm || curr_cmd_rd_ctrl))
|
|
begin
|
|
status <= #1 {1'b0, 1'b0, 1'b0, crc_match_reg};
|
|
status_text = "rd_comm | rd_ctrl";
|
|
end
|
|
else if (shift_dr_i && (!status_cnt_end))
|
|
begin
|
|
status <= #1 {status[`DBG_CPU_STATUS_LEN -2:0], status[`DBG_CPU_STATUS_LEN -1]};
|
|
status_text = "shifting";
|
end
|
end
|
end
|
end
|
|
// Following status is shifted out (MSB first):
|
|
// 3. bit: 1 if crc is OK, else 0
|
|
// 2. bit: 1'b0
|
|
// 1. bit: 0
|
|
// 0. bit: 1 if overrun occured during write (data couldn't be written fast enough)
|
|
// or underrun occured during read (data couldn't be read fast enough)
|
|
|
|
|
|
|
|
// Connecting cpu registers
|
|
assign cpu_reg_we = crc_cnt_end && (!crc_cnt_end_q) && crc_match_i && curr_cmd_wr_ctrl;
|
|
assign cpu_reg_data_i = dr[`DBG_CPU_DR_LEN -1:`DBG_CPU_DR_LEN -`DBG_CPU_CTRL_LEN];
|
|
|
|
dbg_cpu_registers i_dbg_cpu_registers
|
|
(
|
|
.data_i (cpu_reg_data_i),
|
|
.we_i (cpu_reg_we),
|
|
.tck_i (tck_i),
|
|
.bp_i (cpu_bp_i),
|
|
.rst_i (rst_i),
|
|
.cpu_clk_i (cpu_clk_i),
|
|
.ctrl_reg_o (ctrl_reg),
|
|
.cpu_stall_o (cpu_reg_stall),
|
|
.cpu_rst_o (cpu_rst_o)
|
|
);
|
|
|
|
|
|
|
|
|
|
|