首页 > 代码库 > OR1200处理器的计时器模块TT介绍

OR1200处理器的计时器模块TT介绍

以下内容摘自《步步惊芯——软核处理器内部设计分析》一书

 

16.2.1 TT介绍

      计时器模块(Tick TimerTT)一般用在操作系统的进程调度、用户程序的定时参考等。TT内部会对时钟周期计数,当计数值达到一个预设值时,会产生中断,通知处理器进行处理。其实现的主体是两个特殊寄存器:计时器单元计数寄存器TTCR、计时器单元模式寄存器TTMR,通过这两个SPR的不同配置,实现不同的工作模式,以及计时中断的产生。TTCRTTMR是第10组特殊寄存器,如表16.4所示。TTCRTTMR的格式分别如表16.516.6所示。

      TTMR中各个标志位的含义如下:

  •   TP:预设的计时器周期,范围是0x0-0xFFFFFFF
  •   IP:为1表示有计时器中断等待处理
  •   IE:为1表示允许计时器产生中断,反之计时器不会产生中断
  •   M:计时器的工作模式

      其中TTMR[M]的值决定了计时器的工作模式,共有4种工作模式,每种模式下计时器的工作过程如下:

      (1)自动重新开始模式Auto-restart Mode

      TTMR[M]等于2’b01时,TT工作于自动重新开始模式,在这种模式下,当TTCR[27:0]的值等于TTMR[TP]的值时,会将TTCR清零,然后继续计时,如果TTMR[IE]1,那么还会声明计时器中断。

      (2)一次计时模式One-shot Mode

      TTMR[M]等于2’b10时,TT工作于一次计时模式,在这种模式下,当TTCR[27:0]的值等于TTMR[TP]的值时,会停止计时,如果TTMR[IE]1,那么还会声明计时器中断。改写TTCR后,可以继续计时。

      (3)连续计时模式Continuous Mode

      TTMR[M]等于2’b11时,TT工作于连续计时模式,在这种模式下,当TTCR[27:0]的值等于TTMR[TP]的值时,会继续计时,也就是TTCR的值继续累加,如果TTMR[IE]1,那么还会声明计时器中断。

      (4)计时器停止模式Stop Mode

      TTMR[M]等于2’b00时,TT停止工作。

      上述各种模式下,声明计时器中断实际就是设置TTMR[IP]的值为1,处理器响应计时器中断后会进入计时器中断处理例程,但是TTMR[IP]不会自动清零,需要通程序过向TTMR[IP]写入0的方式清零。

16.2.2 TT的对外连接关系及相关宏定义

      OR1200中计时器模块TT的对外连接关系如图16.2所示,通过箭头方向表示该信号是输入还是输出。以spr_xxx开始的接口都是与特殊寄存器读写有关的信号,含义也很明了,此外,intr1表示计时器中断发生,该信号输出到CPU模块的接口sig_tick

      OR1200中与计时器有关的宏定义如下:

or1200_defines.v`define OR1200_TT_IMPLEMENTED                //是否实施TT模块,TT模块是可选模块`define OR1200_TT_OFS_TTMR 1'd0              //TTMR、TTCR寄存器在第10组特殊寄存器中的索引            `define OR1200_TT_OFS_TTCR 1'd1`define OR1200_TTOFS_BITS 0`define OR1200_TT_TTMR                       //需要定义这个宏才能使用TTMR寄存器`define OR1200_TT_TTCR                       //需要定义这个宏才能使用TTCR寄存器`define OR1200_TT_TTMR_TP 27:0               //TTMR中各个标识位的偏移`define OR1200_TT_TTMR_IP 28`define OR1200_TT_TTMR_IE 29`define OR1200_TT_TTMR_M 31:30`define OR1200_TT_READREGS                    //有了这个宏定义标识,才可以读TT中的特殊寄存器TTMR、TTCR


 

16.2.3 TT代码分析

      TT的代码主要就是配置计时器不同的工作模式,并在各种工作模式下改变TTCR、控制计时器中断的产生。代码分析如下(为了便于理解,笔者改变了代码顺序):

