// timerInterrupts.v module timer( pclk, nreset, bus_write_en, bus_read_en, bus_addr, bus_write_data, bus_read_data, fabint ); input pclk, nreset, bus_write_en, bus_read_en; input [7:0] bus_addr; input [31:0] bus_write_data; output reg [31:0] bus_read_data; output reg fabint; reg [31:0] compareReg; reg [31:0] counterReg; reg [31:0] controlReg; reg [31:0] overflowReg; reg overflowReset; //Resets counterReg when new overflow value is written wire timerEn; //Timer Enable wire interruptEn; //Interrupt Enable wire compareEn; //Compare Enable wire overflowEn; //Overflow Enable assign timerEn = controlReg[0]; assign interruptEn = controlReg[1]; assign compareEn = controlReg[2]; assign overflowEn = controlReg[3]; reg [1:0] interrupt_status; reg reset_interrupt; reg timer_interrupt; reg [31:0] nextCounter; always@(posedge pclk) if(~nreset) fabint <= 1'b0; else begin if(timer_interrupt) fabint <= 1'b1; else fabint <= 1'b0; end always@(posedge pclk) if(~nreset) begin overflowReset <= 1'b0; compareReg <= 32'h00000000; overflowReg <= 32'h00000000; controlReg <= 32'h00000000; reset_interrupt <= 1'b0; end else begin if(bus_write_en) begin : WRITE case(bus_addr[4:2]) 3'b000: // Overflow Register begin overflowReset <= 1'b1; overflowReg <= bus_write_data; end 3'b001: // Timer Value, Read Only begin overflowReset <= 1'b0; end 3'b010: // Timer Control begin overflowReset <= 1'b0; controlReg <= bus_write_data; end 3'b011: // Compare Register begin overflowReset <= 1'b0; compareReg <= bus_write_data; end 3'b100: //Interrupt Status, Read Only begin overflowReset <= 1'b0; end 3'b101: //Spare begin end endcase end else if(bus_read_en) begin : READ case(bus_addr[4:2]) 3'b000: // Timer Overflow register begin bus_read_data <= overflowReg; reset_interrupt <= 1'b0; end 3'b001: // Timer Value, Read Only begin bus_read_data <= counterReg; reset_interrupt <= 1'b0; end 3'b010: // Timer Control begin bus_read_data <= controlReg; reset_interrupt <= 1'b0; end 3'b011: //Compare Register begin bus_read_data <= compareReg; reset_interrupt <= 1'b0; end 3'b100: // Interrupt Status begin bus_read_data[31:2] <= 30'd0;; bus_read_data[1:0] <= interrupt_status; reset_interrupt <= 1'b1; end 3'b101: //Spare begin end endcase end else begin overflowReset <= 1'b0; reset_interrupt <= 1'b0; end end always@* nextCounter = counterReg + 1; always@(posedge pclk) if(~nreset) begin counterReg <= 32'd0; timer_interrupt <= 1'b0; interrupt_status <= 2'b00; end else begin if(reset_interrupt)begin interrupt_status <= 2'b00; timer_interrupt <= 1'b0; end else begin if(overflowReset) begin counterReg <= 32'd0; timer_interrupt <= 1'b0; end else if(timerEn) begin if(counterReg == overflowReg) begin counterReg <= 32'd0; if(interruptEn && overflowEn) begin timer_interrupt <= 1'b1; interrupt_status[0] <= 1'b1; end else timer_interrupt <= 1'b0; end else begin if(counterReg == compareReg && interruptEn && compareEn) begin timer_interrupt <= 1'b1; interrupt_status[1] <= 1'b1; end else timer_interrupt <= 1'b0; counterReg <= nextCounter; end end end end endmodule