Last visit was: Wed Mar 26, 2025 6:11 pm
It is currently Wed Mar 26, 2025 6:11 pm



 [ 1 post ] 
 Minimal presettable counters 
Author Message

Joined: Tue Sep 03, 2024 6:20 pm
Posts: 31
When it's necessary to time something or generate a delay, the common solution is to create a loadable counter, decrement it, and detect zero. This leads to a very poor resource utilization. For example, let's say you want to generate a pulse every 1 second with a 27MHz clock:
* 25 registers to store the count;
* 25 adders to increment;
* 25 muxes to select preset value or incremented value into the registers;
* a wide lut to detect zero.

There is a better way. All FPGAs allow registers to be settable or resettable. Instead of using an array of plain old registers, we can use the verilog 'generate' statement to create a mix of registers that can be set or reset based on the binary preset value. A single input wire can now preset the register array to the desired value, eliminating a wide mux.

An adder is then constructed in the logic preceding the register, using the carry chain for incrementing. Carry-in triggers the counter, while carry-out indicates overflow (no zero detect or limit-detect needed). If overflow is connected to preset, the counter will run continuously, generating pulses at desired rate.

A side benefit of this is that the logic in front of the register is used exclusively for the carry chain, and may be used as a full adder. For instance, a Program Counter can normally increment, but may jump by adding an offset, and can be preset to a fixed value to handle reset or interrupt.

The following recipe is for Gowin FPGAs (on Xilinx there is a lot more flexibility with phasing mutually-prime SRL16 shift registers, which I will leave for another time).
Code:
//===========================================================================
// A specialized pre/resettable down-counter.  It is compiled with the
// reset count baked in, using flip-flops which clear or set upon restart.
// All I/O logic is positive (1=asserted).
// * Asserting restart input will preset the counter to RESETVAL.
// * The bit WIDTH of the counter will be computed automagically.
// * EN must be asserted for the counter to sense and count pulses. EN may
//   be used anytime to freeze the operation at the next clock, and
//   continue when de-asserted
// * The device may operate as an event counter countdown/up mode sensing
//   input pulses on SENSE (gate/shape them to be one clock wide!).
// * Alternatively, the device can operate in free-running timer mode by
//   pulling EN and SENSE up.
// * DONE output  will pulse high when the counter reaches zero.  The device
//   will continue counting (and will trigger again every full bitwidth count).
// * If DONE is connected to RESTART the device will restart every n clocks,
//   generating pulses at programmed interfvals.
// * If DONE is connected to EN with a simple latch-like circuit, the device
//   will work in one-shot mode.             

module SpecialCounter #(parameter RESETVAL=27000000)
(
    input  clk,
    input  en,
    input sense,
    input restart,
    output  done
);
localparam WIDTH = $clog2(RESETVAL + 1);

initial begin
    $display("Building a counter %d bits wide",WIDTH);
end
  wire [WIDTH-1:0] X;  wire [WIDTH-1:0]sum; wire [WIDTH:0] ca;       
  wire [WIDTH-1:0] B;  wire [WIDTH-1:0] C; // not connected
  genvar i; generate
   for (i = 0; i < WIDTH; i = i + 1) begin : spclctr
     if(~RESETVAL[i])  // zero means set, 1 means reset
        DFFSE flopOne (.Q(X[i]),.D(sum[i]),.CLK(clk),.CE(en),.SET(restart));
     else
        DFFRE flopZero(.Q(X[i]),.D(sum[i]),.CLK(clk),.CE(en),.RESET(restart));
   
     ALU alut(.I0(X[i]), .I1(B[i]),  .I3(C[i]),     //I0 connects to FF output
         .CIN(ca[i]),  .COUT(ca[i+1]),.SUM(sum[i])); //sum goes to FF input
     defparam alut.ALU_MODE=0;
   end
  endgenerate
  assign ca[0] = sense;
  assign done = ca[WIDTH];
endmodule                 


Note that this counter counts up to zero, and its preset value is inverted, which makes it equivalent to a down counter. I just like counting up, because counting down sense and done are inverted.

I think Ken Chapman of KCPSM/Picoblaze fame did something like that.


Sun Sep 29, 2024 9:35 pm
 [ 1 post ] 

Who is online

Users browsing this forum: CCBot and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software