OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [hw/] [vlog/] [system/] [timer_module.v] - Blame information for rev 20

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 csantifort
//////////////////////////////////////////////////////////////////
2
//                                                              //
3
//  Timer Module                                                //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  Contains 3 configurable timers. Each timer can generate     //
10
//  either one-shot or cyclical interrupts                      //
11
//                                                              //
12
//  Author(s):                                                  //
13
//      - Conor Santifort, csantifort.amber@gmail.com           //
14
//                                                              //
15
//////////////////////////////////////////////////////////////////
16
//                                                              //
17
// Copyright (C) 2010 Authors and OPENCORES.ORG                 //
18
//                                                              //
19
// This source file may be used and distributed without         //
20
// restriction provided that this copyright statement is not    //
21
// removed from the file and that any derivative work contains  //
22
// the original copyright notice and the associated disclaimer. //
23
//                                                              //
24
// This source file is free software; you can redistribute it   //
25
// and/or modify it under the terms of the GNU Lesser General   //
26
// Public License as published by the Free Software Foundation; //
27
// either version 2.1 of the License, or (at your option) any   //
28
// later version.                                               //
29
//                                                              //
30
// This source is distributed in the hope that it will be       //
31
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
32
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
33
// PURPOSE.  See the GNU Lesser General Public License for more //
34
// details.                                                     //
35
//                                                              //
36
// You should have received a copy of the GNU Lesser General    //
37
// Public License along with this source; if not, download it   //
38
// from http://www.opencores.org/lgpl.shtml                     //
39
//                                                              //
40
//////////////////////////////////////////////////////////////////
41
 
42
 
43
module timer_module (
44
input                       i_clk,
45
 
46
input       [31:0]          i_wb_adr,
47
input       [3:0]           i_wb_sel,
48
input                       i_wb_we,
49
output      [31:0]          o_wb_dat,
50
input       [31:0]          i_wb_dat,
51
input                       i_wb_cyc,
52
input                       i_wb_stb,
53
output                      o_wb_ack,
54
output                      o_wb_err,
55
 
56
output      [2:0]           o_timer_int
57
 
58
);
59
 
60
 
