Files
learnFPGAProject/clockworks.v
2025-11-27 04:28:54 +03:00

141 lines
3.1 KiB
Verilog

/*
* Clockworks includes
* - gearbox to divide clock frequency, used
* to let you observe how the design behaves
* one cycle at a time.
* - PLL to generate faster clock
* - reset mechanism that resets the design
* during the first microseconds because
* reading in Ice40 BRAM during the first
* few microseconds returns garbage !
* (made me bang my head against the wall).
*
* Parameters
* SLOW number of bits of gearbox. Clock divider
* is (1 << SLOW)
*
* Macros
* NEGATIVE_RESET if board's RESET pin goes low on reset
* ICE_STICK if board is an IceStick.
*/
`include "RTL/PLL/femtopll.v"
`ifdef ECP5_EVN
`define NEGATIVE_RESET
`endif
`ifdef ARTY
`define NEGATIVE_RESET
`endif
`ifdef TANGNANO9K
`define NEGATIVE_RESET
`endif
`ifdef PRIMER20K
`define NEGATIVE_RESET
`endif
module Clockworks
(
input CLK, // clock pin of the board
input RESET, // reset pin of the board
output clk, // (optionally divided) clock for the design.
// divided if SLOW is different from zero.
output 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