141 lines
3.1 KiB
Verilog
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
|