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_trace.v |
philpem@0 | 19 | // Title : PC Trace and associated logic. |
philpem@0 | 20 | // Dependencies : lm32_include.v, lm32_functions.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 | // ============================================================================= |
philpem@0 | 28 | |
philpem@0 | 29 | `include "lm32_include.v" |
philpem@0 | 30 | `include "system_conf.v" |
philpem@0 | 31 | |
philpem@0 | 32 | `ifdef CFG_TRACE_ENABLED |
philpem@0 | 33 | module lm32_trace( |
philpem@0 | 34 | // ----- Inputs ------- |
philpem@0 | 35 | clk_i, |
philpem@0 | 36 | rst_i, |
philpem@0 | 37 | stb_i, |
philpem@0 | 38 | we_i, |
philpem@0 | 39 | sel_i, |
philpem@0 | 40 | dat_i, |
philpem@0 | 41 | adr_i, |
philpem@0 | 42 | |
philpem@0 | 43 | trace_pc, |
philpem@0 | 44 | trace_eid, |
philpem@0 | 45 | trace_eret, |
philpem@0 | 46 | trace_bret, |
philpem@0 | 47 | trace_pc_valid, |
philpem@0 | 48 | trace_exception, |
philpem@0 | 49 | |
philpem@0 | 50 | // -- outputs |
philpem@0 | 51 | ack_o, |
philpem@0 | 52 | dat_o); |
philpem@0 | 53 | |
philpem@0 | 54 | input clk_i; |
philpem@0 | 55 | input rst_i; |
philpem@0 | 56 | input stb_i; |
philpem@0 | 57 | input we_i; |
philpem@0 | 58 | input [3:0] sel_i; |
philpem@0 | 59 | input [`LM32_WORD_RNG] dat_i; |
philpem@0 | 60 | input [`LM32_WORD_RNG] adr_i; |
philpem@0 | 61 | input [`LM32_PC_RNG] trace_pc; |
philpem@0 | 62 | input [`LM32_EID_RNG] trace_eid; |
philpem@0 | 63 | input trace_eret; |
philpem@0 | 64 | input trace_bret; |
philpem@0 | 65 | input trace_pc_valid; |
philpem@0 | 66 | input trace_exception; |
philpem@0 | 67 | // -- outputs |
philpem@0 | 68 | output ack_o; |
philpem@0 | 69 | output [`LM32_WORD_RNG] dat_o; |
philpem@0 | 70 | reg ovrflw; |
philpem@0 | 71 | |
philpem@0 | 72 | function integer clogb2; |
philpem@0 | 73 | input [31:0] value; |
philpem@0 | 74 | begin |
philpem@0 | 75 | for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) |
philpem@0 | 76 | value = value >> 1; |
philpem@0 | 77 | end |
philpem@0 | 78 | endfunction |
philpem@0 | 79 | |
philpem@0 | 80 | // instantiate the trace memory |
philpem@0 | 81 | parameter mem_data_width = `LM32_PC_WIDTH; |
philpem@0 | 82 | parameter mem_addr_width = clogb2(`CFG_TRACE_DEPTH-1); |
philpem@0 | 83 | |
philpem@0 | 84 | wire [`LM32_PC_RNG] trace_dat_o; |
philpem@0 | 85 | wire [mem_addr_width-1:0] trace_raddr; |
philpem@0 | 86 | wire [mem_addr_width-1:0] trace_waddr; |
philpem@0 | 87 | reg trace_we; |
philpem@0 | 88 | wire trace_be, trace_last; |
philpem@0 | 89 | wire rw_creg = adr_i[12]; |
philpem@0 | 90 | |
philpem@0 | 91 | lm32_ram #(.data_width (mem_data_width), |
philpem@0 | 92 | .address_width (mem_addr_width)) |
philpem@0 | 93 | trace_mem (.read_clk (clk_i), |
philpem@0 | 94 | .write_clk (clk_i), |
philpem@0 | 95 | .reset (rst_i), |
philpem@0 | 96 | .read_address (adr_i[mem_addr_width+1:2]), |
philpem@0 | 97 | .write_address (trace_waddr), |
philpem@0 | 98 | .enable_read (`TRUE), |
philpem@0 | 99 | .enable_write ((trace_we | trace_be) & trace_pc_valid & !trace_last), |
philpem@0 | 100 | .write_enable (`TRUE), |
philpem@0 | 101 | .write_data (trace_pc), |
philpem@0 | 102 | .read_data (trace_dat_o)); |
philpem@0 | 103 | |
philpem@0 | 104 | // trigger type & stop type |
philpem@0 | 105 | // trig_type [0] = start capture when bret |
philpem@0 | 106 | // trig_type [1] = start capture when eret |
philpem@0 | 107 | // trig_type [2] = start capture when PC within a range |
philpem@0 | 108 | // trig_type [3] = start when an exception happens (other than breakpoint) |
philpem@0 | 109 | // trig_type [4] = start when a breakpoint exception happens |
philpem@0 | 110 | |
philpem@0 | 111 | |
philpem@0 | 112 | reg [4:0] trig_type; // at address 0 |
philpem@0 | 113 | reg [4:0] stop_type; // at address 16 |
philpem@0 | 114 | reg [`LM32_WORD_RNG] trace_len; // at address 4 |
philpem@0 | 115 | reg [`LM32_WORD_RNG] pc_low; // at address 8 |
philpem@0 | 116 | reg [`LM32_WORD_RNG] pc_high; // at address 12 |
philpem@0 | 117 | reg trace_start,trace_stop; |
philpem@0 | 118 | reg ack_o; |
philpem@0 | 119 | reg mem_valid; |
philpem@0 | 120 | reg [`LM32_WORD_RNG] reg_dat_o; |
philpem@0 | 121 | reg started; |
philpem@0 | 122 | reg capturing; |
philpem@0 | 123 | assign dat_o = (rw_creg ? reg_dat_o : trace_dat_o); |
philpem@0 | 124 | |
philpem@0 | 125 | initial begin |
philpem@0 | 126 | trig_type <= 0; |
philpem@0 | 127 | stop_type <= 0; |
philpem@0 | 128 | trace_len <= 0; |
philpem@0 | 129 | pc_low <= 0; |
philpem@0 | 130 | pc_high <= 0; |
philpem@0 | 131 | trace_start <= 0; |
philpem@0 | 132 | trace_stop <= 0; |
philpem@0 | 133 | ack_o <= 0; |
philpem@0 | 134 | reg_dat_o <= 0; |
philpem@0 | 135 | mem_valid <= 0; |
philpem@0 | 136 | started <= 0; |
philpem@0 | 137 | capturing <= 0; |
philpem@0 | 138 | end |
philpem@0 | 139 | |
philpem@0 | 140 | // the host side control |
philpem@0 | 141 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 142 | begin |
philpem@0 | 143 | if (rst_i == `TRUE) begin |
philpem@0 | 144 | trig_type <= 0; |
philpem@0 | 145 | trace_stop <= 0; |
philpem@0 | 146 | trace_start <= 0; |
philpem@0 | 147 | pc_low <= 0; |
philpem@0 | 148 | pc_high <= 0; |
philpem@0 | 149 | ack_o <= 0; |
philpem@0 | 150 | end else begin |
philpem@0 | 151 | if (stb_i == `TRUE && ack_o == `FALSE) begin |
philpem@0 | 152 | if (rw_creg) begin // control register access |
philpem@0 | 153 | ack_o <= `TRUE; |
philpem@0 | 154 | if (we_i == `TRUE) begin |
philpem@0 | 155 | case ({adr_i[11:2],2'b0}) |
philpem@0 | 156 | // write to trig type |
philpem@0 | 157 | 12'd0: |
philpem@0 | 158 | begin |
philpem@0 | 159 | if (sel_i[0]) begin |
philpem@0 | 160 | trig_type[4:0] <= dat_i[4:0]; |
philpem@0 | 161 | end |
philpem@0 | 162 | if (sel_i[3]) begin |
philpem@0 | 163 | trace_start <= dat_i[31]; |
philpem@0 | 164 | trace_stop <= dat_i[30]; |
philpem@0 | 165 | end |
philpem@0 | 166 | end |
philpem@0 | 167 | 12'd8: |
philpem@0 | 168 | begin |
philpem@0 | 169 | if (sel_i[3]) pc_low[31:24] <= dat_i[31:24]; |
philpem@0 | 170 | if (sel_i[2]) pc_low[23:16] <= dat_i[23:16]; |
philpem@0 | 171 | if (sel_i[1]) pc_low[15:8] <= dat_i[15:8]; |
philpem@0 | 172 | if (sel_i[0]) pc_low[7:0] <= dat_i[7:0]; |
philpem@0 | 173 | end |
philpem@0 | 174 | 12'd12: |
philpem@0 | 175 | begin |
philpem@0 | 176 | if (sel_i[3]) pc_high[31:24] <= dat_i[31:24]; |
philpem@0 | 177 | if (sel_i[2]) pc_high[23:16] <= dat_i[23:16]; |
philpem@0 | 178 | if (sel_i[1]) pc_high[15:8] <= dat_i[15:8]; |
philpem@0 | 179 | if (sel_i[0]) pc_high[7:0] <= dat_i[7:0]; |
philpem@0 | 180 | end |
philpem@0 | 181 | 12'd16: |
philpem@0 | 182 | begin |
philpem@0 | 183 | if (sel_i[0])begin |
philpem@0 | 184 | stop_type[4:0] <= dat_i[4:0]; |
philpem@0 | 185 | end |
philpem@0 | 186 | end |
philpem@0 | 187 | endcase |
philpem@0 | 188 | end else begin // read control registers |
philpem@0 | 189 | case ({adr_i[11:2],2'b0}) |
philpem@0 | 190 | // read the trig type |
philpem@0 | 191 | 12'd0: |
philpem@0 | 192 | reg_dat_o <= {22'b1,capturing,mem_valid,ovrflw,trace_we,started,trig_type}; |
philpem@0 | 193 | 12'd4: |
philpem@0 | 194 | reg_dat_o <= trace_len; |
philpem@0 | 195 | 12'd8: |
philpem@0 | 196 | reg_dat_o <= pc_low; |
philpem@0 | 197 | 12'd12: |
philpem@0 | 198 | reg_dat_o <= pc_high; |
philpem@0 | 199 | default: |
philpem@0 | 200 | reg_dat_o <= {27'b0,stop_type}; |
philpem@0 | 201 | endcase |
philpem@0 | 202 | end // else: !if(we_i == `TRUE) |
philpem@0 | 203 | end else // read / write memory |
philpem@0 | 204 | if (we_i == `FALSE) begin |
philpem@0 | 205 | ack_o <= `TRUE; |
philpem@0 | 206 | end else |
philpem@0 | 207 | ack_o <= `FALSE; |
philpem@0 | 208 | // not allowed to write to trace memory |
philpem@0 | 209 | end else begin // if (stb_i == `TRUE) |
philpem@0 | 210 | trace_start <= `FALSE; |
philpem@0 | 211 | trace_stop <= `FALSE; |
philpem@0 | 212 | ack_o <= `FALSE; |
philpem@0 | 213 | end // else: !if(stb_i == `TRUE) |
philpem@0 | 214 | end // else: !if(rst_i == `TRUE) |
philpem@0 | 215 | end |
philpem@0 | 216 | |
philpem@0 | 217 | wire [`LM32_WORD_RNG] trace_pc_tmp = {trace_pc,2'b0}; |
philpem@0 | 218 | |
philpem@0 | 219 | // trace state machine |
philpem@0 | 220 | reg [2:0] tstate; |
philpem@0 | 221 | wire pc_in_range = {trace_pc,2'b0} >= pc_low && |
philpem@0 | 222 | {trace_pc,2'b0} <= pc_high; |
philpem@0 | 223 | |
philpem@0 | 224 | assign trace_waddr = trace_len[mem_addr_width-1:0]; |
philpem@0 | 225 | |
philpem@0 | 226 | wire trace_begin = ((trig_type[0] & trace_bret) || |
philpem@0 | 227 | (trig_type[1] & trace_eret) || |
philpem@0 | 228 | (trig_type[2] & pc_in_range & trace_pc_valid) || |
philpem@0 | 229 | (trig_type[3] & trace_exception & (trace_eid != `LM32_EID_BREAKPOINT)) || |
philpem@0 | 230 | (trig_type[4] & trace_exception & (trace_eid == `LM32_EID_BREAKPOINT)) |
philpem@0 | 231 | ); |
philpem@0 | 232 | |
philpem@0 | 233 | |
philpem@0 | 234 | wire trace_end = (trace_stop || |
philpem@0 | 235 | (stop_type[0] & trace_bret) || |
philpem@0 | 236 | (stop_type[1] & trace_eret) || |
philpem@0 | 237 | (stop_type[2] & !pc_in_range & trace_pc_valid) || |
philpem@0 | 238 | (stop_type[3] & trace_exception & (trace_eid != `LM32_EID_BREAKPOINT)) || |
philpem@0 | 239 | (stop_type[4] & trace_exception & (trace_eid == `LM32_EID_BREAKPOINT)) |
philpem@0 | 240 | ); |
philpem@0 | 241 | |
philpem@0 | 242 | assign trace_be = (trace_begin & (tstate == 3'd1)); |
philpem@0 | 243 | assign trace_last = (trace_stop & (tstate == 3'd2)); |
philpem@0 | 244 | |
philpem@0 | 245 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 246 | begin |
philpem@0 | 247 | if (rst_i == `TRUE) begin |
philpem@0 | 248 | tstate <= 0; |
philpem@0 | 249 | trace_we <= 0; |
philpem@0 | 250 | trace_len <= 0; |
philpem@0 | 251 | ovrflw <= `FALSE; |
philpem@0 | 252 | mem_valid <= 0; |
philpem@0 | 253 | started <= 0; |
philpem@0 | 254 | capturing <= 0; |
philpem@0 | 255 | end else begin |
philpem@0 | 256 | case (tstate) |
philpem@0 | 257 | 3'd0: |
philpem@0 | 258 | // start capture |
philpem@0 | 259 | if (trace_start) begin |
philpem@0 | 260 | tstate <= 3'd1; |
philpem@0 | 261 | mem_valid <= 0; |
philpem@0 | 262 | started <= 1; |
philpem@0 | 263 | end |
philpem@0 | 264 | 3'd1: |
philpem@0 | 265 | begin |
philpem@0 | 266 | // wait for trigger |
philpem@0 | 267 | if (trace_begin) begin |
philpem@0 | 268 | capturing <= 1; |
philpem@0 | 269 | tstate <= 3'd2; |
philpem@0 | 270 | trace_we <= `TRUE; |
philpem@0 | 271 | trace_len <= 0; |
philpem@0 | 272 | ovrflw <= `FALSE; |
philpem@0 | 273 | end |
philpem@0 | 274 | end // case: 3'd1 |
philpem@0 | 275 | |
philpem@0 | 276 | 3'd2: |
philpem@0 | 277 | begin |
philpem@0 | 278 | if (trace_pc_valid) begin |
philpem@0 | 279 | if (trace_len[mem_addr_width]) |
philpem@0 | 280 | trace_len <= 0; |
philpem@0 | 281 | else |
philpem@0 | 282 | trace_len <= trace_len + 1; |
philpem@0 | 283 | end |
philpem@0 | 284 | if (!ovrflw) ovrflw <= trace_len[mem_addr_width]; |
philpem@0 | 285 | // wait for stop condition |
philpem@0 | 286 | if (trace_end) begin |
philpem@0 | 287 | tstate <= 3'd0; |
philpem@0 | 288 | trace_we <= 0; |
philpem@0 | 289 | mem_valid <= 1; |
philpem@0 | 290 | started <= 0; |
philpem@0 | 291 | capturing <= 0; |
philpem@0 | 292 | end |
philpem@0 | 293 | end // case: 3'd2 |
philpem@0 | 294 | endcase |
philpem@0 | 295 | end // else: !if(rst_i == `TRUE) |
philpem@0 | 296 | end |
philpem@0 | 297 | endmodule |
philpem@0 | 298 | `endif |