rtl/verilog/timer.v

Fri, 13 Aug 2010 10:49:23 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Fri, 13 Aug 2010 10:49:23 +0100
changeset 0
396b0bd970d3
child 1
85c1144140c3
permissions
-rw-r--r--

Initial import, Timer v3.0

     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          : LM32 Timer
    18 // File             : timer.v
    19 // Title            : Timer component core file
    20 // Dependencies     : None
    21 // Version          : 7.0
    22 //                  : Initial Release
    23 // Version          : 7.0SP2, 3.0
    24 //                  : No Change
    25 // =============================================================================
    26 `ifndef TIMER_FILE
    27 `define TIMER_FILE
    28 module timer #(
    29    parameter PERIOD_NUM   = 20,//decimal
    30    parameter PERIOD_WIDTH = 16,//decimal
    31    parameter WRITEABLE_PERIOD  = 1,
    32    parameter READABLE_SNAPSHOT = 1,
    33    parameter START_STOP_CONTROL = 1,
    34    parameter TIMEOUT_PULSE = 1,
    35    parameter WATCHDOG = 0)
    36              (
    37              //slave port
    38              S_ADR_I,    //32bits
    39              S_DAT_I,    //32bits
    40              S_WE_I,
    41              S_STB_I,
    42              S_CYC_I,
    43              S_CTI_I,
    44              S_BTE_I,
    45              S_LOCK_I,
    46              S_SEL_I,
    47              S_DAT_O,    //32bits
    48              S_ACK_O,
    49              S_RTY_O,
    50              S_ERR_O,
    51              S_INT_O,
    52              RSTREQ_O,   //resetrequest, only used when WatchDog enabled
    53              TOPULSE_O,  //timeoutpulse, only used when TimeOutPulse enabled
    54              //system clock and reset
    55              CLK_I,
    56              RST_I
    57              );
    59    input  [31:0]  S_ADR_I;
    60    input  [31:0]  S_DAT_I;
    61    input          S_WE_I;
    62    input          S_STB_I;
    63    input          S_CYC_I;
    64    input  [2:0]   S_CTI_I;
    65    input          S_LOCK_I;
    66    input  [3:0]   S_SEL_I;
    67    input  [1:0]   S_BTE_I;
    68    output [31:0]  S_DAT_O;
    69    output         S_ACK_O;
    70    output         S_INT_O;
    71    output         S_RTY_O;
    72    output         S_ERR_O;
    73    output         RSTREQ_O;
    74    output         TOPULSE_O;
    76    input          CLK_I;
    77    input          RST_I;
    79    parameter  UDLY     = 1;
    80    parameter  ST_IDLE  = 2'b00;
    81    parameter  ST_CNT   = 2'b01;
    82    parameter  ST_STOP  = 2'b10;
    84    reg  dw00_cs;
    85    reg  dw04_cs;
    86    reg  dw08_cs;
    87    reg  dw0c_cs;
    88    reg  reg_wr;
    89    reg  reg_rd;
    90    reg  [31:0] latch_s_data;
    91    reg  [1:0]  reg_04_data;
    92    reg         reg_run;
    93    reg         reg_stop;
    94    reg         reg_start;
    95    reg [1:0]   status;
    96    reg  [PERIOD_WIDTH-1:0] internal_counter;
    97    reg  [PERIOD_WIDTH-1:0] reg_08_data;
    98    reg  s_ack_dly;
    99    reg  s_ack_2dly;
   100    reg  s_ack_pre;
   101    reg  RSTREQ_O;
   102    reg  TOPULSE_O;
   103    reg  reg_to;
   105    wire        reg_cont;
   106    wire        reg_ito;
   107    wire [1:0]  read_00_data;
   108    wire [1:0]  read_04_data;
   109    wire [PERIOD_WIDTH-1:0] read_08_data;
   110    wire [PERIOD_WIDTH-1:0] read_0c_data;
   111    wire [PERIOD_WIDTH-1:0] reg_period;
   112    wire        S_ACK_O;
   113    wire [31:0] S_DAT_O;
   114    wire        S_INT_O;
   116    assign     S_RTY_O = 1'b0;
   117    assign     S_ERR_O = 1'b0;
   119    always @(posedge CLK_I or posedge RST_I)
   120      if(RST_I)
   121        latch_s_data     <= #UDLY 32'h0;
   122      else
   123        latch_s_data     <= #UDLY S_DAT_I;
   125    always @(posedge CLK_I or posedge RST_I)
   126      if(RST_I)
   127        begin
   128           dw00_cs   <= #UDLY 1'b0;
   129           dw04_cs   <= #UDLY 1'b0;
   130           dw08_cs   <= #UDLY 1'b0;
   131           dw0c_cs   <= #UDLY 1'b0;
   132        end
   133      else
   134        begin
   135           dw00_cs   <= #UDLY (!(|S_ADR_I[5:2]));
   136           dw04_cs   <= #UDLY (S_ADR_I[5:2] == 4'h1);
   137           dw08_cs   <= #UDLY (S_ADR_I[5:2] == 4'h2);
   138           dw0c_cs   <= #UDLY (S_ADR_I[5:2] == 4'h3);
   139        end
   141    always @(posedge CLK_I or posedge RST_I)
   142      if(RST_I)
   143        begin
   144           reg_wr    <= #UDLY 1'b0;
   145           reg_rd    <= #UDLY 1'b0;
   146        end
   147      else
   148        begin
   149           reg_wr    <= #UDLY S_WE_I && S_STB_I && S_CYC_I;
   150           reg_rd    <= #UDLY !S_WE_I && S_STB_I && S_CYC_I;
   151        end
   153    generate
   154    if (START_STOP_CONTROL == 1)
   156    always @(posedge CLK_I or posedge RST_I)
   157      if(RST_I)
   158        begin
   159           status                   <= #UDLY ST_IDLE;
   160           internal_counter         <= #UDLY 'h0;
   161        end
   162      else
   163        case(status)
   164          ST_IDLE:
   165            begin
   166              if(reg_wr && dw08_cs)
   167                begin
   168                internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period;
   169                end
   170              else if(reg_start && !reg_stop)
   171                begin
   172                status           <= #UDLY ST_CNT;
   173                if(|reg_period)
   174                  internal_counter <= #UDLY reg_period - 1;
   175                end
   176            end
   177          ST_CNT:
   178            begin
   179               if(reg_stop && (|internal_counter))
   180                 status           <= #UDLY ST_STOP;
   181               else if(reg_wr && dw08_cs)
   182                 begin
   183                 internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period;
   184                 if(!(|internal_counter) && !reg_cont)
   185                    status        <= #UDLY ST_IDLE;
   186                 end
   187               else if(!(|internal_counter))
   188                 begin
   189                 if(!reg_cont)
   190                   begin
   191                   status         <= #UDLY ST_IDLE;
   192                   end
   193                 internal_counter <= #UDLY reg_period;
   194                 end
   195               else
   196                 internal_counter <= #UDLY internal_counter - 1;
   197            end
   198          ST_STOP:
   199            begin
   200               if(reg_start && !reg_stop)
   201                 status           <= #UDLY ST_CNT;
   202               else if(reg_wr && dw08_cs)
   203                 begin
   204                 internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period;
   205                 end
   206            end
   207         default:
   208            begin
   209               status               <= #UDLY ST_IDLE;
   210               internal_counter     <= #UDLY 'h0;
   211            end
   212        endcase
   213    endgenerate
   216    generate
   217    if (START_STOP_CONTROL == 0)
   218    always @(posedge CLK_I or posedge RST_I)
   219      if(RST_I)
   220        internal_counter         <= #UDLY 'h0;
   221      else if ((reg_wr && dw08_cs) && (WATCHDOG == 1) || !(|internal_counter))
   222        internal_counter         <= #UDLY reg_period;
   223      else
   224        internal_counter         <= #UDLY internal_counter - 1;
   225    endgenerate
   227    always @(posedge CLK_I or posedge RST_I)
   228      if(RST_I)
   229        reg_to        <= #UDLY 1'b0;
   230      else if(reg_wr && dw00_cs && (!latch_s_data[0]))
   231        reg_to        <= #UDLY 1'b0;
   232      else if(!(|internal_counter) && reg_ito && ((START_STOP_CONTROL == 0) || reg_run))
   233        reg_to        <= #UDLY 1'b1;
   235    generate
   236    if (START_STOP_CONTROL == 1)
   237    always @(posedge CLK_I or posedge RST_I)
   238      if(RST_I)
   239        reg_run       <= #UDLY 1'b0;
   240      else if(reg_stop)
   241        reg_run       <= #UDLY 1'b0;
   242      else if(reg_start)
   243        reg_run       <= #UDLY 1'b1;
   244      else
   245        reg_run       <= #UDLY (status !== ST_IDLE);
   246    endgenerate
   248    assign read_00_data   = (START_STOP_CONTROL == 1) ? {reg_run,reg_to} : {1'b1,reg_to};
   250    //reg_04:control
   251    assign      {reg_cont,reg_ito} = reg_04_data;
   253    generate
   254    if (START_STOP_CONTROL == 1)
   255    always @(posedge CLK_I or posedge RST_I)
   256      if(RST_I)
   257        reg_stop      <= #UDLY 1'b0;
   258      else if(reg_wr && dw04_cs)
   259        begin
   260           if(latch_s_data[3] && !latch_s_data[2] && !reg_stop)
   261             reg_stop  <= #UDLY 1'b1;
   262           else if(!latch_s_data[3] && latch_s_data[2] && reg_stop)
   263             reg_stop  <= #UDLY 1'b0;
   264        end
   266    always @(posedge CLK_I or posedge RST_I)
   267      if(RST_I)
   268        reg_start     <= #UDLY 1'b0;
   269      else if(reg_wr && dw04_cs && !reg_run)
   270        reg_start     <= #UDLY latch_s_data[2];
   271      else
   272        reg_start     <= #UDLY 1'b0;
   273    endgenerate
   275    always @(posedge CLK_I or posedge RST_I)
   276      if(RST_I)
   277        reg_04_data   <= #UDLY 2'h0;
   278      else if(reg_wr && dw04_cs)
   279        reg_04_data   <= #UDLY latch_s_data[1:0];
   281    assign  read_04_data   = reg_04_data;
   283   generate
   284   if (WRITEABLE_PERIOD == 1) begin
   285     assign reg_period     = reg_08_data;
   286     assign read_08_data   = reg_08_data;
   287     always @(posedge CLK_I or posedge RST_I) begin
   288      if (RST_I)
   289        reg_08_data   <= #UDLY PERIOD_NUM;
   290      else if ((reg_wr && dw08_cs) && (START_STOP_CONTROL == 1))
   291        reg_08_data   <= #UDLY latch_s_data;
   292 	 end
   293    end
   294   else
   295      assign reg_period   = PERIOD_NUM;
   296   endgenerate
   298   generate
   299   if (READABLE_SNAPSHOT == 1)
   300     assign  read_0c_data   = internal_counter;
   301   endgenerate
   303    always @(posedge CLK_I or posedge RST_I)
   304      if(RST_I)
   305        begin
   306           s_ack_pre     <= #UDLY 1'b0;
   307           s_ack_dly     <= #UDLY 1'b0;
   308           s_ack_2dly    <= #UDLY 1'b0;
   309        end
   310      else
   311        begin
   312           s_ack_pre     <= #UDLY S_STB_I && S_CYC_I;
   313           s_ack_dly     <= #UDLY s_ack_pre;
   314           s_ack_2dly    <= #UDLY s_ack_dly;
   315        end
   317    assign S_ACK_O = s_ack_dly & !s_ack_2dly;
   318    assign S_DAT_O  = (dw00_cs & !S_WE_I & S_STB_I)                     ? read_00_data :
   319                      (dw04_cs & !S_WE_I & S_STB_I)                     ? read_04_data :
   320                      (dw08_cs & !S_WE_I & S_STB_I & WRITEABLE_PERIOD)  ? read_08_data :
   321                      (dw0c_cs & !S_WE_I & S_STB_I & READABLE_SNAPSHOT) ? read_0c_data :
   322                                                                          32'h0;
   323    assign S_INT_O  = reg_to;
   325   generate
   326   if (WATCHDOG == 1)
   327    always @(posedge CLK_I or posedge RST_I) begin
   328      if(RST_I)
   329        RSTREQ_O      <= #UDLY 1'b0;
   330      else if(!(|internal_counter) && !RSTREQ_O && ((START_STOP_CONTROL == 0) || reg_run))
   331        RSTREQ_O      <= #UDLY 1'b1;
   332      else
   333        RSTREQ_O      <= #UDLY 1'b0;
   334 	 end
   335   endgenerate
   338   generate
   339   if (TIMEOUT_PULSE == 1)
   340    //TOPULSE_O
   341    always @(posedge CLK_I or posedge RST_I)
   342      if(RST_I)
   343        TOPULSE_O     <= #UDLY 1'b0;
   344      else if(!(|internal_counter) && !TOPULSE_O && ((START_STOP_CONTROL == 0) || reg_run))
   345        TOPULSE_O     <= #UDLY 1'b1;
   346      else
   347        TOPULSE_O     <= #UDLY 1'b0;
   348   endgenerate
   350 endmodule
   351 `endif