1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/lm32_debug.v Sun Apr 04 20:40:03 2010 +0100 1.3 @@ -0,0 +1,348 @@ 1.4 +// ============================================================================= 1.5 +// COPYRIGHT NOTICE 1.6 +// Copyright 2006 (c) Lattice Semiconductor Corporation 1.7 +// ALL RIGHTS RESERVED 1.8 +// This confidential and proprietary software may be used only as authorised by 1.9 +// a licensing agreement from Lattice Semiconductor Corporation. 1.10 +// The entire notice above must be reproduced on all authorized copies and 1.11 +// copies may only be made to the extent permitted by a licensing agreement from 1.12 +// Lattice Semiconductor Corporation. 1.13 +// 1.14 +// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada) 1.15 +// 5555 NE Moore Court 408-826-6000 (other locations) 1.16 +// Hillsboro, OR 97124 web : http://www.latticesemi.com/ 1.17 +// U.S.A email: techsupport@latticesemi.com 1.18 +// =============================================================================/ 1.19 +// FILE DETAILS 1.20 +// Project : LatticeMico32 1.21 +// File : lm32_debug.v 1.22 +// Title : Hardware debug registers and associated logic. 1.23 +// Dependencies : lm32_include.v 1.24 +// Version : 6.1.17 1.25 +// : Initial Release 1.26 +// Version : 7.0SP2, 3.0 1.27 +// : No Change 1.28 +// Version : 3.1 1.29 +// : No Change 1.30 +// Version : 3.2 1.31 +// : Fixed simulation bug which flares up when number of 1.32 +// : watchpoints is zero. 1.33 +// ============================================================================= 1.34 + 1.35 +`include "lm32_include.v" 1.36 + 1.37 +`ifdef CFG_DEBUG_ENABLED 1.38 + 1.39 +// States for single-step FSM 1.40 +`define LM32_DEBUG_SS_STATE_RNG 2:0 1.41 +`define LM32_DEBUG_SS_STATE_IDLE 3'b000 1.42 +`define LM32_DEBUG_SS_STATE_WAIT_FOR_RET 3'b001 1.43 +`define LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN 3'b010 1.44 +`define LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT 3'b011 1.45 +`define LM32_DEBUG_SS_STATE_RESTART 3'b100 1.46 + 1.47 +///////////////////////////////////////////////////// 1.48 +// Module interface 1.49 +///////////////////////////////////////////////////// 1.50 + 1.51 +module lm32_debug ( 1.52 + // ----- Inputs ------- 1.53 + clk_i, 1.54 + rst_i, 1.55 + pc_x, 1.56 + load_x, 1.57 + store_x, 1.58 + load_store_address_x, 1.59 + csr_write_enable_x, 1.60 + csr_write_data, 1.61 + csr_x, 1.62 +`ifdef CFG_HW_DEBUG_ENABLED 1.63 + jtag_csr_write_enable, 1.64 + jtag_csr_write_data, 1.65 + jtag_csr, 1.66 +`endif 1.67 +`ifdef LM32_SINGLE_STEP_ENABLED 1.68 + eret_q_x, 1.69 + bret_q_x, 1.70 + stall_x, 1.71 + exception_x, 1.72 + q_x, 1.73 +`ifdef CFG_DCACHE_ENABLED 1.74 + dcache_refill_request, 1.75 +`endif 1.76 +`endif 1.77 + // ----- Outputs ------- 1.78 +`ifdef LM32_SINGLE_STEP_ENABLED 1.79 + dc_ss, 1.80 +`endif 1.81 + dc_re, 1.82 + bp_match, 1.83 + wp_match 1.84 + ); 1.85 + 1.86 +///////////////////////////////////////////////////// 1.87 +// Parameters 1.88 +///////////////////////////////////////////////////// 1.89 + 1.90 +parameter breakpoints = 0; // Number of breakpoint CSRs 1.91 +parameter watchpoints = 0; // Number of watchpoint CSRs 1.92 + 1.93 +///////////////////////////////////////////////////// 1.94 +// Inputs 1.95 +///////////////////////////////////////////////////// 1.96 + 1.97 +input clk_i; // Clock 1.98 +input rst_i; // Reset 1.99 + 1.100 +input [`LM32_PC_RNG] pc_x; // X stage PC 1.101 +input load_x; // Load instruction in X stage 1.102 +input store_x; // Store instruction in X stage 1.103 +input [`LM32_WORD_RNG] load_store_address_x; // Load or store effective address 1.104 +input csr_write_enable_x; // wcsr instruction in X stage 1.105 +input [`LM32_WORD_RNG] csr_write_data; // Data to write to CSR 1.106 +input [`LM32_CSR_RNG] csr_x; // Which CSR to write 1.107 +`ifdef CFG_HW_DEBUG_ENABLED 1.108 +input jtag_csr_write_enable; // JTAG interface CSR write enable 1.109 +input [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to CSR 1.110 +input [`LM32_CSR_RNG] jtag_csr; // Which CSR to write 1.111 +`endif 1.112 +`ifdef LM32_SINGLE_STEP_ENABLED 1.113 +input eret_q_x; // eret instruction in X stage 1.114 +input bret_q_x; // bret instruction in X stage 1.115 +input stall_x; // Instruction in X stage is stalled 1.116 +input exception_x; // An exception has occured in X stage 1.117 +input q_x; // Indicates the instruction in the X stage is qualified 1.118 +`ifdef CFG_DCACHE_ENABLED 1.119 +input dcache_refill_request; // Indicates data cache wants to be refilled 1.120 +`endif 1.121 +`endif 1.122 + 1.123 +///////////////////////////////////////////////////// 1.124 +// Outputs 1.125 +///////////////////////////////////////////////////// 1.126 + 1.127 +`ifdef LM32_SINGLE_STEP_ENABLED 1.128 +output dc_ss; // Single-step enable 1.129 +reg dc_ss; 1.130 +`endif 1.131 +output dc_re; // Remap exceptions 1.132 +reg dc_re; 1.133 +output bp_match; // Indicates a breakpoint has matched 1.134 +wire bp_match; 1.135 +output wp_match; // Indicates a watchpoint has matched 1.136 +wire wp_match; 1.137 + 1.138 +///////////////////////////////////////////////////// 1.139 +// Internal nets and registers 1.140 +///////////////////////////////////////////////////// 1.141 + 1.142 +genvar i; // Loop index for generate statements 1.143 + 1.144 +// Debug CSRs 1.145 + 1.146 +reg [`LM32_PC_RNG] bp_a[0:breakpoints-1]; // Instruction breakpoint address 1.147 +reg bp_e[0:breakpoints-1]; // Instruction breakpoint enable 1.148 +wire [0:breakpoints-1]bp_match_n; // Indicates if a h/w instruction breakpoint matched 1.149 + 1.150 +reg [`LM32_WPC_C_RNG] wpc_c[0:watchpoints-1]; // Watchpoint enable 1.151 +reg [`LM32_WORD_RNG] wp[0:watchpoints-1]; // Watchpoint address 1.152 +wire [0:watchpoints]wp_match_n; // Indicates if a h/w data watchpoint matched 1.153 + 1.154 +wire debug_csr_write_enable; // Debug CSR write enable (from either a wcsr instruction of external debugger) 1.155 +wire [`LM32_WORD_RNG] debug_csr_write_data; // Data to write to debug CSR 1.156 +wire [`LM32_CSR_RNG] debug_csr; // Debug CSR to write to 1.157 + 1.158 +`ifdef LM32_SINGLE_STEP_ENABLED 1.159 +// FIXME: Declaring this as a reg causes ModelSim 6.1.15b to crash, so use integer for now 1.160 +//reg [`LM32_DEBUG_SS_STATE_RNG] state; // State of single-step FSM 1.161 +integer state; // State of single-step FSM 1.162 +`endif 1.163 + 1.164 +///////////////////////////////////////////////////// 1.165 +// Functions 1.166 +///////////////////////////////////////////////////// 1.167 + 1.168 +`include "lm32_functions.v" 1.169 + 1.170 +///////////////////////////////////////////////////// 1.171 +// Combinational Logic 1.172 +///////////////////////////////////////////////////// 1.173 + 1.174 +// Check for breakpoints 1.175 +generate 1.176 + for (i = 0; i < breakpoints; i = i + 1) 1.177 + begin : bp_comb 1.178 +assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == `TRUE)); 1.179 + end 1.180 +endgenerate 1.181 +generate 1.182 +`ifdef LM32_SINGLE_STEP_ENABLED 1.183 + if (breakpoints > 0) 1.184 +assign bp_match = (|bp_match_n) || (state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT); 1.185 + else 1.186 +assign bp_match = state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT; 1.187 +`else 1.188 + if (breakpoints > 0) 1.189 +assign bp_match = |bp_match_n; 1.190 + else 1.191 +assign bp_match = `FALSE; 1.192 +`endif 1.193 +endgenerate 1.194 + 1.195 +// Check for watchpoints 1.196 +generate 1.197 + for (i = 0; i < watchpoints; i = i + 1) 1.198 + begin : wp_comb 1.199 +assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); 1.200 + end 1.201 +endgenerate 1.202 +generate 1.203 + if (watchpoints > 0) 1.204 +assign wp_match = |wp_match_n; 1.205 + else 1.206 +assign wp_match = `FALSE; 1.207 +endgenerate 1.208 + 1.209 +`ifdef CFG_HW_DEBUG_ENABLED 1.210 +// Multiplex between wcsr instruction writes and debugger writes to the debug CSRs 1.211 +assign debug_csr_write_enable = (csr_write_enable_x == `TRUE) || (jtag_csr_write_enable == `TRUE); 1.212 +assign debug_csr_write_data = jtag_csr_write_enable == `TRUE ? jtag_csr_write_data : csr_write_data; 1.213 +assign debug_csr = jtag_csr_write_enable == `TRUE ? jtag_csr : csr_x; 1.214 +`else 1.215 +assign debug_csr_write_enable = csr_write_enable_x; 1.216 +assign debug_csr_write_data = csr_write_data; 1.217 +assign debug_csr = csr_x; 1.218 +`endif 1.219 + 1.220 +///////////////////////////////////////////////////// 1.221 +// Sequential Logic 1.222 +///////////////////////////////////////////////////// 1.223 + 1.224 +// Breakpoint address and enable CSRs 1.225 +generate 1.226 + for (i = 0; i < breakpoints; i = i + 1) 1.227 + begin : bp_seq 1.228 +always @(posedge clk_i `CFG_RESET_SENSITIVITY) 1.229 +begin 1.230 + if (rst_i == `TRUE) 1.231 + begin 1.232 + bp_a[i] <= {`LM32_PC_WIDTH{1'bx}}; 1.233 + bp_e[i] <= `FALSE; 1.234 + end 1.235 + else 1.236 + begin 1.237 + if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_BP0 + i)) 1.238 + begin 1.239 + bp_a[i] <= debug_csr_write_data[`LM32_PC_RNG]; 1.240 + bp_e[i] <= debug_csr_write_data[0]; 1.241 + end 1.242 + end 1.243 +end 1.244 + end 1.245 +endgenerate 1.246 + 1.247 +// Watchpoint address and control flags CSRs 1.248 +generate 1.249 + for (i = 0; i < watchpoints; i = i + 1) 1.250 + begin : wp_seq 1.251 +always @(posedge clk_i `CFG_RESET_SENSITIVITY) 1.252 +begin 1.253 + if (rst_i == `TRUE) 1.254 + begin 1.255 + wp[i] <= {`LM32_WORD_WIDTH{1'bx}}; 1.256 + wpc_c[i] <= `LM32_WPC_C_DISABLED; 1.257 + end 1.258 + else 1.259 + begin 1.260 + if (debug_csr_write_enable == `TRUE) 1.261 + begin 1.262 + if (debug_csr == `LM32_CSR_DC) 1.263 + wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; 1.264 + if (debug_csr == `LM32_CSR_WP0 + i) 1.265 + wp[i] <= debug_csr_write_data; 1.266 + end 1.267 + end 1.268 +end 1.269 + end 1.270 +endgenerate 1.271 + 1.272 +// Remap exceptions control bit 1.273 +always @(posedge clk_i `CFG_RESET_SENSITIVITY) 1.274 +begin 1.275 + if (rst_i == `TRUE) 1.276 + dc_re <= `FALSE; 1.277 + else 1.278 + begin 1.279 + if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC)) 1.280 + dc_re <= debug_csr_write_data[1]; 1.281 + end 1.282 +end 1.283 + 1.284 +`ifdef LM32_SINGLE_STEP_ENABLED 1.285 +// Single-step control flag 1.286 +always @(posedge clk_i `CFG_RESET_SENSITIVITY) 1.287 +begin 1.288 + if (rst_i == `TRUE) 1.289 + begin 1.290 + state <= `LM32_DEBUG_SS_STATE_IDLE; 1.291 + dc_ss <= `FALSE; 1.292 + end 1.293 + else 1.294 + begin 1.295 + if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC)) 1.296 + begin 1.297 + dc_ss <= debug_csr_write_data[0]; 1.298 + if (debug_csr_write_data[0] == `FALSE) 1.299 + state <= `LM32_DEBUG_SS_STATE_IDLE; 1.300 + else 1.301 + state <= `LM32_DEBUG_SS_STATE_WAIT_FOR_RET; 1.302 + end 1.303 + case (state) 1.304 + `LM32_DEBUG_SS_STATE_WAIT_FOR_RET: 1.305 + begin 1.306 + // Wait for eret or bret instruction to be executed 1.307 + if ( ( (eret_q_x == `TRUE) 1.308 + || (bret_q_x == `TRUE) 1.309 + ) 1.310 + && (stall_x == `FALSE) 1.311 + ) 1.312 + state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN; 1.313 + end 1.314 + `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN: 1.315 + begin 1.316 + // Wait for an instruction to be executed 1.317 + if ((q_x == `TRUE) && (stall_x == `FALSE)) 1.318 + state <= `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT; 1.319 + end 1.320 + `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT: 1.321 + begin 1.322 + // Wait for exception to be raised 1.323 +`ifdef CFG_DCACHE_ENABLED 1.324 + if (dcache_refill_request == `TRUE) 1.325 + state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN; 1.326 + else 1.327 +`endif 1.328 + if ((exception_x == `TRUE) && (q_x == `TRUE) && (stall_x == `FALSE)) 1.329 + begin 1.330 + dc_ss <= `FALSE; 1.331 + state <= `LM32_DEBUG_SS_STATE_RESTART; 1.332 + end 1.333 + end 1.334 + `LM32_DEBUG_SS_STATE_RESTART: 1.335 + begin 1.336 + // Watch to see if stepped instruction is restarted due to a cache miss 1.337 +`ifdef CFG_DCACHE_ENABLED 1.338 + if (dcache_refill_request == `TRUE) 1.339 + state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN; 1.340 + else 1.341 +`endif 1.342 + state <= `LM32_DEBUG_SS_STATE_IDLE; 1.343 + end 1.344 + endcase 1.345 + end 1.346 +end 1.347 +`endif 1.348 + 1.349 +endmodule 1.350 + 1.351 +`endif