lm32_trace.v

Sun, 04 Apr 2010 20:52:32 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 04 Apr 2010 20:52:32 +0100
changeset 2
a61bb364ae1f
parent 0
cd0b58aa6f83
child 26
73de224304c1
permissions
-rw-r--r--

Disable Lattice-specific stuff by default

To build on Lattice platforms, `define PLATFORM_LATTICE in lm32_include.v.
Otherwise, non-optimal "platform independent" HDL will be used.
This means LM32 can now be built for non-Lattice FPGAs.

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