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

Subversion Repositories amber

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

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 35 csantifort
module timer_module  #(
44
parameter WB_DWIDTH  = 32,
45
parameter WB_SWIDTH  = 4
46
)(
47 2 csantifort
input                       i_clk,
48
 
49
input       [31:0]          i_wb_adr,
50 35 csantifort
input       [WB_SWIDTH-1:0] i_wb_sel,
51 2 csantifort
input                       i_wb_we,
52 35 csantifort
output      [WB_DWIDTH-1:0] o_wb_dat,
53
input       [WB_DWIDTH-1:0] i_wb_dat,
54 2 csantifort
input                       i_wb_cyc,
55
input                       i_wb_stb,
56
output                      o_wb_ack,
57
output                      o_wb_err,
58
 
59
output      [2:0]           o_timer_int
60
 
61
);
62
 
63
 
64
`include "register_addresses.v"
65
 
66
// Wishbone registers
67
reg  [15:0]     timer0_load_reg = 'd0;   // initial count value
68
reg  [15:0]     timer1_load_reg = 'd0;   // initial count value
69
reg  [15:0]     timer2_load_reg = 'd0;   // initial count value
70
reg  [23:0]     timer0_value_reg = 24'hffffff;  // current count value
71
reg  [23:0]     timer1_value_reg = 24'hffffff;  // current count value
72
reg  [23:0]     timer2_value_reg = 24'hffffff;  // current count value
73
reg  [7:0]      timer0_ctrl_reg = 'd0;   // control bits
74
reg  [7:0]      timer1_ctrl_reg = 'd0;   // control bits
75
reg  [7:0]      timer2_ctrl_reg = 'd0;   // control bits
76
reg             timer0_int_reg = 'd0;    // interrupt flag
77
reg             timer1_int_reg = 'd0;    // interrupt flag 
78
reg             timer2_int_reg = 'd0;    // interrupt flag
79
 
80
// Wishbone interface
81 35 csantifort
reg  [31:0]     wb_rdata32 = 'd0;
82 2 csantifort
wire            wb_start_write;
83
wire            wb_start_read;
84
reg             wb_start_read_d1 = 'd0;
85 35 csantifort
wire [31:0]     wb_wdata32;
86 2 csantifort
 
87
 
88
// ======================================================
89
// Wishbone Interface
90
// ======================================================
91
 
92
// Can't start a write while a read is completing. The ack for the read cycle
93
// needs to be sent first
94
assign wb_start_write = i_wb_stb && i_wb_we && !wb_start_read_d1;
95
assign wb_start_read  = i_wb_stb && !i_wb_we && !o_wb_ack;
96
 
97
always @( posedge i_clk )
98
    wb_start_read_d1 <= wb_start_read;
99
 
100
 
101
assign o_wb_err = 1'd0;
102
assign o_wb_ack = i_wb_stb && ( wb_start_write || wb_start_read_d1 );
103
 
104 35 csantifort
generate
105
if (WB_DWIDTH == 128)
106
    begin : wb128
107
    assign wb_wdata32   = i_wb_adr[3:2] == 2'd3 ? i_wb_dat[127:96] :
108
                          i_wb_adr[3:2] == 2'd2 ? i_wb_dat[ 95:64] :
109
                          i_wb_adr[3:2] == 2'd1 ? i_wb_dat[ 63:32] :
110
                                                  i_wb_dat[ 31: 0] ;
111
 
112
    assign o_wb_dat    = {4{wb_rdata32}};
113
    end
114
else
115
    begin : wb32
116
    assign wb_wdata32  = i_wb_dat;
117
    assign o_wb_dat    = wb_rdata32;
118
    end
119
endgenerate
120 2 csantifort
 
121
// ========================================================
122
// Timer Interrupt Outputs
123
// ========================================================
124
assign o_timer_int = { timer2_int_reg,
125
                       timer1_int_reg,
126
                       timer0_int_reg };
127
 
128
 
129
// ========================================================
130
// Register Writes
131
// ========================================================
132
always @( posedge i_clk )
133
    begin
134
    if ( wb_start_write )
135
        case ( i_wb_adr[15:0] )
136
            // write to timer control registers
137
            AMBER_TM_TIMER0_CTRL: timer0_ctrl_reg <= i_wb_dat[7:0];
138
            AMBER_TM_TIMER1_CTRL: timer1_ctrl_reg <= i_wb_dat[7:0];
139
            AMBER_TM_TIMER2_CTRL: timer2_ctrl_reg <= i_wb_dat[7:0];
140
        endcase
141
 
142
    // -------------------------------  
143
    // Timer 0
144
    // -------------------------------  
145
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER0_LOAD )
146
        begin
147
        timer0_value_reg <= {i_wb_dat[15:0], 8'd0};
148
        timer0_load_reg  <= i_wb_dat[15:0];
149
        end
150
    else if ( timer0_ctrl_reg[7] ) // Timer Enabled
151
        begin
152
        if ( timer0_value_reg == 24'd0 )
153
            begin
154
            if ( timer0_ctrl_reg[6] )  // periodic
155
                timer0_value_reg <= {timer0_load_reg, 8'd0};
156
            else
157
                timer0_value_reg <= 24'hffffff;
158
            end
159
        else
160
            case ( timer0_ctrl_reg[3:2] )
161
                2'b00:  timer0_value_reg <= (timer0_value_reg & 24'hffff00) - 9'd256;
162
                2'b01:  timer0_value_reg <= (timer0_value_reg & 24'hfffff0) - 9'd16;
163
                2'b10:  timer0_value_reg <=  timer0_value_reg               - 1'd1;
164
                default:
165
                    begin
166
                    //synopsys translate_off
167
                    `TB_ERROR_MESSAGE
