lm32_trace.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_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