lm32_debug.v

Mon, 05 Apr 2010 21:00:31 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 05 Apr 2010 21:00:31 +0100
changeset 6
a8e459b24c31
parent 0
cd0b58aa6f83
child 26
73de224304c1
permissions
-rw-r--r--

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