module Clockworks 
(
   input  wire CLK,   // clock pin of the board
   input  wire RESET, // reset pin of the board
   output wire clk,   // (optionally divided) clock for the design.
                      // divided if SLOW is different from zero.
   output wire resetn // (optionally timed) negative reset for the design
);               
   parameter SLOW=0;

   generate

/****************************************************

 Slow speed mode.
 - Create a clock divider to let observe what happens.
 - Nothing special to do for reset
 
 ****************************************************/
      if(SLOW != 0) begin
	 // Factor is 1 << slow_bit.
	 // Since simulation is approx. 16 times slower than
	 // actual device we use different factor for bosh.
`ifdef BENCH
   localparam slow_bit=SLOW-4;
`else
   localparam slow_bit=SLOW;
`endif
	 reg [slow_bit:0] slow_CLK = 0;
	 always @(posedge CLK) begin
	    slow_CLK <= slow_CLK + 1;
	 end
	 assign clk = slow_CLK[slow_bit];

`ifdef NEGATIVE_RESET
	 assign resetn = RESET;
`else
	 assign resetn = !RESET;
`endif


/****************************************************

 High speed mode.
 - Nothing special to do for the clock
 - A timer that resets the design during the first
   few microseconds, because reading in Ice40 BRAM 
   during the first few microseconds returns garbage !
   (made me bang my head against the wall).
 
 ****************************************************/
	 
      end else begin 
	
`ifdef CPU_FREQ
        femtoPLL #(
          .freq(`CPU_FREQ)
        ) pll(
           .pclk(CLK),
           .clk(clk)
	);
`else
        assign clk=CLK;
`endif


// Preserve resources on Ice40HX1K (IceStick) with 
// carefully tuned counter (12 bits suffice). 
// For other FPGAs, use larger counter.
`ifdef ICE_STICK
	 reg [11:0] 	    reset_cnt = 0;
`else   
	 reg [15:0] 	    reset_cnt = 0;
`endif   
	 assign resetn = &reset_cnt;

`ifdef NEGATIVE_RESET
	 always @(posedge clk,negedge RESET) begin
	    if(!RESET) begin
	       reset_cnt <= 0;
	    end else begin
	       reset_cnt <= reset_cnt + !resetn;
	    end
	 end
`else   
	 always @(posedge clk,posedge RESET) begin
	    if(RESET) begin
	       reset_cnt <= 0;
	    end else begin
	       /* verilator lint_off WIDTH */
	       reset_cnt <= reset_cnt + !resetn;
	       /* verilator lint_on WIDTH */	       
	    end
	 end
`endif   
      end
   endgenerate

endmodule