stack-machine/timer.v

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