lm32_trace.v

Sat, 06 Aug 2011 01:26:56 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 06 Aug 2011 01:26:56 +0100
changeset 27
d6c693415d59
parent 26
73de224304c1
permissions
-rwxr-xr-x

remove synthesis delay entities to ease merge

philpem@26 1 // ==================================================================
philpem@26 2 // >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
philpem@26 3 // ------------------------------------------------------------------
philpem@26 4 // Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
philpem@26 5 // ALL RIGHTS RESERVED
philpem@26 6 // ------------------------------------------------------------------
philpem@26 7 //
philpem@26 8 // IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
philpem@26 9 //
philpem@26 10 // Permission:
philpem@26 11 //
philpem@26 12 // Lattice Semiconductor grants permission to use this code
philpem@26 13 // pursuant to the terms of the Lattice Semiconductor Corporation
philpem@26 14 // Open Source License Agreement.
philpem@26 15 //
philpem@26 16 // Disclaimer:
philpem@0 17 //
philpem@26 18 // Lattice Semiconductor provides no warranty regarding the use or
philpem@26 19 // functionality of this code. It is the user's responsibility to
philpem@26 20 // verify the userís design for consistency and functionality through
philpem@26 21 // the use of formal verification methods.
philpem@26 22 //
philpem@26 23 // --------------------------------------------------------------------
philpem@26 24 //
philpem@26 25 // Lattice Semiconductor Corporation
philpem@26 26 // 5555 NE Moore Court
philpem@26 27 // Hillsboro, OR 97214
philpem@26 28 // U.S.A
philpem@26 29 //
philpem@26 30 // TEL: 1-800-Lattice (USA and Canada)
philpem@26 31 // 503-286-8001 (other locations)
philpem@26 32 //
philpem@26 33 // web: http://www.latticesemi.com/
philpem@26 34 // email: techsupport@latticesemi.com
philpem@26 35 //
philpem@26 36 // --------------------------------------------------------------------
philpem@0 37 // FILE DETAILS
philpem@0 38 // Project : LatticeMico32
philpem@0 39 // File : lm32_trace.v
philpem@0 40 // Title : PC Trace and associated logic.
philpem@0 41 // Dependencies : lm32_include.v, lm32_functions.v
philpem@0 42 // Version : 6.1.17
philpem@0 43 // : Initial Release
philpem@0 44 // Version : 7.0SP2, 3.0
philpem@0 45 // : No Change
philpem@0 46 // Version : 3.1
philpem@0 47 // : No Change
philpem@26 48 // Version : 3.7
philpem@26 49 // : Removed syntax error.
philpem@0 50 // =============================================================================
philpem@0 51
philpem@0 52 `include "lm32_include.v"
philpem@0 53 `include "system_conf.v"
philpem@0 54
philpem@0 55 `ifdef CFG_TRACE_ENABLED
philpem@0 56 module lm32_trace(
philpem@0 57 // ----- Inputs -------
philpem@0 58 clk_i,
philpem@0 59 rst_i,
philpem@0 60 stb_i,
philpem@0 61 we_i,
philpem@0 62 sel_i,
philpem@0 63 dat_i,
philpem@0 64 adr_i,
philpem@0 65
philpem@0 66 trace_pc,
philpem@0 67 trace_eid,
philpem@0 68 trace_eret,
philpem@0 69 trace_bret,
philpem@0 70 trace_pc_valid,
philpem@0 71 trace_exception,
philpem@0 72
philpem@0 73 // -- outputs
philpem@0 74 ack_o,
philpem@0 75 dat_o);
philpem@0 76
philpem@0 77 input clk_i;
philpem@0 78 input rst_i;
philpem@0 79 input stb_i;
philpem@0 80 input we_i;
philpem@0 81 input [3:0] sel_i;
philpem@0 82 input [`LM32_WORD_RNG] dat_i;
philpem@0 83 input [`LM32_WORD_RNG] adr_i;
philpem@0 84 input [`LM32_PC_RNG] trace_pc;
philpem@0 85 input [`LM32_EID_RNG] trace_eid;
philpem@0 86 input trace_eret;
philpem@0 87 input trace_bret;
philpem@0 88 input trace_pc_valid;
philpem@0 89 input trace_exception;
philpem@0 90 // -- outputs
philpem@0 91 output ack_o;
philpem@0 92 output [`LM32_WORD_RNG] dat_o;
philpem@0 93 reg ovrflw;
philpem@0 94
philpem@0 95 function integer clogb2;
philpem@0 96 input [31:0] value;
philpem@0 97 begin
philpem@0 98 for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1)
philpem@0 99 value = value >> 1;
philpem@0 100 end
philpem@0 101 endfunction
philpem@0 102
philpem@0 103 // instantiate the trace memory
philpem@0 104 parameter mem_data_width = `LM32_PC_WIDTH;
philpem@0 105 parameter mem_addr_width = clogb2(`CFG_TRACE_DEPTH-1);
philpem@0 106
philpem@0 107 wire [`LM32_PC_RNG] trace_dat_o;
philpem@0 108 wire [mem_addr_width-1:0] trace_raddr;
philpem@0 109 wire [mem_addr_width-1:0] trace_waddr;
philpem@0 110 reg trace_we;
philpem@0 111 wire trace_be, trace_last;
philpem@0 112 wire rw_creg = adr_i[12];
philpem@0 113
philpem@0 114 lm32_ram #(.data_width (mem_data_width),
philpem@0 115 .address_width (mem_addr_width))
philpem@0 116 trace_mem (.read_clk (clk_i),
philpem@0 117 .write_clk (clk_i),
philpem@0 118 .reset (rst_i),
philpem@0 119 .read_address (adr_i[mem_addr_width+1:2]),
philpem@0 120 .write_address (trace_waddr),
philpem@0 121 .enable_read (`TRUE),
philpem@0 122 .enable_write ((trace_we | trace_be) & trace_pc_valid & !trace_last),
philpem@0 123 .write_enable (`TRUE),
philpem@0 124 .write_data (trace_pc),
philpem@0 125 .read_data (trace_dat_o));
philpem@0 126
philpem@0 127 // trigger type & stop type
philpem@0 128 // trig_type [0] = start capture when bret
philpem@0 129 // trig_type [1] = start capture when eret
philpem@0 130 // trig_type [2] = start capture when PC within a range
philpem@0 131 // trig_type [3] = start when an exception happens (other than breakpoint)
philpem@0 132 // trig_type [4] = start when a breakpoint exception happens
philpem@0 133
philpem@0 134
philpem@0 135 reg [4:0] trig_type; // at address 0
philpem@0 136 reg [4:0] stop_type; // at address 16
philpem@0 137 reg [`LM32_WORD_RNG] trace_len; // at address 4
philpem@0 138 reg [`LM32_WORD_RNG] pc_low; // at address 8
philpem@0 139 reg [`LM32_WORD_RNG] pc_high; // at address 12
philpem@0 140 reg trace_start,trace_stop;
philpem@0 141 reg ack_o;
philpem@0 142 reg mem_valid;
philpem@0 143 reg [`LM32_WORD_RNG] reg_dat_o;
philpem@0 144 reg started;
philpem@0 145 reg capturing;
philpem@0 146 assign dat_o = (rw_creg ? reg_dat_o : trace_dat_o);
philpem@0 147
philpem@0 148 initial begin
philpem@27 149 trig_type <= 0;
philpem@27 150 stop_type <= 0;
philpem@27 151 trace_len <= 0;
philpem@27 152 pc_low <= 0;
philpem@27 153 pc_high <= 0;
philpem@27 154 trace_start <= 0;
philpem@27 155 trace_stop <= 0;
philpem@27 156 ack_o <= 0;
philpem@27 157 reg_dat_o <= 0;
philpem@27 158 mem_valid <= 0;
philpem@27 159 started <= 0;
philpem@27 160 capturing <= 0;
philpem@0 161 end
philpem@0 162
philpem@0 163 // the host side control
philpem@0 164 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 165 begin
philpem@0 166 if (rst_i == `TRUE) begin
philpem@27 167 trig_type <= 0;
philpem@27 168 trace_stop <= 0;
philpem@27 169 trace_start <= 0;
philpem@27 170 pc_low <= 0;
philpem@27 171 pc_high <= 0;
philpem@27 172 ack_o <= 0;
philpem@0 173 end else begin
philpem@0 174 if (stb_i == `TRUE && ack_o == `FALSE) begin
philpem@0 175 if (rw_creg) begin // control register access
philpem@27 176 ack_o <= `TRUE;
philpem@0 177 if (we_i == `TRUE) begin
philpem@0 178 case ({adr_i[11:2],2'b0})
philpem@0 179 // write to trig type
philpem@0 180 12'd0:
philpem@0 181 begin
philpem@0 182 if (sel_i[0]) begin
philpem@27 183 trig_type[4:0] <= dat_i[4:0];
philpem@0 184 end
philpem@0 185 if (sel_i[3]) begin
philpem@27 186 trace_start <= dat_i[31];
philpem@27 187 trace_stop <= dat_i[30];
philpem@0 188 end
philpem@0 189 end
philpem@0 190 12'd8:
philpem@0 191 begin
philpem@27 192 if (sel_i[3]) pc_low[31:24] <= dat_i[31:24];
philpem@27 193 if (sel_i[2]) pc_low[23:16] <= dat_i[23:16];
philpem@27 194 if (sel_i[1]) pc_low[15:8] <= dat_i[15:8];
philpem@27 195 if (sel_i[0]) pc_low[7:0] <= dat_i[7:0];
philpem@0 196 end
philpem@0 197 12'd12:
philpem@0 198 begin
philpem@27 199 if (sel_i[3]) pc_high[31:24] <= dat_i[31:24];
philpem@27 200 if (sel_i[2]) pc_high[23:16] <= dat_i[23:16];
philpem@27 201 if (sel_i[1]) pc_high[15:8] <= dat_i[15:8];
philpem@27 202 if (sel_i[0]) pc_high[7:0] <= dat_i[7:0];
philpem@0 203 end
philpem@0 204 12'd16:
philpem@0 205 begin
philpem@0 206 if (sel_i[0])begin
philpem@27 207 stop_type[4:0] <= dat_i[4:0];
philpem@0 208 end
philpem@0 209 end
philpem@0 210 endcase
philpem@0 211 end else begin // read control registers
philpem@0 212 case ({adr_i[11:2],2'b0})
philpem@0 213 // read the trig type
philpem@0 214 12'd0:
philpem@27 215 reg_dat_o <= {22'b1,capturing,mem_valid,ovrflw,trace_we,started,trig_type};
philpem@0 216 12'd4:
philpem@27 217 reg_dat_o <= trace_len;
philpem@0 218 12'd8:
philpem@27 219 reg_dat_o <= pc_low;
philpem@0 220 12'd12:
philpem@27 221 reg_dat_o <= pc_high;
philpem@0 222 default:
philpem@27 223 reg_dat_o <= {27'b0,stop_type};
philpem@0 224 endcase
philpem@0 225 end // else: !if(we_i == `TRUE)
philpem@0 226 end else // read / write memory
philpem@0 227 if (we_i == `FALSE) begin
philpem@27 228 ack_o <= `TRUE;
philpem@0 229 end else
philpem@27 230 ack_o <= `FALSE;
philpem@0 231 // not allowed to write to trace memory
philpem@0 232 end else begin // if (stb_i == `TRUE)
philpem@27 233 trace_start <= `FALSE;
philpem@27 234 trace_stop <= `FALSE;
philpem@27 235 ack_o <= `FALSE;
philpem@0 236 end // else: !if(stb_i == `TRUE)
philpem@0 237 end // else: !if(rst_i == `TRUE)
philpem@0 238 end
philpem@0 239
philpem@0 240 wire [`LM32_WORD_RNG] trace_pc_tmp = {trace_pc,2'b0};
philpem@0 241
philpem@0 242 // trace state machine
philpem@0 243 reg [2:0] tstate;
philpem@0 244 wire pc_in_range = {trace_pc,2'b0} >= pc_low &&
philpem@0 245 {trace_pc,2'b0} <= pc_high;
philpem@0 246
philpem@0 247 assign trace_waddr = trace_len[mem_addr_width-1:0];
philpem@0 248
philpem@0 249 wire trace_begin = ((trig_type[0] & trace_bret) ||
philpem@0 250 (trig_type[1] & trace_eret) ||
philpem@0 251 (trig_type[2] & pc_in_range & trace_pc_valid) ||
philpem@0 252 (trig_type[3] & trace_exception & (trace_eid != `LM32_EID_BREAKPOINT)) ||
philpem@0 253 (trig_type[4] & trace_exception & (trace_eid == `LM32_EID_BREAKPOINT))
philpem@0 254 );
philpem@0 255
philpem@0 256
philpem@0 257 wire trace_end = (trace_stop ||
philpem@0 258 (stop_type[0] & trace_bret) ||
philpem@0 259 (stop_type[1] & trace_eret) ||
philpem@0 260 (stop_type[2] & !pc_in_range & trace_pc_valid) ||
philpem@0 261 (stop_type[3] & trace_exception & (trace_eid != `LM32_EID_BREAKPOINT)) ||
philpem@0 262 (stop_type[4] & trace_exception & (trace_eid == `LM32_EID_BREAKPOINT))
philpem@0 263 );
philpem@0 264
philpem@0 265 assign trace_be = (trace_begin & (tstate == 3'd1));
philpem@0 266 assign trace_last = (trace_stop & (tstate == 3'd2));
philpem@0 267
philpem@0 268 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 269 begin
philpem@0 270 if (rst_i == `TRUE) begin
philpem@27 271 tstate <= 0;
philpem@27 272 trace_we <= 0;
philpem@27 273 trace_len <= 0;
philpem@27 274 ovrflw <= `FALSE;
philpem@27 275 mem_valid <= 0;
philpem@27 276 started <= 0;
philpem@27 277 capturing <= 0;
philpem@0 278 end else begin
philpem@0 279 case (tstate)
philpem@0 280 3'd0:
philpem@0 281 // start capture
philpem@0 282 if (trace_start) begin
philpem@27 283 tstate <= 3'd1;
philpem@27 284 mem_valid <= 0;
philpem@27 285 started <= 1;
philpem@0 286 end
philpem@0 287 3'd1:
philpem@0 288 begin
philpem@0 289 // wait for trigger
philpem@0 290 if (trace_begin) begin
philpem@27 291 capturing <= 1;
philpem@27 292 tstate <= 3'd2;
philpem@27 293 trace_we <= `TRUE;
philpem@27 294 trace_len <= 0;
philpem@27 295 ovrflw <= `FALSE;
philpem@0 296 end
philpem@0 297 end // case: 3'd1
philpem@0 298
philpem@0 299 3'd2:
philpem@0 300 begin
philpem@0 301 if (trace_pc_valid) begin
philpem@0 302 if (trace_len[mem_addr_width])
philpem@27 303 trace_len <= 0;
philpem@0 304 else
philpem@27 305 trace_len <= trace_len + 1;
philpem@0 306 end
philpem@27 307 if (!ovrflw) ovrflw <= trace_len[mem_addr_width];
philpem@0 308 // wait for stop condition
philpem@0 309 if (trace_end) begin
philpem@27 310 tstate <= 3'd0;
philpem@27 311 trace_we <= 0;
philpem@27 312 mem_valid <= 1;
philpem@27 313 started <= 0;
philpem@27 314 capturing <= 0;
philpem@0 315 end
philpem@0 316 end // case: 3'd2
philpem@0 317 endcase
philpem@0 318 end // else: !if(rst_i == `TRUE)
philpem@0 319 end
philpem@0 320 endmodule
philpem@0 321 `endif