lm32_debug.v

Mon, 05 Apr 2010 20:23:04 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 05 Apr 2010 20:23:04 +0100
changeset 4
99b7b037ce82
parent 0
cd0b58aa6f83
child 26
73de224304c1
permissions
-rw-r--r--

add better comment re Xilinx Xst cache issues

philpem@0 1 // =============================================================================
philpem@0 2 // COPYRIGHT NOTICE
philpem@0 3 // Copyright 2006 (c) Lattice Semiconductor Corporation
philpem@0 4 // ALL RIGHTS RESERVED
philpem@0 5 // This confidential and proprietary software may be used only as authorised by
philpem@0 6 // a licensing agreement from Lattice Semiconductor Corporation.
philpem@0 7 // The entire notice above must be reproduced on all authorized copies and
philpem@0 8 // copies may only be made to the extent permitted by a licensing agreement from
philpem@0 9 // Lattice Semiconductor Corporation.
philpem@0 10 //
philpem@0 11 // Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
philpem@0 12 // 5555 NE Moore Court 408-826-6000 (other locations)
philpem@0 13 // Hillsboro, OR 97124 web : http://www.latticesemi.com/
philpem@0 14 // U.S.A email: techsupport@latticesemi.com
philpem@0 15 // =============================================================================/
philpem@0 16 // FILE DETAILS
philpem@0 17 // Project : LatticeMico32
philpem@0 18 // File : lm32_debug.v
philpem@0 19 // Title : Hardware debug registers and associated logic.
philpem@0 20 // Dependencies : lm32_include.v
philpem@0 21 // Version : 6.1.17
philpem@0 22 // : Initial Release
philpem@0 23 // Version : 7.0SP2, 3.0
philpem@0 24 // : No Change
philpem@0 25 // Version : 3.1
philpem@0 26 // : No Change
philpem@0 27 // Version : 3.2
philpem@0 28 // : Fixed simulation bug which flares up when number of
philpem@0 29 // : watchpoints is zero.
philpem@0 30 // =============================================================================
philpem@0 31
philpem@0 32 `include "lm32_include.v"
philpem@0 33
philpem@0 34 `ifdef CFG_DEBUG_ENABLED
philpem@0 35
philpem@0 36 // States for single-step FSM
philpem@0 37 `define LM32_DEBUG_SS_STATE_RNG 2:0
philpem@0 38 `define LM32_DEBUG_SS_STATE_IDLE 3'b000
philpem@0 39 `define LM32_DEBUG_SS_STATE_WAIT_FOR_RET 3'b001
philpem@0 40 `define LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN 3'b010
philpem@0 41 `define LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT 3'b011
philpem@0 42 `define LM32_DEBUG_SS_STATE_RESTART 3'b100
philpem@0 43
philpem@0 44 /////////////////////////////////////////////////////
philpem@0 45 // Module interface
philpem@0 46 /////////////////////////////////////////////////////
philpem@0 47
philpem@0 48 module lm32_debug (
philpem@0 49 // ----- Inputs -------
philpem@0 50 clk_i,
philpem@0 51 rst_i,
philpem@0 52 pc_x,
philpem@0 53 load_x,
philpem@0 54 store_x,
philpem@0 55 load_store_address_x,
philpem@0 56 csr_write_enable_x,
philpem@0 57 csr_write_data,
philpem@0 58 csr_x,
philpem@0 59 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 60 jtag_csr_write_enable,
philpem@0 61 jtag_csr_write_data,
philpem@0 62 jtag_csr,
philpem@0 63 `endif
philpem@0 64 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 65 eret_q_x,
philpem@0 66 bret_q_x,
philpem@0 67 stall_x,
philpem@0 68 exception_x,
philpem@0 69 q_x,
philpem@0 70 `ifdef CFG_DCACHE_ENABLED
philpem@0 71 dcache_refill_request,
philpem@0 72 `endif
philpem@0 73 `endif
philpem@0 74 // ----- Outputs -------
philpem@0 75 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 76 dc_ss,
philpem@0 77 `endif
philpem@0 78 dc_re,
philpem@0 79 bp_match,
philpem@0 80 wp_match
philpem@0 81 );
philpem@0 82
philpem@0 83 /////////////////////////////////////////////////////
philpem@0 84 // Parameters
philpem@0 85 /////////////////////////////////////////////////////
philpem@0 86
philpem@0 87 parameter breakpoints = 0; // Number of breakpoint CSRs
philpem@0 88 parameter watchpoints = 0; // Number of watchpoint CSRs
philpem@0 89
philpem@0 90 /////////////////////////////////////////////////////
philpem@0 91 // Inputs
philpem@0 92 /////////////////////////////////////////////////////
philpem@0 93
philpem@0 94 input clk_i; // Clock
philpem@0 95 input rst_i; // Reset
philpem@0 96
philpem@0 97 input [`LM32_PC_RNG] pc_x; // X stage PC
philpem@0 98 input load_x; // Load instruction in X stage
philpem@0 99 input store_x; // Store instruction in X stage
philpem@0 100 input [`LM32_WORD_RNG] load_store_address_x; // Load or store effective address
philpem@0 101 input csr_write_enable_x; // wcsr instruction in X stage
philpem@0 102 input [`LM32_WORD_RNG] csr_write_data; // Data to write to CSR
philpem@0 103 input [`LM32_CSR_RNG] csr_x; // Which CSR to write
philpem@0 104 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 105 input jtag_csr_write_enable; // JTAG interface CSR write enable
philpem@0 106 input [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to CSR
philpem@0 107 input [`LM32_CSR_RNG] jtag_csr; // Which CSR to write
philpem@0 108 `endif
philpem@0 109 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 110 input eret_q_x; // eret instruction in X stage
philpem@0 111 input bret_q_x; // bret instruction in X stage
philpem@0 112 input stall_x; // Instruction in X stage is stalled
philpem@0 113 input exception_x; // An exception has occured in X stage
philpem@0 114 input q_x; // Indicates the instruction in the X stage is qualified
philpem@0 115 `ifdef CFG_DCACHE_ENABLED
philpem@0 116 input dcache_refill_request; // Indicates data cache wants to be refilled
philpem@0 117 `endif
philpem@0 118 `endif
philpem@0 119
philpem@0 120 /////////////////////////////////////////////////////
philpem@0 121 // Outputs
philpem@0 122 /////////////////////////////////////////////////////
philpem@0 123
philpem@0 124 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 125 output dc_ss; // Single-step enable
philpem@0 126 reg dc_ss;
philpem@0 127 `endif
philpem@0 128 output dc_re; // Remap exceptions
philpem@0 129 reg dc_re;
philpem@0 130 output bp_match; // Indicates a breakpoint has matched
philpem@0 131 wire bp_match;
philpem@0 132 output wp_match; // Indicates a watchpoint has matched
philpem@0 133 wire wp_match;
philpem@0 134
philpem@0 135 /////////////////////////////////////////////////////
philpem@0 136 // Internal nets and registers
philpem@0 137 /////////////////////////////////////////////////////
philpem@0 138
philpem@0 139 genvar i; // Loop index for generate statements
philpem@0 140
philpem@0 141 // Debug CSRs
philpem@0 142
philpem@0 143 reg [`LM32_PC_RNG] bp_a[0:breakpoints-1]; // Instruction breakpoint address
philpem@0 144 reg bp_e[0:breakpoints-1]; // Instruction breakpoint enable
philpem@0 145 wire [0:breakpoints-1]bp_match_n; // Indicates if a h/w instruction breakpoint matched
philpem@0 146
philpem@0 147 reg [`LM32_WPC_C_RNG] wpc_c[0:watchpoints-1]; // Watchpoint enable
philpem@0 148 reg [`LM32_WORD_RNG] wp[0:watchpoints-1]; // Watchpoint address
philpem@0 149 wire [0:watchpoints]wp_match_n; // Indicates if a h/w data watchpoint matched
philpem@0 150
philpem@0 151 wire debug_csr_write_enable; // Debug CSR write enable (from either a wcsr instruction of external debugger)
philpem@0 152 wire [`LM32_WORD_RNG] debug_csr_write_data; // Data to write to debug CSR
philpem@0 153 wire [`LM32_CSR_RNG] debug_csr; // Debug CSR to write to
philpem@0 154
philpem@0 155 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 156 // FIXME: Declaring this as a reg causes ModelSim 6.1.15b to crash, so use integer for now
philpem@0 157 //reg [`LM32_DEBUG_SS_STATE_RNG] state; // State of single-step FSM
philpem@0 158 integer state; // State of single-step FSM
philpem@0 159 `endif
philpem@0 160
philpem@0 161 /////////////////////////////////////////////////////
philpem@0 162 // Functions
philpem@0 163 /////////////////////////////////////////////////////
philpem@0 164
philpem@0 165 `include "lm32_functions.v"
philpem@0 166
philpem@0 167 /////////////////////////////////////////////////////
philpem@0 168 // Combinational Logic
philpem@0 169 /////////////////////////////////////////////////////
philpem@0 170
philpem@0 171 // Check for breakpoints
philpem@0 172 generate
philpem@0 173 for (i = 0; i < breakpoints; i = i + 1)
philpem@0 174 begin : bp_comb
philpem@0 175 assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == `TRUE));
philpem@0 176 end
philpem@0 177 endgenerate
philpem@0 178 generate
philpem@0 179 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 180 if (breakpoints > 0)
philpem@0 181 assign bp_match = (|bp_match_n) || (state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT);
philpem@0 182 else
philpem@0 183 assign bp_match = state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT;
philpem@0 184 `else
philpem@0 185 if (breakpoints > 0)
philpem@0 186 assign bp_match = |bp_match_n;
philpem@0 187 else
philpem@0 188 assign bp_match = `FALSE;
philpem@0 189 `endif
philpem@0 190 endgenerate
philpem@0 191
philpem@0 192 // Check for watchpoints
philpem@0 193 generate
philpem@0 194 for (i = 0; i < watchpoints; i = i + 1)
philpem@0 195 begin : wp_comb
philpem@0 196 assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1]));
philpem@0 197 end
philpem@0 198 endgenerate
philpem@0 199 generate
philpem@0 200 if (watchpoints > 0)
philpem@0 201 assign wp_match = |wp_match_n;
philpem@0 202 else
philpem@0 203 assign wp_match = `FALSE;
philpem@0 204 endgenerate
philpem@0 205
philpem@0 206 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 207 // Multiplex between wcsr instruction writes and debugger writes to the debug CSRs
philpem@0 208 assign debug_csr_write_enable = (csr_write_enable_x == `TRUE) || (jtag_csr_write_enable == `TRUE);
philpem@0 209 assign debug_csr_write_data = jtag_csr_write_enable == `TRUE ? jtag_csr_write_data : csr_write_data;
philpem@0 210 assign debug_csr = jtag_csr_write_enable == `TRUE ? jtag_csr : csr_x;
philpem@0 211 `else
philpem@0 212 assign debug_csr_write_enable = csr_write_enable_x;
philpem@0 213 assign debug_csr_write_data = csr_write_data;
philpem@0 214 assign debug_csr = csr_x;
philpem@0 215 `endif
philpem@0 216
philpem@0 217 /////////////////////////////////////////////////////
philpem@0 218 // Sequential Logic
philpem@0 219 /////////////////////////////////////////////////////
philpem@0 220
philpem@0 221 // Breakpoint address and enable CSRs
philpem@0 222 generate
philpem@0 223 for (i = 0; i < breakpoints; i = i + 1)
philpem@0 224 begin : bp_seq
philpem@0 225 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 226 begin
philpem@0 227 if (rst_i == `TRUE)
philpem@0 228 begin
philpem@0 229 bp_a[i] <= {`LM32_PC_WIDTH{1'bx}};
philpem@0 230 bp_e[i] <= `FALSE;
philpem@0 231 end
philpem@0 232 else
philpem@0 233 begin
philpem@0 234 if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_BP0 + i))
philpem@0 235 begin
philpem@0 236 bp_a[i] <= debug_csr_write_data[`LM32_PC_RNG];
philpem@0 237 bp_e[i] <= debug_csr_write_data[0];
philpem@0 238 end
philpem@0 239 end
philpem@0 240 end
philpem@0 241 end
philpem@0 242 endgenerate
philpem@0 243
philpem@0 244 // Watchpoint address and control flags CSRs
philpem@0 245 generate
philpem@0 246 for (i = 0; i < watchpoints; i = i + 1)
philpem@0 247 begin : wp_seq
philpem@0 248 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 249 begin
philpem@0 250 if (rst_i == `TRUE)
philpem@0 251 begin
philpem@0 252 wp[i] <= {`LM32_WORD_WIDTH{1'bx}};
philpem@0 253 wpc_c[i] <= `LM32_WPC_C_DISABLED;
philpem@0 254 end
philpem@0 255 else
philpem@0 256 begin
philpem@0 257 if (debug_csr_write_enable == `TRUE)
philpem@0 258 begin
philpem@0 259 if (debug_csr == `LM32_CSR_DC)
philpem@0 260 wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2];
philpem@0 261 if (debug_csr == `LM32_CSR_WP0 + i)
philpem@0 262 wp[i] <= debug_csr_write_data;
philpem@0 263 end
philpem@0 264 end
philpem@0 265 end
philpem@0 266 end
philpem@0 267 endgenerate
philpem@0 268
philpem@0 269 // Remap exceptions control bit
philpem@0 270 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 271 begin
philpem@0 272 if (rst_i == `TRUE)
philpem@0 273 dc_re <= `FALSE;
philpem@0 274 else
philpem@0 275 begin
philpem@0 276 if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC))
philpem@0 277 dc_re <= debug_csr_write_data[1];
philpem@0 278 end
philpem@0 279 end
philpem@0 280
philpem@0 281 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 282 // Single-step control flag
philpem@0 283 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 284 begin
philpem@0 285 if (rst_i == `TRUE)
philpem@0 286 begin
philpem@0 287 state <= `LM32_DEBUG_SS_STATE_IDLE;
philpem@0 288 dc_ss <= `FALSE;
philpem@0 289 end
philpem@0 290 else
philpem@0 291 begin
philpem@0 292 if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC))
philpem@0 293 begin
philpem@0 294 dc_ss <= debug_csr_write_data[0];
philpem@0 295 if (debug_csr_write_data[0] == `FALSE)
philpem@0 296 state <= `LM32_DEBUG_SS_STATE_IDLE;
philpem@0 297 else
philpem@0 298 state <= `LM32_DEBUG_SS_STATE_WAIT_FOR_RET;
philpem@0 299 end
philpem@0 300 case (state)
philpem@0 301 `LM32_DEBUG_SS_STATE_WAIT_FOR_RET:
philpem@0 302 begin
philpem@0 303 // Wait for eret or bret instruction to be executed
philpem@0 304 if ( ( (eret_q_x == `TRUE)
philpem@0 305 || (bret_q_x == `TRUE)
philpem@0 306 )
philpem@0 307 && (stall_x == `FALSE)
philpem@0 308 )
philpem@0 309 state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
philpem@0 310 end
philpem@0 311 `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN:
philpem@0 312 begin
philpem@0 313 // Wait for an instruction to be executed
philpem@0 314 if ((q_x == `TRUE) && (stall_x == `FALSE))
philpem@0 315 state <= `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT;
philpem@0 316 end
philpem@0 317 `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT:
philpem@0 318 begin
philpem@0 319 // Wait for exception to be raised
philpem@0 320 `ifdef CFG_DCACHE_ENABLED
philpem@0 321 if (dcache_refill_request == `TRUE)
philpem@0 322 state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
philpem@0 323 else
philpem@0 324 `endif
philpem@0 325 if ((exception_x == `TRUE) && (q_x == `TRUE) && (stall_x == `FALSE))
philpem@0 326 begin
philpem@0 327 dc_ss <= `FALSE;
philpem@0 328 state <= `LM32_DEBUG_SS_STATE_RESTART;
philpem@0 329 end
philpem@0 330 end
philpem@0 331 `LM32_DEBUG_SS_STATE_RESTART:
philpem@0 332 begin
philpem@0 333 // Watch to see if stepped instruction is restarted due to a cache miss
philpem@0 334 `ifdef CFG_DCACHE_ENABLED
philpem@0 335 if (dcache_refill_request == `TRUE)
philpem@0 336 state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
philpem@0 337 else
philpem@0 338 `endif
philpem@0 339 state <= `LM32_DEBUG_SS_STATE_IDLE;
philpem@0 340 end
philpem@0 341 endcase
philpem@0 342 end
philpem@0 343 end
philpem@0 344 `endif
philpem@0 345
philpem@0 346 endmodule
philpem@0 347
philpem@0 348 `endif