61
`include "register_addresses.v"
62
 
63
// Wishbone registers
64
reg  [15:0]     timer0_load_reg = 'd0;   // initial count value
65
reg  [15:0]     timer1_load_reg = 'd0;   // initial count value
66
reg  [15:0]     timer2_load_reg = 'd0;   // initial count value
67
reg  [23:0]     timer0_value_reg = 24'hffffff;  // current count value
68
reg  [23:0]     timer1_value_reg = 24'hffffff;  // current count value
69
reg  [23:0]     timer2_value_reg = 24'hffffff;  // current count value
70
reg  [7:0]      timer0_ctrl_reg = 'd0;   // control bits
71
reg  [7:0]      timer1_ctrl_reg = 'd0;   // control bits
72
reg  [7:0]      timer2_ctrl_reg = 'd0;   // control bits
73
reg             timer0_int_reg = 'd0;    // interrupt flag
74
reg             timer1_int_reg = 'd0;    // interrupt flag 
75
reg             timer2_int_reg = 'd0;    // interrupt flag
76
 
77
// Wishbone interface
78
reg  [31:0]     wb_rdata = 'd0;
79
wire            wb_start_write;
80
wire            wb_start_read;
81
reg             wb_start_read_d1 = 'd0;
82
 
83
 
84
// ======================================================
85
// Wishbone Interface
86
// ======================================================
87
 
88
// Can't start a write while a read is completing. The ack for the read cycle
89
// needs to be sent first
90
assign wb_start_write = i_wb_stb && i_wb_we && !wb_start_read_d1;
91
assign wb_start_read  = i_wb_stb && !i_wb_we && !o_wb_ack;
92
 
93
always @( posedge i_clk )
94
    wb_start_read_d1 <= wb_start_read;
95
 
96
assign o_wb_dat = wb_rdata;
97
 
98
assign o_wb_err = 1'd0;
99
assign o_wb_ack = i_wb_stb && ( wb_start_write || wb_start_read_d1 );
100
 
101
 
102
// ========================================================
103
// Timer Interrupt Outputs
104
// ========================================================
105
assign o_timer_int = { timer2_int_reg,
106
                       timer1_int_reg,
107
                       timer0_int_reg };
108
 
109
 
110
// ========================================================
111
// Register Writes
112
// ========================================================
113
always @( posedge i_clk )
114
    begin
115
    if ( wb_start_write )
116
        case ( i_wb_adr[15:0] )
117
            // write to timer control registers
118
            AMBER_TM_TIMER0_CTRL: timer0_ctrl_reg <= i_wb_dat[7:0];
119
            AMBER_TM_TIMER1_CTRL: timer1_ctrl_reg <= i_wb_dat[7:0];
120
            AMBER_TM_TIMER2_CTRL: timer2_ctrl_reg <= i_wb_dat[7:0];
121
        endcase
122
 
123
    // -------------------------------  
124
    // Timer 0
125
    // -------------------------------  
126
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER0_LOAD )
127
        begin
128
        timer0_value_reg <= {i_wb_dat[15:0], 8'd0};
129
        timer0_load_reg  <= i_wb_dat[15:0];
130
        end
131
    else if ( timer0_ctrl_reg[7] ) // Timer Enabled
132
        begin
133
        if ( timer0_value_reg == 24'd0 )
134
            begin
135
            if ( timer0_ctrl_reg[6] )  // periodic
136
                timer0_value_reg <= {timer0_load_reg, 8'd0};
137
            else
138
                timer0_value_reg <= 24'hffffff;
139
            end
140
        else
141
            case ( timer0_ctrl_reg[3:2] )
142
                2'b00:  timer0_value_reg <= (timer0_value_reg & 24'hffff00) - 9'd256;
143
                2'b01:  timer0_value_reg <= (timer0_value_reg & 24'hfffff0) - 9'd16;
144
                2'b10:  timer0_value_reg <=  timer0_value_reg               - 1'd1;
145
                default:
146
                    begin
147
                    //synopsys translate_off
148
                    `TB_ERROR_MESSAGE
149
                    $write("unknown Timer Module Prescale Value %d for Timer 0",
150
                           timer0_ctrl_reg[3:2]);
151
                    //synopsys translate_on
152
                    end
153
            endcase
154
        end
155
 
156
 
157
    // -------------------------------  
158
    // Timer 1
159
    // -------------------------------  
160
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER1_LOAD )
161
        begin