or1200_tt.vmodule or1200_tt(	// RISC Internal Interface	clk, rst, du_stall, spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o, intr);	……`ifdef OR1200_TT_IMPLEMENTED`ifdef OR1200_TT_TTMRreg	[31:0]	ttmr;                          	//TTMR寄存器                        `elsewire	[31:0]	ttmr;	`endif`ifdef OR1200_TT_TTCRreg	[31:0]	ttcr;	                       // TTCR寄存器`elsewire	[31:0]	ttcr;	`endif……//如果spr_cs为1,那么依据spr_addr的最低位判断指令l.mfspr/l.mtspr的访问目标是//TTMR还是TTCR,ttmr_sel为1,表示访问目标是TTMR;ttcr_sel为1,表示访问目标是TTCRassign ttmr_sel = (spr_cs && (spr_addr[`OR1200_TTOFS_BITS] == `OR1200_TT_OFS_TTMR)) ?                   1'b1 : 1'b0;assign ttcr_sel = (spr_cs && (spr_addr[`OR1200_TTOFS_BITS] == `OR1200_TT_OFS_TTCR)) ?                   1'b1 : 1'b0;//当TTMR[TP]等于TTCR[27:0]时,match等于1assign match = (ttmr[`OR1200_TT_TTMR_TP] == ttcr[27:0]) ? 1'b1 : 1'b0;   //当工作在Auto-retart模式,且TTMR[TP]等于TTCR[27:0]时,会设置restart为1assign restart = match && (ttmr[`OR1200_TT_TTMR_M] == 2'b01);//stop为1的情况有三种:(1)当工作在One-shot模式,且TTMR[TP]等于TTCR[27:0]时,//会停止计时,设置stop为1;(2)当TTMR[M]为2’b00时,计时器不工作,stop为1;//(3)外部中断单元设置定时器停止,此时du_stall为1assign stop = match &              (ttmr[`OR1200_TT_TTMR_M] == 2'b10) | (ttmr[`OR1200_TT_TTMR_M] == 2'b00) | du_stall;`ifdef OR1200_TT_TTMRalways @(posedge clk or `OR1200_RST_EVENT rst)	   if (rst == `OR1200_RST_VALUE)	  	ttmr <= 32'b0;	   else if (ttmr_sel && spr_write)               		ttmr <=  spr_dat_i;                //如果ttmr_sel为1,且spr_write为1,表示写TTMR	   else if (ttmr[`OR1200_TT_TTMR_IE])      // TTMR[IE]为1表示中断使能,那么当match等于1时,                                             //会设置TTMR[IP]为1,并且TTMR[IP]的值不会自动清零		ttmr[`OR1200_TT_TTMR_IP] <=  ttmr[`OR1200_TT_TTMR_IP] | (match & ttmr[`OR1200_TT_TTMR_IE]);`else  assign ttmr = {2'b11, 30'b0};	       //没有设置TTMR寄存器的情况下,变量ttmr的值`endif//从图16.2可知intr连接至CPU的输入sig_tick接口,intr的值就是TTMR[IP]的值,表示计时器中断是否发生assign intr = ttmr[`OR1200_TT_TTMR_IP];`ifdef OR1200_TT_TTCRalways @(posedge clk or `OR1200_RST_EVENT rst)	   if (rst == `OR1200_RST_VALUE)		 ttcr <= 32'b0;	   else if (restart)            //当工作在Auto-restart模式,且TTMR[TP]等于TTCR[27:0]                                  //时会设置restart为1,此时将TTCR清零,重新开始计数	 	 ttcr <=  32'b0;	   else if (ttcr_sel && spr_write)              //ttcr_sel为1,且spr_write为1,表示写TTCR寄存器		 ttcr <=  spr_dat_i;	   else if (!stop)                              //只要stop不为1,那么每个时钟周期TTCR的值加1		 ttcr <=  ttcr + 32'd1;`elseassign ttcr = 32'b0;                         //没有设置TTCR寄存器的情况下,变量ttcr的值`endifalways @(spr_addr or ttmr or ttcr)	case (spr_addr[`OR1200_TTOFS_BITS])	// synopsys parallel_case		`OR1200_TT_OFS_TTMR: spr_dat_o = ttmr;      //读TTMR		default: spr_dat_o = ttcr;                  //读TTCR	endcase`else                                        //在没有配置TT模块的情况下intr始终为0,没有计时器中断assign intr = 1'b0;assign spr_dat_o = 32'b0;`endifendmodule