/* =============================================================== (C) 2006 Robert Finch All rights reserved. rob@birdcomputer.ca ts_timer.v This source code is free for use and modification for non-commercial or evaluation purposes, provided this copyright statement and disclaimer remains present in the file. If you do modify the code, please state the origin and note that you have modified the code. NO WARRANTY. THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED. The user must assume the entire risk of using the Work. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR. IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR LOSSES RELATING TO SUCH UNAUTHORIZED USE. Time slice can be circumvented by writing the current count register. System time slice timer. One of the beauties of an FPGA is that you can provide customized logic like this, rather than having to spend resources on a generic timer chip. Since the system time-slice is not likely to be modified during system operation it can be "hard-coded". In this case a default time slice of 20 ms is used. Reg. 0 = time slice in ms 1 to 255 (20 on reset) 1 = current count (read/writeable) +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |WISHBONE Datasheet |WISHBONE SoC Architecture Specification, Revision B.3 | |Description: Specifications: +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |General Description: system time slice timer +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Supported Cycles: SLAVE,READ/WRITE | SLAVE,BLOCK READ/WRITE | SLAVE,RMW +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Data port, size: 8 bit |Data port, granularity: 8 bit |Data port, maximum operand size: 8 bit |Data transfer ordering: Little Endian |Data transfer sequencing: Undefined +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Clock frequency constraints: none +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Supported signal list and Signal Name WISHBONE equiv. |cross reference to equivalent ack_o ACK_O |WISHBONE signals adr_i ADR_I() | clk_i CLK_I | dat_i(7:0) DAT_I() | dat_o(7:0) DAT_O() | cyc_i CYC_I | stb_i STB_I | we_i WE_I | +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Special requirements: +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Ref. Spartan3 34 slices 42 4-LUTs 139MHz =============================================================== */ module ts_timer( // WISHBONE / SoC bus interfacing input rst_i, // reset input clk_i, // system clock input cyc_i, // cycle valid input stb_i, // core select output ack_o, // transfer acknowledge input we_i, // write input adr_i, // register address 0 = max count, 1 = status input [7:0] dat_i, // data in output [7:0] dat_o, // data out output vol_o, // volatile register output reg tout ); parameter pLFSR = 17'h169AB; // 1ms assuming 28.636MHz clock // parameter pLFSR = 17'h169F7; // 1ms assuming 25.000MHz clock // parameter pLFSR = 17'h19BAD; // 1ms assuming 40.000MHz clock // parameter pLFSR = 17'h1B6CB; // 1ms assuming 50.000MHz clock parameter pMaxCount = 8'd20; // 20 ms default // A LFSR is used to get a 1 ms period from the input clock. reg [16:0] lfsr; // sufficient up to 100MHz wire ms = lfsr==pLFSR; // millisecond pulse reg [7:0] max_cnt; reg [7:0] cnt; assign vol_o = cyc_i & stb_i & adr_i; assign ack_o = cyc_i & stb_i; assign dat_o = adr_i ? cnt : max_cnt; // Note: on reset the lfsr will contain some random count, // most likely zero. It may take from 0 to 32767 clocks // (1.6 ms) to get into the right sequence, in which case the // first 1 ms period after rst_i probably isn't a ms. // Generally, we don't care at this point because it's a // one time occurrance during the boot sequence. always @(posedge clk_i) lfsr <= {lfsr[15:0],~(lfsr[16]^lfsr[13]^ms)}; always @(posedge clk_i) if (rst_i) begin max_cnt <= pMaxCount; // 20 ms cnt <= pMaxCount; tout <= 0; end else begin tout <= 0; if (ms) begin cnt <= cnt - 1; if (cnt==0) begin cnt <= max_cnt; tout <= 1; end end // register update if (cyc_i & stb_i & we_i) begin if (adr_i) cnt <= dat_i; else max_cnt <= dat_i; end end endmodule