162
        timer1_value_reg <= {i_wb_dat[15:0], 8'd0};
163
        timer1_load_reg  <= i_wb_dat[15:0];
164
        end
165
    else if ( timer1_ctrl_reg[7] ) // Timer Enabled
166
        begin
167
        if ( timer1_value_reg == 24'd0 )
168
            begin
169
            if ( timer1_ctrl_reg[6] )  // periodic
170
                timer1_value_reg <= {timer1_load_reg, 8'd0};
171
            else
172
                timer1_value_reg <= 24'hffffff;
173
            end
174
        else
175
            case ( timer1_ctrl_reg[3:2] )
176
                2'b00:  timer1_value_reg <= (timer1_value_reg & 24'hffff00) - 9'd256;
177
                2'b01:  timer1_value_reg <= (timer1_value_reg & 24'hfffff0) - 9'd16;
178
                2'b10:  timer1_value_reg <=  timer1_value_reg - 1'd1;
179
                default:
180
                    begin
181
                    //synopsys translate_off
182
                    `TB_ERROR_MESSAGE
183
                    $write("unknown Timer Module Prescale Value %d for Timer 1",
184
                           timer1_ctrl_reg[3:2]);
185
                    //synopsys translate_on
186
                    end
187
            endcase
188
        end
189
 
190
 
191
 
192
    // -------------------------------  
193
    // Timer 2
194
    // -------------------------------  
195
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER2_LOAD )
196
        begin
197
        timer2_value_reg <= {i_wb_dat[15:0], 8'd0};
198
        timer2_load_reg  <= i_wb_dat[15:0];
199
        end
200
    else if ( timer2_ctrl_reg[7] ) // Timer Enabled
201
        begin
202
        if ( timer2_value_reg == 24'd0 )
203
            begin
204
            if ( timer2_ctrl_reg[6] )  // periodic
205
                timer2_value_reg <= {timer2_load_reg, 8'd0};
206
            else
207
                timer2_value_reg <= 24'hffffff;
208
            end
209
        else
210
            case ( timer2_ctrl_reg[3:2] )
211
                2'b00:  timer2_value_reg <= (timer2_value_reg & 24'hffff00) - 9'd256;
212
                2'b01:  timer2_value_reg <= (timer2_value_reg & 24'hfffff0) - 9'd16;
213
                2'b10:  timer2_value_reg <=  timer2_value_reg - 1'd1;
214
                default:
215
                    begin
216
                    //synopsys translate_off
217
                    `TB_ERROR_MESSAGE
218
                    $write("unknown Timer Module Prescale Value %d for Timer 2",
219
                           timer2_ctrl_reg[3:2]);
220
                    //synopsys translate_on
221
                    end
222
            endcase
223
        end
224
 
225
 
226
    // -------------------------------  
227
    // Timer generated Interrupt Flags    
228
    // -------------------------------  
229
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER0_CLR )
230
        timer0_int_reg <= 1'd0;
231
    else if ( timer0_value_reg == 24'd0 )
232
        // stays asserted until cleared
233
        timer0_int_reg <= 1'd1;
234
 
235
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER1_CLR)
236
        timer1_int_reg <= 1'd0;
237
    else if ( timer1_value_reg == 24'd0 )
238
        // stays asserted until cleared
239
        timer1_int_reg <= 1'd1;
240
 
241
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER2_CLR)
242
        timer2_int_reg <= 1'd0;
