以下内容摘自《步步惊芯——软核处理器内部设计分析》一书
计时器模块(Tick Timer:TT)一般用在操作系统的进程调度、用户程序的定时参考等。TT内部会对时钟周期计数,当计数值达到一个预设值时,会产生中断,通知处理器进行处理。其实现的主体是两个特殊寄存器:计时器单元计数寄存器TTCR、计时器单元模式寄存器TTMR,通过这两个SPR的不同配置,实现不同的工作模式,以及计时中断的产生。TTCR、TTMR是第10组特殊寄存器,如表16.4所示。TTCR、TTMR的格式分别如表16.5、16.6所示。
TTMR中各个标志位的含义如下:
其中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的方式清零。
OR1200中计时器模块TT的对外连接关系如图16.2所示,通过箭头方向表示该信号是输入还是输出。以spr_xxx开始的接口都是与特殊寄存器读写有关的信号,含义也很明了,此外,intr为1表示计时器中断发生,该信号输出到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
TT的代码主要就是配置计时器不同的工作模式,并在各种工作模式下改变TTCR、控制计时器中断的产生。代码分析如下(为了便于理解,笔者改变了代码顺序):
or1200_tt.v module 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_TTMR reg [31:0] ttmr; //TTMR寄存器 `else wire [31:0] ttmr; `endif `ifdef OR1200_TT_TTCR reg [31:0] ttcr; // TTCR寄存器 `else wire [31:0] ttcr; `endif …… //如果spr_cs为1,那么依据spr_addr的最低位判断指令l.mfspr/l.mtspr的访问目标是 //TTMR还是TTCR,ttmr_sel为1,表示访问目标是TTMR;ttcr_sel为1,表示访问目标是TTCR assign 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等于1 assign match = (ttmr[`OR1200_TT_TTMR_TP] == ttcr[27:0]) ? 1'b1 : 1'b0; //当工作在Auto-retart模式,且TTMR[TP]等于TTCR[27:0]时,会设置restart为1 assign 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为1 assign stop = match & (ttmr[`OR1200_TT_TTMR_M] == 2'b10) | (ttmr[`OR1200_TT_TTMR_M] == 2'b00) | du_stall; `ifdef OR1200_TT_TTMR always @(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_TTCR always @(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; `else assign ttcr = 32'b0; //没有设置TTCR寄存器的情况下,变量ttcr的值 `endif always @(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; `endif endmodule
OR1200处理器的计时器模块TT介绍,布布扣,bubuko.com
原文:http://blog.csdn.net/leishangwen/article/details/36411165