Mon, 05 Apr 2010 21:00:31 +0100
reduce size of caches to fit in DE1 FPGA
The default cache size makes the Icache and Dcache "just a bit" too big to
fit in the EP2C20 FPGA on the DE1 board. This commit reduces the Icache and
Dcache sizes to the defaults shown in the LatticeMico32 Processor Reference
Manual (pages 36 and 37).
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 |