lm32_trace.v

changeset 0
cd0b58aa6f83
child 26
73de224304c1
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/lm32_trace.v	Sun Apr 04 20:40:03 2010 +0100
     1.3 @@ -0,0 +1,298 @@
     1.4 +// =============================================================================
     1.5 +//                           COPYRIGHT NOTICE
     1.6 +// Copyright 2006 (c) Lattice Semiconductor Corporation
     1.7 +// ALL RIGHTS RESERVED
     1.8 +// This confidential and proprietary software may be used only as authorised by
     1.9 +// a licensing agreement from Lattice Semiconductor Corporation.
    1.10 +// The entire notice above must be reproduced on all authorized copies and
    1.11 +// copies may only be made to the extent permitted by a licensing agreement from
    1.12 +// Lattice Semiconductor Corporation.
    1.13 +//
    1.14 +// Lattice Semiconductor Corporation        TEL : 1-800-Lattice (USA and Canada)
    1.15 +// 5555 NE Moore Court                            408-826-6000 (other locations)
    1.16 +// Hillsboro, OR 97124                     web  : http://www.latticesemi.com/
    1.17 +// U.S.A                                   email: techsupport@latticesemi.com
    1.18 +// =============================================================================/
    1.19 +//                         FILE DETAILS
    1.20 +// Project          : LatticeMico32
    1.21 +// File             : lm32_trace.v
    1.22 +// Title            : PC Trace and associated logic.
    1.23 +// Dependencies     : lm32_include.v, lm32_functions.v
    1.24 +// Version          : 6.1.17
    1.25 +//                  : Initial Release
    1.26 +// Version          : 7.0SP2, 3.0
    1.27 +//                  : No Change
    1.28 +// Version          : 3.1
    1.29 +//                  : No Change
    1.30 +// =============================================================================
    1.31 +
    1.32 +`include "lm32_include.v"
    1.33 +`include "system_conf.v"
    1.34 +
    1.35 +`ifdef CFG_TRACE_ENABLED
    1.36 +module lm32_trace(
    1.37 +		  // ----- Inputs -------
    1.38 +		  clk_i,
    1.39 +		  rst_i,
    1.40 +		  stb_i,
    1.41 +		  we_i,
    1.42 +		  sel_i,
    1.43 +		  dat_i,
    1.44 +		  adr_i,
    1.45 +		  
    1.46 +		  trace_pc,
    1.47 +		  trace_eid,
    1.48 +		  trace_eret,
    1.49 +		  trace_bret,
    1.50 +		  trace_pc_valid,
    1.51 +		  trace_exception,
    1.52 +		  
    1.53 +		  // -- outputs
    1.54 +		  ack_o,
    1.55 +		  dat_o);
    1.56 +
    1.57 +   input clk_i;   
    1.58 +   input rst_i;   
    1.59 +   input stb_i;
    1.60 +   input we_i;   
    1.61 +   input [3:0] sel_i;
    1.62 +   input [`LM32_WORD_RNG] dat_i;
    1.63 +   input [`LM32_WORD_RNG] adr_i;
    1.64 +   input [`LM32_PC_RNG]   trace_pc;
    1.65 +   input [`LM32_EID_RNG]  trace_eid;
    1.66 +   input 		  trace_eret;
    1.67 +   input 		  trace_bret;
    1.68 +   input 		  trace_pc_valid;
    1.69 +   input 		  trace_exception;
    1.70 +   // -- outputs
    1.71 +   output 		  ack_o;
    1.72 +   output [`LM32_WORD_RNG] dat_o;
    1.73 +   reg 			   ovrflw;
    1.74 +   
    1.75 +   function integer clogb2;
    1.76 +      input [31:0] value;
    1.77 +      begin
    1.78 +	 for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1)
    1.79 +           value = value >> 1;
    1.80 +      end
    1.81 +   endfunction 
    1.82 +  
    1.83 +  // instantiate the trace memory
    1.84 +  parameter mem_data_width = `LM32_PC_WIDTH;
    1.85 +  parameter mem_addr_width = clogb2(`CFG_TRACE_DEPTH-1);
    1.86 +   
    1.87 +   wire [`LM32_PC_RNG] 	     trace_dat_o;
    1.88 +   wire [mem_addr_width-1:0] trace_raddr;
    1.89 +   wire [mem_addr_width-1:0] trace_waddr;
    1.90 +   reg  		     trace_we;
    1.91 +   wire 		     trace_be, trace_last;   
    1.92 +   wire 		     rw_creg = adr_i[12]; 
    1.93 +   
    1.94 +   lm32_ram #(.data_width    (mem_data_width),
    1.95 +	      .address_width (mem_addr_width)) 
    1.96 +     trace_mem (.read_clk  	(clk_i),
    1.97 +		.write_clk 	(clk_i),
    1.98 +		.reset     	(rst_i),
    1.99 +		.read_address 	(adr_i[mem_addr_width+1:2]),
   1.100 +		.write_address  (trace_waddr),
   1.101 +		.enable_read 	(`TRUE),
   1.102 +		.enable_write 	((trace_we | trace_be) & trace_pc_valid & !trace_last),
   1.103 +		.write_enable 	(`TRUE),
   1.104 +		.write_data   	(trace_pc),
   1.105 +		.read_data    	(trace_dat_o));
   1.106 +
   1.107 +   // trigger type & stop type
   1.108 +   //  trig_type [0] = start capture when bret
   1.109 +   //  trig_type [1] = start capture when eret
   1.110 +   //  trig_type [2] = start capture when PC within a range
   1.111 +   //  trig_type [3] = start when an exception happens (other than breakpoint)
   1.112 +   //  trig_type [4] = start when a breakpoint exception happens
   1.113 +
   1.114 +   
   1.115 +   reg [4:0]	        trig_type;	   // at address  0
   1.116 +   reg [4:0] 	        stop_type;         // at address 16   
   1.117 +   reg [`LM32_WORD_RNG] trace_len;   	   // at address  4
   1.118 +   reg [`LM32_WORD_RNG]   pc_low;	   // at address  8
   1.119 +   reg [`LM32_WORD_RNG]   pc_high;	   // at address 12
   1.120 +   reg 		        trace_start,trace_stop;
   1.121 +   reg 		        ack_o;
   1.122 +   reg 			mem_valid;   
   1.123 +   reg [`LM32_WORD_RNG] reg_dat_o;
   1.124 +   reg started;
   1.125 +   reg capturing;
   1.126 +   assign 		dat_o = (rw_creg ? reg_dat_o : trace_dat_o);
   1.127 +   
   1.128 +   initial begin
   1.129 +      trig_type <= 0;
   1.130 +      stop_type <= 0;
   1.131 +      trace_len <= 0;
   1.132 +      pc_low    <= 0;
   1.133 +      pc_high   <= 0;
   1.134 +      trace_start <= 0;
   1.135 +      trace_stop  <= 0;
   1.136 +      ack_o 	<= 0;
   1.137 +      reg_dat_o <= 0;
   1.138 +      mem_valid <= 0;
   1.139 +      started   <= 0;
   1.140 +      capturing <= 0;
   1.141 +   end
   1.142 +   
   1.143 +   // the host side control
   1.144 +   always @(posedge clk_i `CFG_RESET_SENSITIVITY)
   1.145 +     begin
   1.146 +	if (rst_i == `TRUE) begin
   1.147 +	   trig_type   <= 0;
   1.148 +	   trace_stop  <= 0;
   1.149 +	   trace_start <= 0;
   1.150 +	   pc_low      <= 0;
   1.151 +	   pc_high     <= 0;
   1.152 +	   ack_o       <= 0;
   1.153 +	end else begin
   1.154 +	   if (stb_i == `TRUE && ack_o == `FALSE) begin
   1.155 +	      if (rw_creg) begin // control register access
   1.156 +		 ack_o <= `TRUE;		    
   1.157 +		 if (we_i == `TRUE) begin
   1.158 +		    case ({adr_i[11:2],2'b0})
   1.159 +		      // write to trig type
   1.160 +		      12'd0:
   1.161 +			begin
   1.162 +			   if (sel_i[0]) begin
   1.163 +			      trig_type[4:0] <= dat_i[4:0];
   1.164 +                           end
   1.165 +                           if (sel_i[3]) begin
   1.166 +                              trace_start <= dat_i[31];
   1.167 +                              trace_stop  <= dat_i[30];
   1.168 +                           end
   1.169 +			end
   1.170 +		      12'd8:
   1.171 +			begin
   1.172 +			   if (sel_i[3]) pc_low[31:24] <= dat_i[31:24];
   1.173 +			   if (sel_i[2]) pc_low[23:16] <= dat_i[23:16];
   1.174 +			   if (sel_i[1]) pc_low[15:8]  <= dat_i[15:8];
   1.175 +			   if (sel_i[0]) pc_low[7:0]   <= dat_i[7:0];			 
   1.176 +			end
   1.177 +		      12'd12:
   1.178 +			begin
   1.179 +			   if (sel_i[3]) pc_high[31:24] <= dat_i[31:24];
   1.180 +			   if (sel_i[2]) pc_high[23:16] <= dat_i[23:16];
   1.181 +			   if (sel_i[1]) pc_high[15:8]  <= dat_i[15:8];
   1.182 +			   if (sel_i[0]) pc_high[7:0]   <= dat_i[7:0];			 
   1.183 +			end
   1.184 +		      12'd16:
   1.185 +                        begin
   1.186 +			   if (sel_i[0])begin
   1.187 +                               stop_type[4:0] <= dat_i[4:0];
   1.188 +                           end
   1.189 +                        end
   1.190 +		    endcase
   1.191 +		 end else begin // read control registers
   1.192 +		    case ({adr_i[11:2],2'b0})
   1.193 +		      // read the trig type
   1.194 +		      12'd0:
   1.195 +                        reg_dat_o <= {22'b1,capturing,mem_valid,ovrflw,trace_we,started,trig_type};
   1.196 +		      12'd4:
   1.197 +                        reg_dat_o <= trace_len;			 
   1.198 +		      12'd8:
   1.199 +			reg_dat_o <= pc_low;
   1.200 +		      12'd12:
   1.201 +			reg_dat_o <= pc_high;		      
   1.202 +		      default:
   1.203 +			reg_dat_o <= {27'b0,stop_type};
   1.204 +		    endcase
   1.205 +		 end // else: !if(we_i == `TRUE)		 
   1.206 +	      end else // read / write memory
   1.207 +		if (we_i == `FALSE) begin
   1.208 +		   ack_o <= `TRUE;
   1.209 +		end else
   1.210 +		  ack_o <= `FALSE;	      
   1.211 +	      // not allowed to write to trace memory
   1.212 +	   end else begin // if (stb_i == `TRUE)
   1.213 +	      trace_start  <= `FALSE;
   1.214 +	      trace_stop   <= `FALSE;
   1.215 +	      ack_o        <= `FALSE;	      
   1.216 +	   end // else: !if(stb_i == `TRUE)	   
   1.217 +	end // else: !if(rst_i == `TRUE)
   1.218 +     end 
   1.219 +   
   1.220 +   wire [`LM32_WORD_RNG] trace_pc_tmp = {trace_pc,2'b0};
   1.221 +   
   1.222 +   // trace state machine
   1.223 +   reg [2:0] tstate;
   1.224 +   wire      pc_in_range = {trace_pc,2'b0} >= pc_low &&
   1.225 +	                   {trace_pc,2'b0} <= pc_high;
   1.226 +   
   1.227 +   assign    trace_waddr = trace_len[mem_addr_width-1:0];
   1.228 +
   1.229 +   wire trace_begin = ((trig_type[0] & trace_bret) ||
   1.230 +		       (trig_type[1] & trace_eret) ||
   1.231 +		       (trig_type[2] & pc_in_range & trace_pc_valid) ||
   1.232 +		       (trig_type[3] & trace_exception & (trace_eid != `LM32_EID_BREAKPOINT)) ||
   1.233 +                       (trig_type[4] & trace_exception & (trace_eid == `LM32_EID_BREAKPOINT))
   1.234 +                      );
   1.235 +   
   1.236 +
   1.237 +   wire trace_end = (trace_stop  ||
   1.238 +		      (stop_type[0] & trace_bret) ||
   1.239 +		      (stop_type[1] & trace_eret) ||
   1.240 +		      (stop_type[2] & !pc_in_range & trace_pc_valid) ||
   1.241 +		      (stop_type[3] & trace_exception & (trace_eid != `LM32_EID_BREAKPOINT)) ||
   1.242 +                      (stop_type[4] & trace_exception & (trace_eid == `LM32_EID_BREAKPOINT))
   1.243 +                    );
   1.244 +
   1.245 +   assign trace_be = (trace_begin & (tstate == 3'd1));
   1.246 +   assign trace_last = (trace_stop & (tstate == 3'd2));
   1.247 +   
   1.248 +   always @(posedge clk_i `CFG_RESET_SENSITIVITY)
   1.249 +     begin
   1.250 +	if (rst_i == `TRUE) begin
   1.251 +	   tstate    <= 0;
   1.252 +	   trace_we  <= 0;
   1.253 +	   trace_len <= 0;	   
   1.254 +	   ovrflw    <= `FALSE;
   1.255 +	   mem_valid <= 0;
   1.256 +           started   <= 0;
   1.257 +           capturing <= 0;
   1.258 +	end else begin
   1.259 +	   case (tstate)
   1.260 +	   3'd0:
   1.261 +	     // start capture	     
   1.262 +	     if (trace_start) begin
   1.263 +		tstate <= 3'd1;
   1.264 +		mem_valid <= 0;
   1.265 +                started   <= 1;
   1.266 +	     end
   1.267 +	   3'd1:
   1.268 +	     begin
   1.269 +		// wait for trigger
   1.270 +		if (trace_begin) begin
   1.271 +                   capturing <= 1;
   1.272 +		   tstate    <= 3'd2;
   1.273 +		   trace_we  <= `TRUE;
   1.274 +		   trace_len <= 0;		
   1.275 +		   ovrflw    <= `FALSE;			      
   1.276 +		end
   1.277 +	     end // case: 3'd1	     
   1.278 +
   1.279 +	   3'd2:
   1.280 +	     begin
   1.281 +		if (trace_pc_valid) begin
   1.282 +		   if (trace_len[mem_addr_width])
   1.283 +		     trace_len <= 0;
   1.284 +		   else
   1.285 +		     trace_len <= trace_len + 1;
   1.286 +		end
   1.287 +		if (!ovrflw) ovrflw <= trace_len[mem_addr_width];		
   1.288 +		// wait for stop condition
   1.289 +		if (trace_end) begin
   1.290 +		   tstate    <= 3'd0;
   1.291 +		   trace_we  <= 0;
   1.292 +		   mem_valid <= 1;
   1.293 +                   started   <= 0;
   1.294 +                   capturing <= 0;
   1.295 +		end
   1.296 +	     end // case: 3'd2
   1.297 +	   endcase
   1.298 +	end // else: !if(rst_i == `TRUE)
   1.299 +     end
   1.300 +endmodule
   1.301 +`endif