62 lines
1.2 KiB
Verilog
62 lines
1.2 KiB
Verilog
module TIMER (CLK_I,RST_I,ADR_I,DAT_I,DAT_O,STB_I,WE_I,ACK_O,IRQ_O);
|
|
|
|
parameter INIT_RELOAD = 0;
|
|
|
|
input CLK_I, RST_I, STB_I, WE_I;
|
|
input [1:0] ADR_I;
|
|
input [31:0] DAT_I;
|
|
output [31:0] DAT_O;
|
|
output ACK_O, IRQ_O;
|
|
|
|
reg [31:0] RELOAD = INIT_RELOAD;
|
|
reg [31:0] COUNTER = INIT_RELOAD;
|
|
reg [63:0] TIMEBASE = 64'd0;
|
|
|
|
wire ZERO = ~|COUNTER;
|
|
|
|
assign ACK_O = STB_I;
|
|
assign IRQ_O = ZERO & ~RST_I;
|
|
|
|
reg [31:0] DAT_O;
|
|
|
|
always @*
|
|
begin
|
|
case (ADR_I)
|
|
2'd0: DAT_O <= COUNTER;
|
|
2'd1: DAT_O <= RELOAD;
|
|
2'd2: DAT_O <= TIMEBASE[63:32];
|
|
2'd3: DAT_O <= TIMEBASE[31:0];
|
|
endcase
|
|
end
|
|
|
|
always @(posedge CLK_I)
|
|
begin
|
|
if (RST_I)
|
|
begin
|
|
RELOAD <= INIT_RELOAD;
|
|
COUNTER <= INIT_RELOAD;
|
|
TIMEBASE <= 64'd0;
|
|
end
|
|
else
|
|
begin
|
|
if (STB_I & WE_I & ~ADR_I[1] & ~ADR_I[0])
|
|
COUNTER <= DAT_I;
|
|
else if (ZERO | RST_I)
|
|
COUNTER <= RELOAD;
|
|
else
|
|
COUNTER <= COUNTER - 1;
|
|
|
|
if (STB_I & WE_I & ~ADR_I[1] & ADR_I[0])
|
|
RELOAD <= DAT_I;
|
|
|
|
if (STB_I & WE_I & ADR_I[1] & ~ADR_I[0])
|
|
TIMEBASE <= { DAT_I, 32'd0 };
|
|
else if (STB_I & WE_I & ADR_I[1] & ADR_I[0])
|
|
TIMEBASE <= { TIMEBASE[63:32], DAT_I };
|
|
else
|
|
TIMEBASE <= TIMEBASE + 1;
|
|
end
|
|
end
|
|
|
|
endmodule
|