| ////////////////////////////////////////////////////////////////////////////// |
| // SPDX-FileCopyrightText: Syntacore LLC © 2016-2021 |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // SPDX-License-Identifier: Apache-2.0 |
| // SPDX-FileContributor: Syntacore LLC |
| // ////////////////////////////////////////////////////////////////////////// |
| /// @file <scr1_dm.sv> |
| /// @brief Debug Module (DM) |
| /// |
| |
| //------------------------------------------------------------------------------ |
| // |
| // Functionality: |
| // - Allows debugger to perform a system reset (ndm_rst) |
| // - Allows debugger to control the HART's state |
| // - Provides debugger with information about the current HART's state |
| // - Provides debugger with Abstract Command interface that allows to: |
| // - Access MPRF registers |
| // - Access CSR registers |
| // - Access memory with the same view and permission as the hart has |
| // - Provides debugger with Abstract Command status information (busy flag and error code) |
| // - Provides debugger with Program Buffer functionality that allows to execute |
| // small programs on a halted HART |
| // |
| // Structure: |
| // - DM <-> DMI interface |
| // - DM registers: |
| // - DMCONTROL |
| // - DMSTATUS |
| // - Abstract Command Control logic |
| // - Abstract Command FSM |
| // - Abstract Command Status logic |
| // - Abstract Instruction logic |
| // - Abstract registers: |
| // - COMMAND |
| // - ABSTRACTAUTO |
| // - PROGBUF0..5 |
| // - DATA0..1 |
| // - DHI FSM |
| // - HART command registers |
| // - DHI interface |
| // |
| // |
| |
| `include "scr1_arch_description.svh" |
| |
| `ifdef SCR1_DBG_EN |
| `include "scr1_csr.svh" |
| `include "scr1_dm.svh" |
| |
| module scr1_dm ( |
| // System |
| input logic rst_n, // DM reset |
| input logic clk, // DM clock |
| |
| // DM internal interface |
| input logic dmi2dm_req_i, // DMI request |
| input logic dmi2dm_wr_i, // DMI write |
| input logic [SCR1_DBG_DMI_ADDR_WIDTH-1:0] dmi2dm_addr_i, // DMI address |
| input logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dmi2dm_wdata_i, // DMI write data |
| output logic dm2dmi_resp_o, // DMI response |
| output logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dm2dmi_rdata_o, // DMI read data |
| |
| // DM <-> Pipeline: HART Run Control i/f |
| output logic ndm_rst_n_o, // Non-DM Reset output |
| output logic hart_rst_n_o, // HART reset output |
| output logic dm2pipe_active_o, // Debug Module active flag |
| output logic dm2pipe_cmd_req_o, // Request to pipe |
| output type_scr1_hdu_dbgstates_e dm2pipe_cmd_o, // Command to pipe |
| input logic pipe2dm_cmd_resp_i, // Response to Debug Module |
| input logic pipe2dm_cmd_rcode_i, // HART Command return code: 0 - Ok; 1 - Error |
| input logic pipe2dm_hart_event_i, // HART event flag |
| input type_scr1_hdu_hartstatus_s pipe2dm_hart_status_i, // HART Status |
| |
| input logic [`SCR1_XLEN-1:0] soc2dm_fuse_mhartid_i, // RO MHARTID value |
| input logic [`SCR1_XLEN-1:0] pipe2dm_pc_sample_i, // RO PC value for sampling |
| |
| // HART Abstract Command / Program Buffer i/f |
| input logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pipe2dm_pbuf_addr_i, // Program Buffer address |
| output logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm2pipe_pbuf_instr_o, // Program Buffer instruction |
| |
| // HART Abstract Data regs i/f |
| input logic pipe2dm_dreg_req_i, // Abstract Data Register request |
| input logic pipe2dm_dreg_wr_i, // Abstract Data Register write |
| input logic [`SCR1_XLEN-1:0] pipe2dm_dreg_wdata_i, // Abstract Data Register write data |
| output logic dm2pipe_dreg_resp_o, // Abstract Data Register response |
| output logic dm2pipe_dreg_fail_o, // Abstract Data Register fail - possibly not needed ? |
| output logic [`SCR1_XLEN-1:0] dm2pipe_dreg_rdata_o // Abstract Data Register read data |
| ); |
| |
| //------------------------------------------------------------------------------ |
| // Local types declaration |
| //------------------------------------------------------------------------------ |
| |
| typedef enum logic [3:0] { |
| ABS_STATE_IDLE, |
| ABS_STATE_ERR, |
| ABS_STATE_EXEC, |
| ABS_STATE_XREG_RW, |
| ABS_STATE_MEM_SAVE_XREG, |
| ABS_STATE_MEM_SAVE_XREG_FORADDR, |
| ABS_STATE_MEM_RW, |
| ABS_STATE_MEM_RETURN_XREG, |
| ABS_STATE_MEM_RETURN_XREG_FORADDR, |
| ABS_STATE_CSR_RO, |
| ABS_STATE_CSR_SAVE_XREG, |
| ABS_STATE_CSR_RW, |
| ABS_STATE_CSR_RETURN_XREG |
| } type_scr1_abs_fsm_e; |
| |
| typedef enum logic [2:0] { |
| DHI_STATE_IDLE, |
| DHI_STATE_EXEC, |
| DHI_STATE_EXEC_RUN, |
| DHI_STATE_EXEC_HALT, |
| DHI_STATE_HALT_REQ, |
| DHI_STATE_RESUME_REQ, |
| DHI_STATE_RESUME_RUN |
| } type_scr1_dhi_fsm_e; |
| |
| //typedef enum logic [SCR1_DBG_ABSTRACTCS_CMDERR_WDTH:0] { |
| parameter ABS_ERR_NONE = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d0); |
| parameter ABS_ERR_BUSY = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d1); |
| parameter ABS_ERR_CMD = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d2); |
| parameter ABS_ERR_EXCEPTION = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d3); |
| parameter ABS_ERR_NOHALT = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d4); |
| //} type_scr1_abs_err_e; |
| |
| |
| //------------------------------------------------------------------------------ |
| // Local parameters declaration |
| //------------------------------------------------------------------------------ |
| |
| // Abstract instruction opcode parameters |
| localparam SCR1_OP_SYSTEM = 7'b111_0011; |
| localparam SCR1_OP_LOAD = 7'b000_0011; |
| localparam SCR1_OP_STORE = 7'b010_0011; |
| |
| // Abstract instruction funct3 parameters |
| localparam SCR1_FUNCT3_CSRRW = 3'b001; |
| localparam SCR1_FUNCT3_CSRRS = 3'b010; |
| localparam SCR1_FUNCT3_SB = 3'b000; |
| localparam SCR1_FUNCT3_SH = 3'b001; |
| localparam SCR1_FUNCT3_SW = 3'b010; |
| localparam SCR1_FUNCT3_LW = 3'b010; |
| localparam SCR1_FUNCT3_LBU = 3'b100; |
| localparam SCR1_FUNCT3_LHU = 3'b101; |
| |
| // DMCONTROL parameters |
| //------------------------------------------------------------------------------ |
| localparam DMCONTROL_HARTRESET = 1'd0; |
| localparam DMCONTROL_RESERVEDB = 1'd0; |
| localparam DMCONTROL_HASEL = 1'd0; |
| localparam DMCONTROL_HARTSELLO = 1'd0; |
| localparam DMCONTROL_HARTSELHI = 1'd0; |
| localparam DMCONTROL_RESERVEDA = 1'd0; |
| |
| // DMSTATUS parameters |
| //------------------------------------------------------------------------------ |
| localparam DMSTATUS_RESERVEDC = 1'd0; |
| localparam DMSTATUS_IMPEBREAK = 1'd1; |
| localparam DMSTATUS_RESERVEDB = 1'd0; |
| localparam DMSTATUS_ALLUNAVAIL = 1'd0; |
| localparam DMSTATUS_ANYUNAVAIL = 1'd0; |
| localparam DMSTATUS_ALLANYUNAVAIL = 1'd0; |
| localparam DMSTATUS_ALLANYNONEXIST = 1'b0; |
| localparam DMSTATUS_AUTHENTICATED = 1'd1; |
| localparam DMSTATUS_AUTHBUSY = 1'd0; |
| localparam DMSTATUS_RESERVEDA = 1'd0; |
| localparam DMSTATUS_DEVTREEVALID = 1'd0; |
| localparam DMSTATUS_VERSION = 2'd2; |
| |
| // HARTINFO parameters |
| //------------------------------------------------------------------------------ |
| localparam HARTINFO_RESERVEDB = 1'd0; |
| localparam HARTINFO_NSCRATCH = 4'd1; |
| localparam HARTINFO_RESERVEDA = 1'd0; |
| localparam HARTINFO_DATAACCESS = 1'd0; |
| localparam HARTINFO_DATASIZE = 4'd1; |
| localparam HARTINFO_DATAADDR = 12'h7b2; |
| |
| // ABSTRACTCS parameters |
| //------------------------------------------------------------------------------ |
| localparam ABSTRACTCS_RESERVEDD = 1'd0; |
| localparam ABSTRACTCS_PROGBUFSIZE = 5'd6; |
| localparam ABSTRACTCS_RESERVEDC = 1'd0; |
| localparam ABSTRACTCS_RESERVEDB = 1'd0; |
| localparam ABSTRACTCS_RESERVEDA = 1'd0; |
| localparam ABSTRACTCS_DATACOUNT = 4'd2; |
| |
| localparam ABS_CMD_HARTREG = 1'd0; |
| localparam ABS_CMD_HARTMEM = 2'd2; |
| localparam ABS_CMD_HARTREG_CSR = 4'b0000; |
| localparam ABS_CMD_HARTREG_INTFPU = 4'b0001; |
| localparam ABS_CMD_HARTREG_INT = 7'b000_0000; |
| localparam ABS_CMD_HARTREG_FPU = 7'b000_0001; |
| localparam ABS_EXEC_EBREAK = 32'b000000000001_00000_000_00000_1110011; |
| |
| //------------------------------------------------------------------------------ |
| // Local signals declaration |
| //------------------------------------------------------------------------------ |
| |
| // DM <-> DMI interface internal signals |
| //------------------------------------------------------------------------------ |
| |
| // Register selection signals |
| logic dmi_req_dmcontrol; |
| logic dmi_req_abstractcs; |
| logic dmi_req_abstractauto; |
| logic dmi_req_command; |
| logic dmi_rpt_command; |
| logic dmi_req_data0; |
| logic dmi_req_data1; |
| logic dmi_req_progbuf0; |
| logic dmi_req_progbuf1; |
| logic dmi_req_progbuf2; |
| logic dmi_req_progbuf3; |
| logic dmi_req_progbuf4; |
| logic dmi_req_progbuf5; |
| |
| logic dmi_req_any; |
| |
| // Registers write request signals |
| logic dmcontrol_wr_req; |
| logic abstractcs_wr_req; |
| logic data0_wr_req; |
| logic data1_wr_req; |
| logic dreg_wr_req; |
| logic command_wr_req; |
| logic autoexec_wr_req; |
| logic progbuf0_wr_req; |
| logic progbuf1_wr_req; |
| logic progbuf2_wr_req; |
| logic progbuf3_wr_req; |
| logic progbuf4_wr_req; |
| logic progbuf5_wr_req; |
| |
| // DM registers |
| //------------------------------------------------------------------------------ |
| |
| // DM clock enable signals |
| logic clk_en_dm; |
| logic clk_en_dm_ff; |
| |
| // DMCONTROL register signals |
| logic dmcontrol_haltreq_ff; |
| logic dmcontrol_haltreq_next; |
| logic dmcontrol_resumereq_ff; |
| logic dmcontrol_resumereq_next; |
| logic dmcontrol_ackhavereset_ff; |
| logic dmcontrol_ackhavereset_next; |
| logic dmcontrol_ndmreset_ff; |
| logic dmcontrol_ndmreset_next; |
| logic dmcontrol_dmactive_ff; |
| logic dmcontrol_dmactive_next; |
| |
| // Auxilary Skip Reset On Powerup register |
| logic havereset_skip_pwrup_ff; |
| logic havereset_skip_pwrup_next; |
| |
| // DMSTATUS register signals |
| logic dmstatus_allany_havereset_ff; |
| logic dmstatus_allany_havereset_next; |
| logic dmstatus_allany_resumeack_ff; |
| logic dmstatus_allany_resumeack_next; |
| logic dmstatus_allany_halted_ff; |
| logic dmstatus_allany_halted_next; |
| |
| // Abstract command control logic signals |
| //------------------------------------------------------------------------------ |
| |
| logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] abs_cmd; |
| |
| logic abs_cmd_csr_ro; |
| logic [SCR1_DBG_COMMAND_TYPE_WDTH:0] abs_cmd_type; |
| logic abs_cmd_regacs; |
| logic [SCR1_DBG_COMMAND_ACCESSREG_REGNO_HI-12:0] abs_cmd_regtype; |
| logic [6:0] abs_cmd_regfile; |
| logic abs_cmd_regwr; |
| logic [SCR1_DBG_COMMAND_ACCESSREG_SIZE_WDTH:0] abs_cmd_regsize; |
| logic abs_cmd_execprogbuf; |
| logic abs_cmd_regvalid; |
| logic [2:0] abs_cmd_memsize; |
| logic abs_cmd_memwr; |
| logic abs_cmd_memvalid; |
| |
| logic abs_cmd_regsize_vd; |
| logic abs_cmd_memsize_vd; |
| |
| logic abs_cmd_wr_ff; |
| logic abs_cmd_wr_next; |
| logic abs_cmd_postexec_ff; |
| logic abs_cmd_postexec_next; |
| logic [11:0] abs_cmd_regno; |
| logic [11:0] abs_cmd_regno_ff; |
| logic [1:0] abs_cmd_size_ff; |
| logic [1:0] abs_cmd_size_next; |
| |
| logic abs_reg_access_csr; |
| logic abs_reg_access_mprf; |
| |
| logic abs_cmd_hartreg_vd; |
| logic abs_cmd_hartmem_vd; |
| |
| logic abs_cmd_reg_access_req; |
| logic abs_cmd_csr_access_req; |
| logic abs_cmd_mprf_access_req; |
| logic abs_cmd_execprogbuf_req; |
| |
| logic abs_cmd_csr_ro_access_vd; |
| logic abs_cmd_csr_rw_access_vd; |
| logic abs_cmd_mprf_access_vd; |
| logic abs_cmd_mem_access_vd; |
| |
| // Abstract FSM signals |
| //------------------------------------------------------------------------------ |
| |
| type_scr1_abs_fsm_e abs_fsm_ff; |
| type_scr1_abs_fsm_e abs_fsm_next; |
| logic abs_fsm_idle; |
| logic abs_fsm_exec; |
| logic abs_fsm_csr_ro; |
| logic abs_fsm_err; |
| logic abs_fsm_use_addr; |
| |
| // Abstract registers |
| //------------------------------------------------------------------------------ |
| |
| logic clk_en_abs; |
| |
| // ABSTRACTCS register signals |
| logic abstractcs_busy; |
| logic abstractcs_ro_en; |
| |
| // COMMAND register signals |
| logic [`SCR1_XLEN-1:0] abs_command_ff; |
| logic [`SCR1_XLEN-1:0] abs_command_next; |
| |
| // ABSTRACTAUTO register signals |
| logic abs_autoexec_ff; |
| logic abs_autoexec_next; |
| |
| // Program buffer registers |
| logic [`SCR1_XLEN-1:0] abs_progbuf0_ff; |
| logic [`SCR1_XLEN-1:0] abs_progbuf1_ff; |
| logic [`SCR1_XLEN-1:0] abs_progbuf2_ff; |
| logic [`SCR1_XLEN-1:0] abs_progbuf3_ff; |
| logic [`SCR1_XLEN-1:0] abs_progbuf4_ff; |
| logic [`SCR1_XLEN-1:0] abs_progbuf5_ff; |
| |
| // Data 0/1 registers |
| logic data0_xreg_save; |
| logic [`SCR1_XLEN-1:0] abs_data0_ff; |
| logic [`SCR1_XLEN-1:0] abs_data0_next; |
| logic [`SCR1_XLEN-1:0] abs_data1_ff; |
| logic [`SCR1_XLEN-1:0] abs_data1_next; |
| |
| // Abstract command status logic signals |
| //------------------------------------------------------------------------------ |
| |
| // Abstract error exception flag register |
| logic abs_err_exc_upd; |
| logic abs_err_exc_ff; |
| logic abs_err_exc_next; |
| |
| logic abs_err_acc_busy_upd; |
| logic abs_err_acc_busy_ff; |
| logic abs_err_acc_busy_next; |
| |
| logic [SCR1_DBG_ABSTRACTCS_CMDERR_WDTH:0] abstractcs_cmderr_ff; |
| logic [SCR1_DBG_ABSTRACTCS_CMDERR_WDTH:0] abstractcs_cmderr_next; |
| |
| // Abstract instruction signals |
| //------------------------------------------------------------------------------ |
| |
| // Abstract instruction execution request register |
| logic abs_exec_req_next; |
| logic abs_exec_req_ff; |
| |
| // Abstract instruction register |
| logic [4:0] abs_instr_rd; |
| logic [4:0] abs_instr_rs1; |
| logic [4:0] abs_instr_rs2; |
| logic [2:0] abs_instr_mem_funct3; |
| logic [`SCR1_XLEN-1:0] abs_exec_instr_next; |
| logic [`SCR1_XLEN-1:0] abs_exec_instr_ff; |
| |
| // DHI FSM signals |
| //------------------------------------------------------------------------------ |
| |
| type_scr1_dhi_fsm_e dhi_fsm_next; |
| type_scr1_dhi_fsm_e dhi_fsm_ff; |
| type_scr1_dhi_fsm_e dhi_req; |
| |
| logic dhi_fsm_idle; |
| logic dhi_fsm_exec; |
| logic dhi_fsm_exec_halt; |
| logic dhi_fsm_halt_req; |
| logic dhi_fsm_resume_req; |
| |
| // DHI interface signals |
| //------------------------------------------------------------------------------ |
| |
| logic cmd_resp_ok; |
| logic hart_rst_unexp; |
| logic halt_req_vd; |
| logic resume_req_vd; |
| |
| logic dhi_resp; |
| logic dhi_resp_exc; |
| |
| logic hart_pbuf_ebreak_ff; |
| logic hart_pbuf_ebreak_next; |
| |
| // HART command registers |
| //------------------------------------------------------------------------------ |
| |
| logic hart_cmd_req_ff; |
| logic hart_cmd_req_next; |
| |
| type_scr1_hdu_dbgstates_e hart_cmd_ff; |
| type_scr1_hdu_dbgstates_e hart_cmd_next; |
| |
| // HART state signals |
| //------------------------------------------------------------------------------ |
| |
| logic hart_state_reset; |
| logic hart_state_run; |
| logic hart_state_drun; |
| logic hart_state_dhalt; |
| |
| //------------------------------------------------------------------------------ |
| // DM <-> DMI interface |
| //------------------------------------------------------------------------------ |
| |
| // Register selection logic |
| //------------------------------------------------------------------------------ |
| |
| always_comb begin |
| dmi_req_dmcontrol = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_DMCONTROL); |
| dmi_req_abstractcs = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_ABSTRACTCS); |
| dmi_req_abstractauto = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_ABSTRACTAUTO); |
| dmi_req_data0 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_DATA0); |
| dmi_req_data1 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_DATA1); |
| dmi_req_command = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_COMMAND); |
| dmi_rpt_command = (abs_autoexec_ff & dmi_req_data0); |
| dmi_req_progbuf0 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF0); |
| dmi_req_progbuf1 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF1); |
| dmi_req_progbuf2 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF2); |
| dmi_req_progbuf3 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF3); |
| dmi_req_progbuf4 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF4); |
| dmi_req_progbuf5 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF5); |
| end |
| |
| assign dmi_req_any = dmi_req_command | dmi_rpt_command | dmi_req_abstractauto |
| | dmi_req_data0 | dmi_req_data1 | dmi_req_progbuf0 |
| | dmi_req_progbuf1 | dmi_req_progbuf2 | dmi_req_progbuf3 |
| | dmi_req_progbuf4 | dmi_req_progbuf5; |
| |
| |
| // Read data multiplexer |
| //------------------------------------------------------------------------------ |
| |
| always_comb begin |
| dm2dmi_rdata_o = '0; |
| |
| case (dmi2dm_addr_i) |
| SCR1_DBG_DMSTATUS: begin |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_RESERVEDC_HI: |
| SCR1_DBG_DMSTATUS_RESERVEDC_LO] = DMSTATUS_RESERVEDC; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_IMPEBREAK] = DMSTATUS_IMPEBREAK; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_RESERVEDB_HI: |
| SCR1_DBG_DMSTATUS_RESERVEDB_LO] = DMSTATUS_RESERVEDB; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLHAVERESET] = dmstatus_allany_havereset_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYHAVERESET] = dmstatus_allany_havereset_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLRESUMEACK] = dmstatus_allany_resumeack_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYRESUMEACK] = dmstatus_allany_resumeack_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLNONEXISTENT] = DMSTATUS_ALLANYNONEXIST; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYNONEXISTENT] = DMSTATUS_ALLANYNONEXIST; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLUNAVAIL] = DMSTATUS_ALLANYUNAVAIL; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYUNAVAIL] = DMSTATUS_ALLANYUNAVAIL; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLRUNNING] = ~dmstatus_allany_halted_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYRUNNING] = ~dmstatus_allany_halted_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLHALTED] = dmstatus_allany_halted_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYHALTED] = dmstatus_allany_halted_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_AUTHENTICATED] = DMSTATUS_AUTHENTICATED; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_AUTHBUSY] = DMSTATUS_AUTHBUSY; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_RESERVEDA] = DMSTATUS_RESERVEDA; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_DEVTREEVALID] = DMSTATUS_DEVTREEVALID; |
| dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_VERSION_HI: |
| SCR1_DBG_DMSTATUS_VERSION_LO] = DMSTATUS_VERSION;; |
| end |
| |
| SCR1_DBG_DMCONTROL: begin |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HALTREQ] = dmcontrol_haltreq_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_RESUMEREQ] = dmcontrol_resumereq_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HARTRESET] = DMCONTROL_HARTRESET; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_ACKHAVERESET] = dmcontrol_ackhavereset_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_RESERVEDB] = DMCONTROL_RESERVEDB; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HASEL] = DMCONTROL_HASEL; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HARTSELLO_HI: |
| SCR1_DBG_DMCONTROL_HARTSELLO_LO] = DMCONTROL_HARTSELLO; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HARTSELHI_HI: |
| SCR1_DBG_DMCONTROL_HARTSELHI_LO] = DMCONTROL_HARTSELHI; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_RESERVEDA_HI: |
| SCR1_DBG_DMCONTROL_RESERVEDA_LO] = DMCONTROL_RESERVEDA; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_NDMRESET] = dmcontrol_ndmreset_ff; |
| dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_DMACTIVE] = dmcontrol_dmactive_ff; |
| end |
| |
| SCR1_DBG_ABSTRACTCS: begin |
| dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_RESERVEDD_HI: |
| SCR1_DBG_ABSTRACTCS_RESERVEDD_LO] = ABSTRACTCS_RESERVEDD; |
| dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_PROGBUFSIZE_HI: |
| SCR1_DBG_ABSTRACTCS_PROGBUFSIZE_LO] = ABSTRACTCS_PROGBUFSIZE; |
| dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_RESERVEDC_HI: |
| SCR1_DBG_ABSTRACTCS_RESERVEDC_LO] = ABSTRACTCS_RESERVEDC; |
| dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_BUSY] = abstractcs_busy; |
| dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_RESERVEDB] = ABSTRACTCS_RESERVEDB; |
| dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_CMDERR_HI: |
| SCR1_DBG_ABSTRACTCS_CMDERR_LO] = abstractcs_cmderr_ff; |
| dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_RESERVEDA_HI: |
| SCR1_DBG_ABSTRACTCS_RESERVEDA_LO] = ABSTRACTCS_RESERVEDA; |
| dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_DATACOUNT_HI: |
| SCR1_DBG_ABSTRACTCS_DATACOUNT_LO] = ABSTRACTCS_DATACOUNT; |
| end |
| |
| SCR1_DBG_HARTINFO: begin |
| dm2dmi_rdata_o[SCR1_DBG_HARTINFO_RESERVEDB_HI: |
| SCR1_DBG_HARTINFO_RESERVEDB_LO] = HARTINFO_RESERVEDB; |
| dm2dmi_rdata_o[SCR1_DBG_HARTINFO_NSCRATCH_HI: |
| SCR1_DBG_HARTINFO_NSCRATCH_LO] = HARTINFO_NSCRATCH; |
| dm2dmi_rdata_o[SCR1_DBG_HARTINFO_RESERVEDA_HI: |
| SCR1_DBG_HARTINFO_RESERVEDA_LO] = HARTINFO_RESERVEDA; |
| dm2dmi_rdata_o[SCR1_DBG_HARTINFO_DATAACCESS] = HARTINFO_DATAACCESS; |
| dm2dmi_rdata_o[SCR1_DBG_HARTINFO_DATASIZE_HI: |
| SCR1_DBG_HARTINFO_DATASIZE_LO] = HARTINFO_DATASIZE; |
| dm2dmi_rdata_o[SCR1_DBG_HARTINFO_DATAADDR_HI: |
| SCR1_DBG_HARTINFO_DATAADDR_LO] = HARTINFO_DATAADDR; |
| end |
| |
| SCR1_DBG_ABSTRACTAUTO: dm2dmi_rdata_o[0] = abs_autoexec_ff; |
| SCR1_DBG_DATA0 : dm2dmi_rdata_o = abs_data0_ff; |
| SCR1_DBG_DATA1 : dm2dmi_rdata_o = abs_data1_ff; |
| SCR1_DBG_PROGBUF0 : dm2dmi_rdata_o = abs_progbuf0_ff; |
| SCR1_DBG_PROGBUF1 : dm2dmi_rdata_o = abs_progbuf1_ff; |
| SCR1_DBG_PROGBUF2 : dm2dmi_rdata_o = abs_progbuf2_ff; |
| SCR1_DBG_PROGBUF3 : dm2dmi_rdata_o = abs_progbuf3_ff; |
| SCR1_DBG_PROGBUF4 : dm2dmi_rdata_o = abs_progbuf4_ff; |
| SCR1_DBG_PROGBUF5 : dm2dmi_rdata_o = abs_progbuf5_ff; |
| SCR1_DBG_HALTSUM0 : dm2dmi_rdata_o[0] = dmstatus_allany_halted_ff; |
| |
| default: begin |
| dm2dmi_rdata_o = '0; |
| end |
| endcase |
| end |
| |
| // Response |
| assign dm2dmi_resp_o = 1'b1; |
| |
| // Write requests signals |
| //------------------------------------------------------------------------------ |
| |
| assign dmcontrol_wr_req = dmi_req_dmcontrol & dmi2dm_wr_i; |
| assign data0_wr_req = dmi_req_data0 & dmi2dm_wr_i; |
| assign data1_wr_req = dmi_req_data1 & dmi2dm_wr_i; |
| assign dreg_wr_req = pipe2dm_dreg_req_i & pipe2dm_dreg_wr_i; |
| assign command_wr_req = dmi_req_command & dmi2dm_wr_i; |
| assign autoexec_wr_req = dmi_req_abstractauto & dmi2dm_wr_i; |
| assign progbuf0_wr_req = dmi_req_progbuf0 & dmi2dm_wr_i; |
| assign progbuf1_wr_req = dmi_req_progbuf1 & dmi2dm_wr_i; |
| assign progbuf2_wr_req = dmi_req_progbuf2 & dmi2dm_wr_i; |
| assign progbuf3_wr_req = dmi_req_progbuf3 & dmi2dm_wr_i; |
| assign progbuf4_wr_req = dmi_req_progbuf4 & dmi2dm_wr_i; |
| assign progbuf5_wr_req = dmi_req_progbuf5 & dmi2dm_wr_i; |
| assign abstractcs_wr_req = dmi_req_abstractcs & dmi2dm_wr_i; |
| |
| // HART state signals |
| //------------------------------------------------------------------------------ |
| |
| assign hart_state_reset = (pipe2dm_hart_status_i.dbg_state == SCR1_HDU_DBGSTATE_RESET); |
| assign hart_state_run = (pipe2dm_hart_status_i.dbg_state == SCR1_HDU_DBGSTATE_RUN); |
| assign hart_state_dhalt = (pipe2dm_hart_status_i.dbg_state == SCR1_HDU_DBGSTATE_DHALTED); |
| assign hart_state_drun = (pipe2dm_hart_status_i.dbg_state == SCR1_HDU_DBGSTATE_DRUN); |
| |
| //------------------------------------------------------------------------------ |
| // DM registers |
| //------------------------------------------------------------------------------ |
| // |
| // Registers: |
| // - DM clock enable register |
| // - Auxilary Skip Reset On Powerup register |
| // - DMCONTROL register |
| // - DMSTATUS register |
| |
| // DM clock enable logic |
| //------------------------------------------------------------------------------ |
| |
| assign clk_en_dm = dmcontrol_wr_req | dmcontrol_dmactive_ff | clk_en_dm_ff; |
| |
| always_ff @(posedge clk, negedge rst_n) begin |
| if (~rst_n) begin |
| clk_en_dm_ff <= 1'b0; |
| end else if (clk_en_dm) begin |
| clk_en_dm_ff <= dmcontrol_dmactive_ff; |
| end |
| end |
| |
| assign dm2pipe_active_o = clk_en_dm_ff; |
| |
| // DMCONTROL register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk, negedge rst_n) begin |
| if (~rst_n) begin |
| dmcontrol_dmactive_ff <= 1'b0; |
| dmcontrol_ndmreset_ff <= 1'b0; |
| dmcontrol_ackhavereset_ff <= 1'b0; |
| dmcontrol_haltreq_ff <= 1'b0; |
| dmcontrol_resumereq_ff <= 1'b0; |
| end else if (clk_en_dm) begin |
| dmcontrol_dmactive_ff <= dmcontrol_dmactive_next; |
| dmcontrol_ndmreset_ff <= dmcontrol_ndmreset_next; |
| dmcontrol_ackhavereset_ff <= dmcontrol_ackhavereset_next; |
| dmcontrol_haltreq_ff <= dmcontrol_haltreq_next; |
| dmcontrol_resumereq_ff <= dmcontrol_resumereq_next; |
| end |
| end |
| |
| assign dmcontrol_dmactive_next = dmcontrol_wr_req |
| ? dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_DMACTIVE] |
| : dmcontrol_dmactive_ff; |
| |
| always_comb begin |
| dmcontrol_ndmreset_next = dmcontrol_ndmreset_ff; |
| dmcontrol_ackhavereset_next = dmcontrol_ackhavereset_ff; |
| dmcontrol_haltreq_next = dmcontrol_haltreq_ff; |
| dmcontrol_resumereq_next = dmcontrol_resumereq_ff; |
| if (~dmcontrol_dmactive_ff) begin |
| dmcontrol_ndmreset_next = 1'b0; |
| dmcontrol_ackhavereset_next = 1'b0; |
| dmcontrol_haltreq_next = 1'b0; |
| dmcontrol_resumereq_next = 1'b0; |
| end else if (dmcontrol_wr_req) begin |
| dmcontrol_ndmreset_next = dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_NDMRESET]; |
| dmcontrol_ackhavereset_next = dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_ACKHAVERESET]; |
| dmcontrol_haltreq_next = dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_HALTREQ]; |
| dmcontrol_resumereq_next = dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_RESUMEREQ]; |
| end |
| end |
| |
| // Reset signal for system controlled by Debug Module |
| assign hart_rst_n_o = ~dmcontrol_ndmreset_ff; |
| assign ndm_rst_n_o = ~dmcontrol_ndmreset_ff; |
| |
| // Skip reset on powerup register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk, negedge rst_n) begin |
| if (~rst_n) begin |
| havereset_skip_pwrup_ff <= 1'b1; |
| end else if (clk_en_dm) begin |
| havereset_skip_pwrup_ff <= havereset_skip_pwrup_next; |
| end |
| end |
| |
| assign havereset_skip_pwrup_next = ~dmcontrol_dmactive_ff ? 1'b1 |
| : havereset_skip_pwrup_ff ? hart_state_reset & ndm_rst_n_o & hart_rst_n_o |
| : havereset_skip_pwrup_ff; |
| |
| // DMSTATUS register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk, negedge rst_n) begin |
| if (~rst_n) begin |
| dmstatus_allany_havereset_ff <= 1'b0; |
| dmstatus_allany_resumeack_ff <= 1'b0; |
| dmstatus_allany_halted_ff <= 1'b0; |
| end else if (clk_en_dm) begin |
| dmstatus_allany_havereset_ff <= dmstatus_allany_havereset_next; |
| dmstatus_allany_resumeack_ff <= dmstatus_allany_resumeack_next; |
| dmstatus_allany_halted_ff <= dmstatus_allany_halted_next; |
| end |
| end |
| |
| assign dmstatus_allany_havereset_next = ~dmcontrol_dmactive_ff ? 1'b0 |
| : ~havereset_skip_pwrup_ff & hart_state_reset ? 1'b1 |
| : dmcontrol_ackhavereset_ff ? 1'b0 |
| : dmstatus_allany_havereset_ff; |
| assign dmstatus_allany_resumeack_next = ~dmcontrol_dmactive_ff ? 1'b0 |
| : ~dmcontrol_resumereq_ff ? 1'b0 |
| : hart_state_run ? 1'b1 |
| : dmstatus_allany_resumeack_ff; |
| |
| assign dmstatus_allany_halted_next = ~dmcontrol_dmactive_ff ? 1'b0 |
| : hart_state_dhalt ? 1'b1 |
| : hart_state_run ? 1'b0 |
| : dmstatus_allany_halted_ff; |
| |
| //------------------------------------------------------------------------------ |
| // Abstract Command control logic |
| //------------------------------------------------------------------------------ |
| // |
| // Consists of the following functional units: |
| // - Abstract command decoder |
| // - Abstract command access valid flags |
| // - Abstract command control registers |
| |
| assign clk_en_abs = clk_en_dm & dmcontrol_dmactive_ff; |
| |
| // Abstract command decoder |
| //------------------------------------------------------------------------------ |
| |
| assign abs_cmd = dmi_req_command ? dmi2dm_wdata_i : abs_command_ff; |
| |
| always_comb begin |
| abs_cmd_regno = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_REGNO_LO +: 12]; |
| |
| abs_cmd_csr_ro = (abs_cmd_regno == SCR1_CSR_ADDR_MISA) |
| | (abs_cmd_regno == SCR1_CSR_ADDR_MVENDORID) |
| | (abs_cmd_regno == SCR1_CSR_ADDR_MARCHID) |
| | (abs_cmd_regno == SCR1_CSR_ADDR_MIMPID) |
| | (abs_cmd_regno == SCR1_CSR_ADDR_MHARTID) |
| | (abs_cmd_regno == SCR1_HDU_DBGCSR_ADDR_DPC); |
| |
| abs_cmd_type = abs_cmd[SCR1_DBG_COMMAND_TYPE_HI:SCR1_DBG_COMMAND_TYPE_LO]; |
| abs_cmd_regacs = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_TRANSFER]; |
| abs_cmd_regtype = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_REGNO_HI:12]; |
| abs_cmd_regfile = abs_cmd[11:5]; |
| abs_cmd_regsize = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_SIZE_HI: |
| SCR1_DBG_COMMAND_ACCESSREG_SIZE_LO]; |
| abs_cmd_regwr = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_WRITE]; |
| abs_cmd_execprogbuf = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_POSTEXEC]; |
| |
| abs_cmd_regvalid = ~(|{abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_RESERVEDB], |
| abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_RESERVEDA]}); |
| |
| abs_cmd_memsize = abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_AAMSIZE_HI: |
| SCR1_DBG_COMMAND_ACCESSMEM_AAMSIZE_LO]; |
| abs_cmd_memwr = abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_WRITE]; |
| |
| abs_cmd_memvalid = ~(|{abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_AAMVIRTUAL], |
| abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_AAMPOSTINC], |
| abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDB_HI: |
| SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDB_HI], |
| abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDA_HI: |
| SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDA_HI]}); |
| end |
| |
| assign abs_reg_access_csr = (abs_cmd_regtype == ABS_CMD_HARTREG_CSR); |
| assign abs_reg_access_mprf = (abs_cmd_regtype == ABS_CMD_HARTREG_INTFPU) |
| & (abs_cmd_regfile == ABS_CMD_HARTREG_INT); |
| |
| // Abstract command access request and valid flags |
| //------------------------------------------------------------------------------ |
| |
| assign abs_cmd_regsize_vd = (abs_cmd_regsize == 3'h2); |
| assign abs_cmd_memsize_vd = (abs_cmd_memsize < 3'h3); |
| |
| assign abs_cmd_hartreg_vd = (abs_cmd_type == ABS_CMD_HARTREG) & abs_cmd_regvalid; |
| assign abs_cmd_hartmem_vd = (abs_cmd_type == ABS_CMD_HARTMEM) & abs_cmd_memvalid; |
| |
| // Abstract command requests |
| assign abs_cmd_reg_access_req = abs_cmd_hartreg_vd & abs_cmd_regacs; |
| assign abs_cmd_csr_access_req = abs_cmd_reg_access_req & abs_reg_access_csr; |
| assign abs_cmd_mprf_access_req = abs_cmd_reg_access_req & abs_reg_access_mprf; |
| assign abs_cmd_execprogbuf_req = abs_cmd_hartreg_vd & abs_cmd_execprogbuf; |
| |
| // Abstract command access valid flags |
| assign abs_cmd_csr_ro_access_vd = abs_cmd_csr_access_req & abs_cmd_regsize_vd & ~abs_cmd_regwr |
| & ~abs_cmd_execprogbuf & abs_cmd_csr_ro & hart_state_run; |
| assign abs_cmd_csr_rw_access_vd = abs_cmd_csr_access_req & abs_cmd_regsize_vd |
| & (abs_cmd_regwr | ~abs_cmd_csr_ro_access_vd); |
| assign abs_cmd_mprf_access_vd = abs_cmd_mprf_access_req & abs_cmd_regsize_vd; |
| assign abs_cmd_mem_access_vd = abs_cmd_hartmem_vd & abs_cmd_memsize_vd; |
| |
| // Abstract command control registers |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_abs & abs_fsm_idle) begin |
| abs_cmd_postexec_ff <= abs_cmd_postexec_next; |
| abs_cmd_wr_ff <= abs_cmd_wr_next; |
| abs_cmd_regno_ff <= abs_cmd_regno; |
| abs_cmd_size_ff <= abs_cmd_size_next; |
| end |
| end |
| |
| always_comb begin |
| abs_cmd_wr_next = 1'b0; |
| abs_cmd_postexec_next = 1'b0; |
| abs_cmd_size_next = abs_cmd_size_ff; |
| if ((command_wr_req | dmi_rpt_command) & hart_state_dhalt & abs_fsm_idle) begin |
| if (abs_cmd_csr_rw_access_vd) begin |
| abs_cmd_wr_next = abs_cmd_regwr; |
| abs_cmd_postexec_next = abs_cmd_execprogbuf; |
| end else if (abs_cmd_mprf_access_vd) begin |
| abs_cmd_wr_next = abs_cmd_regwr; |
| abs_cmd_size_next = abs_cmd_regsize[1:0]; |
| abs_cmd_postexec_next = abs_cmd_execprogbuf; |
| end else if (abs_cmd_mem_access_vd) begin |
| abs_cmd_wr_next = abs_cmd_memwr; |
| abs_cmd_size_next = abs_cmd_memsize[1:0]; |
| end |
| end |
| end |
| |
| //------------------------------------------------------------------------------ |
| // Abstract command FSM |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_dm) begin |
| if (~dmcontrol_dmactive_ff) begin |
| abs_fsm_ff <= ABS_STATE_IDLE; |
| end else begin |
| abs_fsm_ff <= abs_fsm_next; |
| end |
| end |
| end |
| |
| always_comb begin |
| abs_fsm_next = abs_fsm_ff; |
| |
| case (abs_fsm_ff) |
| ABS_STATE_IDLE: begin |
| if (command_wr_req | dmi_rpt_command) begin |
| case (1'b1) |
| abs_cmd_csr_ro_access_vd: abs_fsm_next = ABS_STATE_CSR_RO; |
| abs_cmd_csr_rw_access_vd: abs_fsm_next = hart_state_dhalt ? ABS_STATE_CSR_SAVE_XREG : ABS_STATE_ERR; |
| abs_cmd_mprf_access_vd : abs_fsm_next = hart_state_dhalt ? ABS_STATE_XREG_RW : ABS_STATE_ERR; |
| abs_cmd_execprogbuf_req : abs_fsm_next = ABS_STATE_EXEC; |
| abs_cmd_mem_access_vd : abs_fsm_next = hart_state_dhalt ? ABS_STATE_MEM_SAVE_XREG : ABS_STATE_ERR; |
| default : abs_fsm_next = ABS_STATE_ERR; |
| endcase |
| end |
| end |
| |
| ABS_STATE_EXEC: begin |
| if (dhi_resp) begin |
| if (dhi_resp_exc | abs_err_acc_busy_ff) begin |
| abs_fsm_next = ABS_STATE_ERR; |
| end else begin |
| abs_fsm_next = ABS_STATE_IDLE; |
| end |
| end |
| end |
| |
| ABS_STATE_XREG_RW: begin |
| if (dhi_resp) begin |
| case (1'b1) |
| abs_err_acc_busy_ff: abs_fsm_next = ABS_STATE_ERR; |
| abs_cmd_postexec_ff: abs_fsm_next = ABS_STATE_EXEC; |
| default : abs_fsm_next = ABS_STATE_IDLE; |
| endcase |
| end |
| end |
| |
| ABS_STATE_CSR_RO : abs_fsm_next = abs_err_acc_busy_ff ? ABS_STATE_ERR : ABS_STATE_IDLE; |
| ABS_STATE_CSR_SAVE_XREG: abs_fsm_next = dhi_resp ? ABS_STATE_CSR_RW : ABS_STATE_CSR_SAVE_XREG; |
| ABS_STATE_CSR_RW : abs_fsm_next = dhi_resp ? ABS_STATE_CSR_RETURN_XREG : ABS_STATE_CSR_RW; |
| |
| ABS_STATE_CSR_RETURN_XREG: begin |
| if (dhi_resp) begin |
| case (1'b1) |
| abs_err_exc_ff : abs_fsm_next = ABS_STATE_ERR; |
| abs_err_acc_busy_ff : abs_fsm_next = ABS_STATE_ERR; |
| abs_cmd_postexec_ff : abs_fsm_next = ABS_STATE_EXEC; |
| default : abs_fsm_next = ABS_STATE_IDLE; |
| endcase |
| end |
| end |
| |
| ABS_STATE_MEM_SAVE_XREG : abs_fsm_next = dhi_resp ? ABS_STATE_MEM_SAVE_XREG_FORADDR : ABS_STATE_MEM_SAVE_XREG; |
| ABS_STATE_MEM_SAVE_XREG_FORADDR : abs_fsm_next = dhi_resp ? ABS_STATE_MEM_RW : ABS_STATE_MEM_SAVE_XREG_FORADDR; |
| ABS_STATE_MEM_RW : abs_fsm_next = dhi_resp ? ABS_STATE_MEM_RETURN_XREG : ABS_STATE_MEM_RW; |
| ABS_STATE_MEM_RETURN_XREG : abs_fsm_next = dhi_resp ? ABS_STATE_MEM_RETURN_XREG_FORADDR : ABS_STATE_MEM_RETURN_XREG; |
| |
| ABS_STATE_MEM_RETURN_XREG_FORADDR: begin |
| if (dhi_resp) begin |
| case (1'b1) |
| abs_err_exc_ff: abs_fsm_next = ABS_STATE_ERR; |
| abs_err_acc_busy_ff : abs_fsm_next = ABS_STATE_ERR; |
| abs_cmd_postexec_ff : abs_fsm_next = ABS_STATE_EXEC; |
| default : abs_fsm_next = ABS_STATE_IDLE; |
| endcase |
| end |
| end |
| |
| ABS_STATE_ERR: begin |
| if (abstractcs_wr_req & (abstractcs_cmderr_next == 3'b0)) begin |
| abs_fsm_next = ABS_STATE_IDLE; |
| end |
| end |
| endcase |
| |
| if (~abs_fsm_idle & hart_state_reset) begin |
| abs_fsm_next = ABS_STATE_ERR; |
| end |
| end |
| |
| assign abs_fsm_idle = (abs_fsm_ff == ABS_STATE_IDLE); |
| assign abs_fsm_exec = (abs_fsm_ff == ABS_STATE_EXEC); |
| assign abs_fsm_csr_ro = (abs_fsm_ff == ABS_STATE_CSR_RO); |
| assign abs_fsm_err = (abs_fsm_ff == ABS_STATE_ERR); |
| assign abs_fsm_use_addr = (abs_fsm_ff == ABS_STATE_MEM_SAVE_XREG_FORADDR) |
| | (abs_fsm_ff == ABS_STATE_MEM_RETURN_XREG_FORADDR); |
| |
| //------------------------------------------------------------------------------ |
| // Abstract command status logic |
| //------------------------------------------------------------------------------ |
| |
| // Abstract command access busy error register |
| //------------------------------------------------------------------------------ |
| |
| assign abs_err_acc_busy_upd = clk_en_abs & (abs_fsm_idle | dmi_req_any); |
| |
| always_ff @(posedge clk) begin |
| if (abs_err_acc_busy_upd) abs_err_acc_busy_ff <= abs_err_acc_busy_next; |
| end |
| |
| assign abs_err_acc_busy_next = ~abs_fsm_idle & dmi_req_any; |
| |
| // Abstract command access exception error register |
| //------------------------------------------------------------------------------ |
| |
| assign abs_err_exc_upd = clk_en_abs & (abs_fsm_idle | (dhi_resp & dhi_resp_exc)); |
| |
| always_ff @(posedge clk) begin |
| if (abs_err_exc_upd) abs_err_exc_ff <= abs_err_exc_next; |
| end |
| |
| assign abs_err_exc_next = ~abs_fsm_idle & dhi_resp & dhi_resp_exc; |
| |
| //------------------------------------------------------------------------------ |
| // Abstract Instruction logic |
| //------------------------------------------------------------------------------ |
| // |
| // Cosists of the following functional units: |
| // - Instruction execution request register |
| // - Instruction memory FUNCT3 field multiplexer |
| // - Instruction RS1 multiplexer |
| // - Instruction RD multiplexer |
| // - Abstract Instruction register |
| |
| // Abstract instruction execution request register |
| //------------------------------------------------------------------------------ |
| |
| assign abs_exec_req_next = ~(abs_fsm_idle | abs_fsm_csr_ro | abs_fsm_err) & ~dhi_resp; |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_dm) begin |
| if (~dmcontrol_dmactive_ff) begin |
| abs_exec_req_ff <= 1'b0; |
| end else begin |
| abs_exec_req_ff <= abs_exec_req_next; |
| end |
| end |
| end |
| |
| // Abstract instruction memory FUNCT3 field multiplexer |
| //------------------------------------------------------------------------------ |
| |
| always_comb begin |
| case (abs_cmd_size_ff) |
| 2'b00 : abs_instr_mem_funct3 = abs_cmd_wr_ff ? SCR1_FUNCT3_SB : SCR1_FUNCT3_LBU; |
| 2'b01 : abs_instr_mem_funct3 = abs_cmd_wr_ff ? SCR1_FUNCT3_SH : SCR1_FUNCT3_LHU; |
| 2'b10 : abs_instr_mem_funct3 = abs_cmd_wr_ff ? SCR1_FUNCT3_SW : SCR1_FUNCT3_LW; |
| default: abs_instr_mem_funct3 = SCR1_FUNCT3_SB; |
| endcase |
| end |
| |
| // Abstract instruction RS1 multiplexer |
| //------------------------------------------------------------------------------ |
| |
| always_comb begin |
| abs_instr_rs1 = 5'h0; |
| case (abs_fsm_ff) |
| ABS_STATE_XREG_RW : abs_instr_rs1 = abs_cmd_wr_ff ? 5'h0 : abs_cmd_regno_ff[4:0]; |
| ABS_STATE_CSR_SAVE_XREG : abs_instr_rs1 = 5'h5; |
| ABS_STATE_MEM_SAVE_XREG : abs_instr_rs1 = 5'h5; |
| ABS_STATE_CSR_RETURN_XREG : abs_instr_rs1 = 5'h5; |
| ABS_STATE_MEM_RETURN_XREG : abs_instr_rs1 = 5'h5; |
| ABS_STATE_CSR_RW : abs_instr_rs1 = abs_cmd_wr_ff ? 5'h5 : 5'h0; |
| ABS_STATE_MEM_SAVE_XREG_FORADDR : abs_instr_rs1 = 5'h6; |
| ABS_STATE_MEM_RETURN_XREG_FORADDR: abs_instr_rs1 = 5'h6; |
| ABS_STATE_MEM_RW : abs_instr_rs1 = 5'h6; |
| default : begin end |
| endcase |
| end |
| |
| assign abs_instr_rs2 = 5'h5; |
| |
| // Abstract instruction RD multiplexer |
| //------------------------------------------------------------------------------ |
| |
| always_comb begin |
| abs_instr_rd = 5'h0; |
| case (abs_fsm_ff) |
| ABS_STATE_XREG_RW : abs_instr_rd = abs_cmd_wr_ff ? abs_cmd_regno_ff[4:0] : 5'h0; |
| ABS_STATE_CSR_SAVE_XREG : abs_instr_rd = abs_cmd_wr_ff ? 5'h5 : 5'h0; |
| ABS_STATE_MEM_SAVE_XREG : abs_instr_rd = abs_cmd_wr_ff ? 5'h5 : 5'h0; |
| ABS_STATE_CSR_RW : abs_instr_rd = abs_cmd_wr_ff ? 5'h0 : 5'h5; |
| ABS_STATE_MEM_RW : abs_instr_rd = abs_cmd_wr_ff ? 5'h0 : 5'h5; |
| ABS_STATE_CSR_RETURN_XREG : abs_instr_rd = 5'h5; |
| ABS_STATE_MEM_RETURN_XREG : abs_instr_rd = 5'h5; |
| ABS_STATE_MEM_SAVE_XREG_FORADDR : abs_instr_rd = 5'h6; |
| ABS_STATE_MEM_RETURN_XREG_FORADDR: abs_instr_rd = 5'h6; |
| default : begin end |
| endcase |
| end |
| |
| // Abstract instruction register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_abs) begin |
| abs_exec_instr_ff <= abs_exec_instr_next; |
| end |
| end |
| |
| always_comb begin |
| abs_exec_instr_next = abs_exec_instr_ff; |
| case (abs_fsm_ff) |
| ABS_STATE_XREG_RW, |
| ABS_STATE_CSR_SAVE_XREG, |
| ABS_STATE_CSR_RETURN_XREG, |
| ABS_STATE_MEM_SAVE_XREG, |
| ABS_STATE_MEM_SAVE_XREG_FORADDR, |
| ABS_STATE_MEM_RETURN_XREG, |
| ABS_STATE_MEM_RETURN_XREG_FORADDR: begin |
| abs_exec_instr_next = {SCR1_HDU_DBGCSR_ADDR_DSCRATCH0, abs_instr_rs1, SCR1_FUNCT3_CSRRW, abs_instr_rd, SCR1_OP_SYSTEM}; |
| end |
| |
| ABS_STATE_CSR_RW: begin |
| abs_exec_instr_next = abs_cmd_wr_ff |
| ? {abs_cmd_regno_ff[11:0], abs_instr_rs1, SCR1_FUNCT3_CSRRW, abs_instr_rd, SCR1_OP_SYSTEM} |
| : {abs_cmd_regno_ff[11:0], abs_instr_rs1, SCR1_FUNCT3_CSRRS, abs_instr_rd, SCR1_OP_SYSTEM}; |
| end |
| |
| ABS_STATE_MEM_RW: begin |
| abs_exec_instr_next = abs_cmd_wr_ff |
| ? {7'h0, abs_instr_rs2, abs_instr_rs1, abs_instr_mem_funct3, 5'h0, SCR1_OP_STORE} |
| : {12'h0, abs_instr_rs1, abs_instr_mem_funct3, abs_instr_rd, SCR1_OP_LOAD}; |
| end |
| |
| default: begin end |
| endcase |
| end |
| |
| //------------------------------------------------------------------------------ |
| // Abstract registers |
| //------------------------------------------------------------------------------ |
| // |
| // Registers: |
| // - ABSTRACTCS register |
| // - COMMAND register |
| // - ABSTRACTAUTO register |
| // - PROGBUF0..5 registers |
| // - DATA0..1 registers |
| |
| // ABSTRACTCS register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_dm) begin |
| if (~dmcontrol_dmactive_ff) begin |
| abstractcs_cmderr_ff <= ABS_ERR_NONE; |
| end else begin |
| abstractcs_cmderr_ff <= abstractcs_cmderr_next; |
| end |
| end |
| end |
| |
| always_comb begin |
| abstractcs_cmderr_next = abstractcs_cmderr_ff; |
| |
| case (abs_fsm_ff) |
| ABS_STATE_IDLE: begin |
| if (command_wr_req | dmi_rpt_command) begin |
| if (abs_cmd_hartreg_vd) begin |
| case (1'b1) |
| abs_cmd_reg_access_req : begin |
| case (1'b1) |
| abs_cmd_csr_rw_access_vd: abstractcs_cmderr_next = hart_state_dhalt |
| ? abstractcs_cmderr_ff |
| : ABS_ERR_NOHALT; |
| abs_cmd_mprf_access_vd : abstractcs_cmderr_next = hart_state_dhalt |
| ? abstractcs_cmderr_ff |
| : ABS_ERR_NOHALT; |
| abs_cmd_csr_ro_access_vd: abstractcs_cmderr_next = abstractcs_cmderr_ff; |
| default : abstractcs_cmderr_next = ABS_ERR_CMD; |
| endcase |
| end |
| abs_cmd_execprogbuf_req : abstractcs_cmderr_next = abstractcs_cmderr_ff; |
| default : abstractcs_cmderr_next = ABS_ERR_CMD; |
| endcase |
| end else if (abs_cmd_hartmem_vd) begin |
| abstractcs_cmderr_next = ~abs_cmd_memsize_vd ? ABS_ERR_CMD |
| : ~hart_state_dhalt ? ABS_ERR_NOHALT |
| : abstractcs_cmderr_ff; |
| end else begin |
| abstractcs_cmderr_next = ABS_ERR_CMD; |
| end |
| end |
| end |
| |
| ABS_STATE_EXEC: begin |
| if (dhi_resp) begin |
| if (dhi_resp_exc) begin |
| abstractcs_cmderr_next = ABS_ERR_EXCEPTION; |
| end else if (abs_err_acc_busy_ff) begin |
| abstractcs_cmderr_next = ABS_ERR_BUSY; |
| end |
| end |
| end |
| |
| ABS_STATE_XREG_RW, |
| ABS_STATE_CSR_RO: begin |
| if (abs_err_acc_busy_ff) begin |
| abstractcs_cmderr_next = ABS_ERR_BUSY; |
| end |
| end |
| |
| ABS_STATE_CSR_RETURN_XREG, |
| ABS_STATE_MEM_RETURN_XREG_FORADDR: begin |
| if (dhi_resp) begin |
| case (1'b1) |
| abs_err_exc_ff : abstractcs_cmderr_next = ABS_ERR_EXCEPTION; |
| abs_err_acc_busy_ff: abstractcs_cmderr_next = ABS_ERR_BUSY; |
| default: abstractcs_cmderr_next = abstractcs_cmderr_ff; |
| endcase |
| end |
| end |
| |
| ABS_STATE_ERR: begin |
| if (dmi_req_abstractcs & dmi2dm_wr_i) begin |
| abstractcs_cmderr_next = abstractcs_cmderr_ff // cp.7 |
| & (~dmi2dm_wdata_i[SCR1_DBG_ABSTRACTCS_CMDERR_HI: |
| SCR1_DBG_ABSTRACTCS_CMDERR_LO]); |
| end |
| end |
| |
| default: begin |
| end |
| endcase |
| |
| if (~abs_fsm_idle & hart_state_reset) begin |
| abstractcs_cmderr_next = ABS_ERR_EXCEPTION; |
| end |
| end |
| |
| assign abstractcs_busy = ~abs_fsm_idle & ~abs_fsm_err; |
| |
| // Abstract COMMAND register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_dm) abs_command_ff <= abs_command_next; |
| end |
| |
| assign abs_command_next = ~dmcontrol_dmactive_ff ? '0 |
| : (command_wr_req & abs_fsm_idle) ? dmi2dm_wdata_i |
| : abs_command_ff; |
| |
| // Abstract ABSTRACTAUTO register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_dm) abs_autoexec_ff <= abs_autoexec_next; |
| end |
| |
| assign abs_autoexec_next = ~dmcontrol_dmactive_ff ? 1'b0 |
| : (autoexec_wr_req & abs_fsm_idle) ? dmi2dm_wdata_i[0] |
| : abs_autoexec_ff; |
| |
| // Program Buffer registers |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_abs & abs_fsm_idle) begin |
| if (progbuf0_wr_req) abs_progbuf0_ff <= dmi2dm_wdata_i; |
| if (progbuf1_wr_req) abs_progbuf1_ff <= dmi2dm_wdata_i; |
| if (progbuf2_wr_req) abs_progbuf2_ff <= dmi2dm_wdata_i; |
| if (progbuf3_wr_req) abs_progbuf3_ff <= dmi2dm_wdata_i; |
| if (progbuf4_wr_req) abs_progbuf4_ff <= dmi2dm_wdata_i; |
| if (progbuf5_wr_req) abs_progbuf5_ff <= dmi2dm_wdata_i; |
| end |
| end |
| |
| // Data 0 register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_abs) begin |
| abs_data0_ff <= abs_data0_next; |
| end |
| end |
| |
| assign data0_xreg_save = dreg_wr_req & ~abs_cmd_wr_ff; |
| |
| always_comb begin |
| abs_data0_next = abs_data0_ff; |
| |
| case (abs_fsm_ff) |
| ABS_STATE_IDLE : abs_data0_next = data0_wr_req ? dmi2dm_wdata_i : abs_data0_ff; |
| ABS_STATE_EXEC : abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff; |
| ABS_STATE_CSR_SAVE_XREG : abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff; |
| ABS_STATE_CSR_RETURN_XREG: abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff; |
| ABS_STATE_MEM_SAVE_XREG : abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff; |
| ABS_STATE_MEM_RETURN_XREG: abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff; |
| ABS_STATE_XREG_RW : abs_data0_next = data0_xreg_save ? pipe2dm_dreg_wdata_i : abs_data0_ff; |
| |
| ABS_STATE_CSR_RO: begin |
| case (abs_cmd_regno_ff[11:0]) |
| SCR1_CSR_ADDR_MISA : abs_data0_next = SCR1_CSR_MISA; |
| SCR1_CSR_ADDR_MVENDORID: abs_data0_next = SCR1_CSR_MVENDORID; |
| SCR1_CSR_ADDR_MARCHID : abs_data0_next = SCR1_CSR_MARCHID; |
| SCR1_CSR_ADDR_MIMPID : abs_data0_next = SCR1_CSR_MIMPID; |
| SCR1_CSR_ADDR_MHARTID : abs_data0_next = soc2dm_fuse_mhartid_i; |
| default : abs_data0_next = pipe2dm_pc_sample_i; |
| endcase |
| end |
| |
| default : begin end |
| endcase |
| end |
| |
| // Data 1 register |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_abs) begin |
| abs_data1_ff <= abs_data1_next; |
| end |
| end |
| |
| always_comb begin |
| abs_data1_next = abs_data1_ff; |
| case (abs_fsm_ff) |
| ABS_STATE_IDLE : abs_data1_next = data1_wr_req ? dmi2dm_wdata_i : abs_data1_ff; |
| ABS_STATE_MEM_SAVE_XREG_FORADDR : abs_data1_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data1_ff; |
| ABS_STATE_MEM_RETURN_XREG_FORADDR: abs_data1_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data1_ff; |
| default : begin end |
| endcase |
| end |
| |
| //------------------------------------------------------------------------------ |
| // Debug Hart Interface : control |
| //------------------------------------------------------------------------------ |
| |
| assign cmd_resp_ok = pipe2dm_cmd_resp_i & ~pipe2dm_cmd_rcode_i; |
| assign hart_rst_unexp = ~dhi_fsm_idle & ~dhi_fsm_halt_req & hart_state_reset; |
| |
| assign halt_req_vd = dmcontrol_haltreq_ff & ~hart_state_dhalt; |
| assign resume_req_vd = dmcontrol_resumereq_ff & ~dmstatus_allany_resumeack_ff |
| & hart_state_dhalt; |
| |
| // DHI fsm |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk, negedge rst_n) begin |
| if (~rst_n) begin |
| dhi_fsm_ff <= DHI_STATE_IDLE; |
| end else if (clk_en_dm) begin |
| dhi_fsm_ff <= dhi_fsm_next; |
| end |
| end |
| |
| always_comb begin |
| dhi_fsm_next = dhi_fsm_ff; |
| if (~hart_rst_unexp & dmcontrol_dmactive_ff) begin |
| // Normal work |
| case (dhi_fsm_ff) |
| DHI_STATE_IDLE : dhi_fsm_next = dhi_req; |
| DHI_STATE_EXEC : dhi_fsm_next = cmd_resp_ok ? DHI_STATE_EXEC_RUN : DHI_STATE_EXEC; |
| DHI_STATE_EXEC_RUN : dhi_fsm_next = hart_state_drun ? DHI_STATE_EXEC_HALT : DHI_STATE_EXEC_RUN; |
| DHI_STATE_HALT_REQ : dhi_fsm_next = cmd_resp_ok ? DHI_STATE_EXEC_HALT : DHI_STATE_HALT_REQ; |
| DHI_STATE_EXEC_HALT : dhi_fsm_next = hart_state_dhalt ? DHI_STATE_IDLE : DHI_STATE_EXEC_HALT; |
| DHI_STATE_RESUME_REQ: dhi_fsm_next = cmd_resp_ok ? DHI_STATE_RESUME_RUN : DHI_STATE_RESUME_REQ; |
| DHI_STATE_RESUME_RUN: dhi_fsm_next = hart_state_run ? DHI_STATE_IDLE : DHI_STATE_RESUME_RUN; |
| default : dhi_fsm_next = dhi_fsm_ff; |
| endcase |
| end else begin |
| // In case of DM reset or core unexpected reset |
| dhi_fsm_next = DHI_STATE_IDLE; |
| end |
| end |
| |
| assign dhi_fsm_idle = (dhi_fsm_ff == DHI_STATE_IDLE); |
| assign dhi_fsm_halt_req = (dhi_fsm_ff == DHI_STATE_HALT_REQ); |
| assign dhi_fsm_exec = (dhi_fsm_ff == DHI_STATE_EXEC); |
| assign dhi_fsm_exec_halt = (dhi_fsm_ff == DHI_STATE_EXEC_HALT); |
| assign dhi_fsm_resume_req = (dhi_fsm_ff == DHI_STATE_RESUME_REQ); |
| |
| always_comb begin |
| case (1'b1) |
| abs_exec_req_ff: dhi_req = DHI_STATE_EXEC; |
| halt_req_vd : dhi_req = DHI_STATE_HALT_REQ; |
| resume_req_vd : dhi_req = DHI_STATE_RESUME_REQ; |
| default : dhi_req = DHI_STATE_IDLE; |
| endcase |
| end |
| |
| assign dhi_resp = dhi_fsm_exec_halt & hart_state_dhalt; |
| assign dhi_resp_exc = pipe2dm_hart_event_i & pipe2dm_hart_status_i.except |
| & ~pipe2dm_hart_status_i.ebreak; |
| |
| // HART command registers |
| //------------------------------------------------------------------------------ |
| |
| // HART command request register |
| always_ff @(posedge clk, negedge rst_n) begin |
| if (~rst_n) begin |
| hart_cmd_req_ff <= 1'b0; |
| end else if (clk_en_dm) begin |
| hart_cmd_req_ff <= hart_cmd_req_next; |
| end |
| end |
| |
| assign hart_cmd_req_next = (dhi_fsm_exec | dhi_fsm_halt_req | dhi_fsm_resume_req) |
| & ~cmd_resp_ok & dmcontrol_dmactive_ff; |
| |
| // HART command register |
| always_ff @(posedge clk, negedge rst_n) begin |
| if (~rst_n) begin |
| hart_cmd_ff <= SCR1_HDU_DBGSTATE_RUN; |
| end else if (clk_en_dm) begin |
| hart_cmd_ff <= hart_cmd_next; |
| end |
| end |
| |
| always_comb begin |
| hart_cmd_next = SCR1_HDU_DBGSTATE_RUN; |
| if (dmcontrol_dmactive_ff) begin |
| case (dhi_fsm_ff) |
| DHI_STATE_EXEC : hart_cmd_next = SCR1_HDU_DBGSTATE_DRUN; |
| DHI_STATE_HALT_REQ : hart_cmd_next = SCR1_HDU_DBGSTATE_DHALTED; |
| DHI_STATE_RESUME_REQ: hart_cmd_next = SCR1_HDU_DBGSTATE_RUN; |
| default : hart_cmd_next = dm2pipe_cmd_o; |
| endcase |
| end |
| end |
| |
| assign dm2pipe_cmd_req_o = hart_cmd_req_ff; |
| assign dm2pipe_cmd_o = hart_cmd_ff; |
| |
| //------------------------------------------------------------------------------ |
| // Debug Hart Interface : program buffer |
| //------------------------------------------------------------------------------ |
| |
| // Program Buffer execution EBREAK flag |
| //------------------------------------------------------------------------------ |
| |
| always_ff @(posedge clk) begin |
| if (clk_en_dm) hart_pbuf_ebreak_ff <= hart_pbuf_ebreak_next; |
| end |
| |
| assign hart_pbuf_ebreak_next = abs_fsm_exec & (dm2pipe_pbuf_instr_o == ABS_EXEC_EBREAK); |
| |
| // Program Buffer instruction multiplexer |
| //------------------------------------------------------------------------------ |
| |
| always_comb begin |
| dm2pipe_pbuf_instr_o = ABS_EXEC_EBREAK; |
| |
| if (abs_fsm_exec & ~hart_pbuf_ebreak_ff) begin |
| case (pipe2dm_pbuf_addr_i) |
| 3'h0: dm2pipe_pbuf_instr_o = abs_progbuf0_ff; |
| 3'h1: dm2pipe_pbuf_instr_o = abs_progbuf1_ff; |
| 3'h2: dm2pipe_pbuf_instr_o = abs_progbuf2_ff; |
| 3'h3: dm2pipe_pbuf_instr_o = abs_progbuf3_ff; |
| 3'h4: dm2pipe_pbuf_instr_o = abs_progbuf4_ff; |
| 3'h5: dm2pipe_pbuf_instr_o = abs_progbuf5_ff; |
| default: ; |
| endcase |
| end else if (pipe2dm_pbuf_addr_i == 3'b0) begin |
| dm2pipe_pbuf_instr_o = abs_exec_instr_ff; |
| end |
| end |
| |
| //------------------------------------------------------------------------------ |
| // Debug Hart Interface : abstract command data |
| //------------------------------------------------------------------------------ |
| |
| assign dm2pipe_dreg_resp_o = 1'b1; |
| assign dm2pipe_dreg_fail_o = 1'b0; |
| assign dm2pipe_dreg_rdata_o = abs_fsm_use_addr ? abs_data1_ff : abs_data0_ff; |
| |
| `ifdef SCR1_TRGT_SIMULATION |
| //------------------------------------------------------------------------------ |
| // Assertions |
| //------------------------------------------------------------------------------ |
| |
| SVA_DM_X_CONTROL : assert property ( |
| @(negedge clk) disable iff (~rst_n) |
| !$isunknown({dmi2dm_req_i, pipe2dm_dreg_req_i, pipe2dm_cmd_resp_i, |
| pipe2dm_hart_event_i}) |
| ) else $error("DM error: control signals is X - %0b", {dmi2dm_req_i, |
| pipe2dm_dreg_req_i, pipe2dm_cmd_resp_i, pipe2dm_hart_event_i}); |
| |
| SVA_DM_X_DMI : assert property ( |
| @(negedge clk) disable iff (~rst_n) |
| dmi2dm_req_i |-> !$isunknown({dmi2dm_wr_i, dmi2dm_addr_i, dmi2dm_wdata_i}) |
| ) else $error("DM error: data signals is X on dmi"); |
| |
| SVA_DM_X_HART_PBUF : assert property ( |
| @(negedge clk) disable iff (~rst_n) |
| !$isunknown (pipe2dm_pbuf_addr_i) |
| ) else $error("DM error: data signals is X on hart_pbuf"); |
| |
| SVA_DM_X_HART_DREG : assert property ( |
| @(negedge clk) disable iff (~rst_n) |
| pipe2dm_dreg_req_i |-> !$isunknown({pipe2dm_dreg_wr_i, pipe2dm_dreg_wdata_i}) |
| ) else $error("DM error: data signals is X on hart_dreg"); |
| |
| SVA_DM_X_HART_CMD : assert property ( |
| @(negedge clk) disable iff (~rst_n) |
| pipe2dm_cmd_resp_i |-> !$isunknown({pipe2dm_cmd_rcode_i}) |
| ) else $error("DM error: data signals is X on dm2pipe_cmd_o"); |
| |
| SVA_DM_X_HART_EVENT : assert property ( |
| @(negedge clk) disable iff (~rst_n) |
| pipe2dm_hart_event_i |-> !$isunknown(pipe2dm_hart_status_i) |
| ) else $error("DM error: data signals is X on pipe2dm_hart_event_i"); |
| |
| `endif // SCR1_TRGT_SIMULATION |
| |
| endmodule : scr1_dm |
| |
| `endif // SCR1_DBG_EN |