243
    else if ( timer2_value_reg == 24'd0 )
244
        // stays asserted until cleared
245
        timer2_int_reg <= 1'd1;
246
 
247
    end
248
 
249
 
250
// ========================================================
251
// Register Reads
252
// ========================================================
253
always @( posedge i_clk )
254
    if ( wb_start_read )
255
        case ( i_wb_adr[15:0] )
256
            AMBER_TM_TIMER0_LOAD: wb_rdata <= {16'd0, timer0_load_reg};
257
            AMBER_TM_TIMER1_LOAD: wb_rdata <= {16'd0, timer1_load_reg};
258
            AMBER_TM_TIMER2_LOAD: wb_rdata <= {16'd0, timer2_load_reg};
259
            AMBER_TM_TIMER0_CTRL: wb_rdata <= {24'd0,
260
                                               timer0_ctrl_reg[7:6],
261
                                               2'd0,
262
                                               timer0_ctrl_reg[3:2],
263
                                               2'd0
264
                                              };
265
            AMBER_TM_TIMER1_CTRL: wb_rdata <= {24'd0,
266
                                               timer1_ctrl_reg[7:6],
267
                                               2'd0,
268
                                               timer1_ctrl_reg[3:2],
269
                                               2'd0
270
                                              };
271
            AMBER_TM_TIMER2_CTRL: wb_rdata <= {24'd0,
272
                                               timer2_ctrl_reg[7:6],
273
                                               2'd0,
274
                                               timer2_ctrl_reg[3:2],
275
                                               2'd0
276
                                              };
277
            AMBER_TM_TIMER0_VALUE: wb_rdata <= {16'd0, timer0_value_reg[23:8]};
278
            AMBER_TM_TIMER1_VALUE: wb_rdata <= {16'd0, timer1_value_reg[23:8]};
279
            AMBER_TM_TIMER2_VALUE: wb_rdata <= {16'd0, timer2_value_reg[23:8]};
280
 
281
            default:               wb_rdata <= 32'h66778899;
282
 
283
        endcase
284
 
285
 
286
 
287
// =======================================================================================
288
// =======================================================================================
289
// =======================================================================================
290
// Non-synthesizable debug code
291
// =======================================================================================
292
 
293
 
294
//synopsys translate_off
295
 
296
`ifdef AMBER_CT_DEBUG
297
 
298
reg  timer0_int_reg_d1;
299
reg  timer1_int_reg_d1;
300
reg  timer2_int_reg_d1;
301
wire wb_read_ack = i_wb_stb && !i_wb_we &&  o_wb_ack;
302
 
303
// -----------------------------------------------
304
// Report Timer Module Register accesses
305
// -----------------------------------------------  
306
always @(posedge i_clk)
307
    if ( wb_read_ack || wb_start_write )
308
        begin
309
        `TB_DEBUG_MESSAGE
310
 
311
        if ( wb_start_write )
312
            $write("Write 0x%08x to   ", i_wb_dat);
313
        else
314
            $write("Read  0x%08x from ", o_wb_dat);
315
 
316
        case ( i_wb_adr[15:0] )
317
            AMBER_TM_TIMER0_LOAD:
318
                $write(" Timer Module Timer 0 Load");
319
            AMBER_TM_TIMER1_LOAD:
320
                $write(" Timer Module Timer 1 Load");
321
            AMBER_TM_TIMER2_LOAD:
322
                $write(" Timer Module Timer 2 Load");
323
            AMBER_TM_TIMER0_CTRL:
324
                $write(" Timer Module Timer 0 Control");
325
            AMBER_TM_TIMER1_CTRL:
326
                $write(" Timer Module Timer 1 Control");
327
            AMBER_TM_TIMER2_CTRL:
328
                $write(" Timer Module Timer 2 Control");
329
            AMBER_TM_TIMER0_VALUE:
330
                $write(" Timer Module Timer 0 Value");
331
            AMBER_TM_TIMER1_VALUE:
332
                $write(" Timer Module Timer 1 Value");
333
            AMBER_TM_TIMER2_VALUE:
334
                $write(" Timer Module Timer 2 Value");
335
            AMBER_TM_TIMER0_CLR:
336
                $write(" Timer Module Timer 0 Clear");
337
            AMBER_TM_TIMER1_CLR:
338
                $write(" Timer Module Timer 1 Clear");
339
            AMBER_TM_TIMER2_CLR:
340
                $write(" Timer Module Timer 2 Clear");
341
 
342
            default:
343
                begin
344
                $write(" unknown Amber IC Register region");
345
                $write(", Address 0x%08h\n", i_wb_adr);
346
                `TB_ERROR_MESSAGE
347
                end
348
        endcase
349
 
350
        $write(", Address 0x%08h\n", i_wb_adr);
351
        end
352
 
353
always @(posedge i_clk)
354
    begin
355
    timer0_int_reg_d1 <= timer0_int_reg;
356
    timer1_int_reg_d1 <= timer1_int_reg;
357
    timer2_int_reg_d1 <= timer2_int_reg;
358
 
359
    if ( timer0_int_reg && !timer0_int_reg_d1 )
360
        begin
361
        `TB_DEBUG_MESSAGE
362
        $display("Timer Module Timer 0 Interrupt");
363
        end
364
    if ( timer1_int_reg && !timer1_int_reg_d1 )
365
        begin
366
        `TB_DEBUG_MESSAGE
367
        $display("Timer Module Timer 1 Interrupt");
368
        end
369
    if ( timer2_int_reg && !timer2_int_reg_d1 )
370
        begin
371
        `TB_DEBUG_MESSAGE
372
        $display("Timer Module Timer 2 Interrupt");
373
        end
374
    end
375
 
376
`endif
377
 
378
//synopsys translate_on
379
 
380
 
381
endmodule
382
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.