168
                    $write("unknown Timer Module Prescale Value %d for Timer 0",
169
                           timer0_ctrl_reg[3:2]);
170
                    //synopsys translate_on
171
                    end
172
            endcase
173
        end
174
 
175
 
176
    // -------------------------------  
177
    // Timer 1
178
    // -------------------------------  
179
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER1_LOAD )
180
        begin
181
        timer1_value_reg <= {i_wb_dat[15:0], 8'd0};
182
        timer1_load_reg  <= i_wb_dat[15:0];
183
        end
184
    else if ( timer1_ctrl_reg[7] ) // Timer Enabled
185
        begin
186
        if ( timer1_value_reg == 24'd0 )
187
            begin
188
            if ( timer1_ctrl_reg[6] )  // periodic
189
                timer1_value_reg <= {timer1_load_reg, 8'd0};
190
            else
191
                timer1_value_reg <= 24'hffffff;
192
            end
193
        else
194
            case ( timer1_ctrl_reg[3:2] )
195
                2'b00:  timer1_value_reg <= (timer1_value_reg & 24'hffff00) - 9'd256;
196
                2'b01:  timer1_value_reg <= (timer1_value_reg & 24'hfffff0) - 9'd16;
197
                2'b10:  timer1_value_reg <=  timer1_value_reg - 1'd1;
198
                default:
199
                    begin
200
                    //synopsys translate_off
201
                    `TB_ERROR_MESSAGE
202
                    $write("unknown Timer Module Prescale Value %d for Timer 1",
203
                           timer1_ctrl_reg[3:2]);
204
                    //synopsys translate_on
205
                    end
206
            endcase
207
        end
208
 
209
 
210
 
211
    // -------------------------------  
212
    // Timer 2
213
    // -------------------------------  
214
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER2_LOAD )
215
        begin
216
        timer2_value_reg <= {i_wb_dat[15:0], 8'd0};
217
        timer2_load_reg  <= i_wb_dat[15:0];
218
        end
219
    else if ( timer2_ctrl_reg[7] ) // Timer Enabled
220
        begin
221
        if ( timer2_value_reg == 24'd0 )
222
            begin
223
            if ( timer2_ctrl_reg[6] )  // periodic
224
                timer2_value_reg <= {timer2_load_reg, 8'd0};
225
            else
226
                timer2_value_reg <= 24'hffffff;
227
            end
228
        else
229
            case ( timer2_ctrl_reg[3:2] )
230
                2'b00:  timer2_value_reg <= (timer2_value_reg & 24'hffff00) - 9'd256;
231
                2'b01:  timer2_value_reg <= (timer2_value_reg & 24'hfffff0) - 9'd16;
232
                2'b10:  timer2_value_reg <=  timer2_value_reg - 1'd1;
233
                default:
234
                    begin
235
                    //synopsys translate_off
236
                    `TB_ERROR_MESSAGE
237
                    $write("unknown Timer Module Prescale Value %d for Timer 2",
238
                           timer2_ctrl_reg[3:2]);
239
                    //synopsys translate_on
240
                    end
241
            endcase
242
        end
243
 
244
 
245
    // -------------------------------  
246
    // Timer generated Interrupt Flags    
247
    // -------------------------------  
248
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER0_CLR )
249
        timer0_int_reg <= 1'd0;
250
    else if ( timer0_value_reg == 24'd0 )
251
        // stays asserted until cleared
252
        timer0_int_reg <= 1'd1;
253
 
254
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER1_CLR)
255
        timer1_int_reg <= 1'd0;
256
    else if ( timer1_value_reg == 24'd0 )
257
        // stays asserted until cleared
258
        timer1_int_reg <= 1'd1;
259
 
260
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_TM_TIMER2_CLR)
261
        timer2_int_reg <= 1'd0;
262
    else if ( timer2_value_reg == 24'd0 )
263
        // stays asserted until cleared
264
        timer2_int_reg <= 1'd1;
265
 
266
    end
267
 
268
 
269
// ========================================================
270
// Register Reads
271
// ========================================================
272
always @( posedge i_clk )
273
    if ( wb_start_read )
274
        case ( i_wb_adr[15:0] )
275 35 csantifort
            AMBER_TM_TIMER0_LOAD: wb_rdata32 <= {16'd0, timer0_load_reg};
276
            AMBER_TM_TIMER1_LOAD: wb_rdata32 <= {16'd0, timer1_load_reg};
277
            AMBER_TM_TIMER2_LOAD: wb_rdata32 <= {16'd0, timer2_load_reg};
278
            AMBER_TM_TIMER0_CTRL: wb_rdata32 <= {24'd0,
279 2 csantifort
                                               timer0_ctrl_reg[7:6],
280
                                               2'd0,
281
                                               timer0_ctrl_reg[3:2],
282
                                               2'd0
283
                                              };
284 35 csantifort
            AMBER_TM_TIMER1_CTRL: wb_rdata32 <= {24'd0,
285 2 csantifort
                                               timer1_ctrl_reg[7:6],
286
                                               2'd0,
287
                                               timer1_ctrl_reg[3:2],
288
                                               2'd0
289
                                              };
290 35 csantifort
            AMBER_TM_TIMER2_CTRL: wb_rdata32 <= {24'd0,
291 2 csantifort
                                               timer2_ctrl_reg[7:6],
292
                                               2'd0,
293
                                               timer2_ctrl_reg[3:2],
294
                                               2'd0
295
                                              };
296 35 csantifort
            AMBER_TM_TIMER0_VALUE: wb_rdata32 <= {16'd0, timer0_value_reg[23:8]};
297
            AMBER_TM_TIMER1_VALUE: wb_rdata32 <= {16'd0, timer1_value_reg[23:8]};
298
            AMBER_TM_TIMER2_VALUE: wb_rdata32 <= {16'd0, timer2_value_reg[23:8]};
299 2 csantifort
 
300 35 csantifort
            default:               wb_rdata32 <= 32'h66778899;
301 2 csantifort
 
302
        endcase
303
 
304
 
305
 
306
// =======================================================================================
307
// =======================================================================================
308
// =======================================================================================
309
// Non-synthesizable debug code
310
// =======================================================================================
311
 
312
 
313
//synopsys translate_off
314
 
315
`ifdef AMBER_CT_DEBUG
316
 
317
reg  timer0_int_reg_d1;
318
reg  timer1_int_reg_d1;
319
reg  timer2_int_reg_d1;
320
wire wb_read_ack = i_wb_stb && !i_wb_we &&  o_wb_ack;
321
 
322
// -----------------------------------------------
323
// Report Timer Module Register accesses
324
// -----------------------------------------------  
325
always @(posedge i_clk)
326
    if ( wb_read_ack || wb_start_write )
327
        begin
328
        `TB_DEBUG_MESSAGE
329
 
330
        if ( wb_start_write )
331
            $write("Write 0x%08x to   ", i_wb_dat);
332
        else
333
            $write("Read  0x%08x from ", o_wb_dat);
334
 
335
        case ( i_wb_adr[15:0] )
336
            AMBER_TM_TIMER0_LOAD:
337
                $write(" Timer Module Timer 0 Load");
338
            AMBER_TM_TIMER1_LOAD:
339
                $write(" Timer Module Timer 1 Load");
340
            AMBER_TM_TIMER2_LOAD:
341
                $write(" Timer Module Timer 2 Load");
342
            AMBER_TM_TIMER0_CTRL:
343
                $write(" Timer Module Timer 0 Control");
344
            AMBER_TM_TIMER1_CTRL:
345
                $write(" Timer Module Timer 1 Control");
346
            AMBER_TM_TIMER2_CTRL:
347
                $write(" Timer Module Timer 2 Control");
348
            AMBER_TM_TIMER0_VALUE:
349
                $write(" Timer Module Timer 0 Value");
350
            AMBER_TM_TIMER1_VALUE:
351
                $write(" Timer Module Timer 1 Value");
352
            AMBER_TM_TIMER2_VALUE:
353
                $write(" Timer Module Timer 2 Value");
354
            AMBER_TM_TIMER0_CLR:
355
                $write(" Timer Module Timer 0 Clear");
356
            AMBER_TM_TIMER1_CLR:
357
                $write(" Timer Module Timer 1 Clear");
358
            AMBER_TM_TIMER2_CLR:
359
                $write(" Timer Module Timer 2 Clear");
360
 
361
            default:
362
                begin
363
                $write(" unknown Amber IC Register region");
364
                $write(", Address 0x%08h\n", i_wb_adr);
365
                `TB_ERROR_MESSAGE
366
                end
367
        endcase
368
 
369
        $write(", Address 0x%08h\n", i_wb_adr);
370
        end
371
 
372
always @(posedge i_clk)
373
    begin
374
    timer0_int_reg_d1 <= timer0_int_reg;
375
    timer1_int_reg_d1 <= timer1_int_reg;
376
    timer2_int_reg_d1 <= timer2_int_reg;
377
 
378
    if ( timer0_int_reg && !timer0_int_reg_d1 )
379
        begin
380
        `TB_DEBUG_MESSAGE
381
        $display("Timer Module Timer 0 Interrupt");
382
        end
383
    if ( timer1_int_reg && !timer1_int_reg_d1 )
384
        begin
385
        `TB_DEBUG_MESSAGE
386
        $display("Timer Module Timer 1 Interrupt");
387
        end
388
    if ( timer2_int_reg && !timer2_int_reg_d1 )
389
        begin
390
        `TB_DEBUG_MESSAGE
391
        $display("Timer Module Timer 2 Interrupt");
392
        end
393
    end
394
 
395
`endif
396
 
397
//synopsys translate_on
398
 
399
 
400
endmodule
401
 

powered by: WebSVN 2.1.0

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