2022-09-19 02:51:11 -04:00
|
|
|
//======================================================================
|
|
|
|
//
|
2022-09-27 10:41:38 -04:00
|
|
|
// clk_reset_gen.v
|
2022-09-19 02:51:11 -04:00
|
|
|
// -----------
|
2022-09-27 10:41:38 -04:00
|
|
|
// Clock and reset generator used in the Tillitis Key 1 design.
|
|
|
|
// This module instantiate the internal SB_HFOSC clock source in the
|
|
|
|
// Lattice ice40 UP device. It then connects it to the PLL, and
|
|
|
|
// finally connects the output from the PLL to the global clock net.
|
2022-09-19 02:51:11 -04:00
|
|
|
//
|
|
|
|
//
|
|
|
|
// Author: Joachim Strombergson
|
|
|
|
// Copyright (C) 2022 - Tillitis AB
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
//
|
|
|
|
//======================================================================
|
|
|
|
|
|
|
|
`default_nettype none
|
|
|
|
|
2022-09-27 10:41:38 -04:00
|
|
|
module clk_reset_gen #(parameter RESET_CYCLES = 200)
|
|
|
|
(
|
|
|
|
output wire clk,
|
|
|
|
output wire rst_n
|
|
|
|
);
|
2022-09-19 02:51:11 -04:00
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
// Registers with associated wires.
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
reg [7 : 0] rst_ctr_reg = 8'h0;
|
|
|
|
reg [7 : 0] rst_ctr_new;
|
|
|
|
reg rst_ctr_we;
|
|
|
|
|
|
|
|
reg rst_n_reg = 1'h0;
|
|
|
|
reg rst_n_new;
|
|
|
|
|
2022-09-27 10:41:38 -04:00
|
|
|
wire hfosc_clk;
|
|
|
|
wire pll_clk;
|
|
|
|
|
2022-09-19 02:51:11 -04:00
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
// Concurrent assignment.
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
assign rst_n = rst_n_reg;
|
|
|
|
|
|
|
|
|
2022-09-27 10:41:38 -04:00
|
|
|
//----------------------------------------------------------------
|
|
|
|
// Core instantiations.
|
|
|
|
//----------------------------------------------------------------
|
2022-10-06 07:23:30 -04:00
|
|
|
/* verilator lint_off PINMISSING */
|
|
|
|
|
2022-09-27 10:41:38 -04:00
|
|
|
// Use the FPGA internal High Frequency OSCillator as clock source.
|
|
|
|
// 00: 48MHz, 01: 24MHz, 10: 12MHz, 11: 6MHz
|
|
|
|
SB_HFOSC #(.CLKHF_DIV("0b10")
|
2022-10-06 07:23:30 -04:00
|
|
|
) hfosc_inst (.CLKHFPU(1'b1),.CLKHFEN(1'b1),.CLKHF(hfosc_clk));
|
2022-09-27 10:41:38 -04:00
|
|
|
|
|
|
|
|
2022-10-06 07:23:30 -04:00
|
|
|
// Use a PLL to generate a new clock frequency based on the HFOSC clock.
|
2022-10-21 08:33:03 -04:00
|
|
|
//
|
|
|
|
// Given FEEDBACK_PATH=="SIMPLE", clock calculation according to 3.5.2 in
|
|
|
|
// FPGA-TN-02052-1-4-iCE40-sysCLOCK-PLL-Design-User-Guide.pdf
|
|
|
|
// https://www.latticesemi.com/view_document?document_id=47778 follows:
|
|
|
|
//
|
|
|
|
// F_pllout == (F_referenceclk * (DIVF + 1)) / (2^DIVQ * (DIVR + 1))
|
|
|
|
//
|
|
|
|
// Given the 12 MHz HFOSC clock set above, we get a final 18 MHz:
|
|
|
|
//
|
|
|
|
// (12000000 * (47 + 1)) / (2^5 * (0 + 1)) = 18000000
|
2022-09-27 10:41:38 -04:00
|
|
|
SB_PLL40_CORE #(
|
|
|
|
.FEEDBACK_PATH("SIMPLE"),
|
|
|
|
.DIVR(4'b0000), // DIVR = 0
|
|
|
|
.DIVF(7'b0101111), // DIVF = 47
|
|
|
|
.DIVQ(3'b101), // DIVQ = 5
|
|
|
|
.FILTER_RANGE(3'b001) // FILTER_RANGE = 1
|
2022-10-06 07:23:30 -04:00
|
|
|
) pll_inst (
|
2022-09-27 10:41:38 -04:00
|
|
|
.RESETB(1'b1),
|
|
|
|
.BYPASS(1'b0),
|
|
|
|
.REFERENCECLK(hfosc_clk),
|
|
|
|
.PLLOUTCORE(pll_clk)
|
|
|
|
);
|
|
|
|
|
2022-10-06 07:23:30 -04:00
|
|
|
|
|
|
|
// Use a Global Buffer to distribute the clock.
|
|
|
|
SB_GB gb_inst (
|
2022-09-27 10:41:38 -04:00
|
|
|
.USER_SIGNAL_TO_GLOBAL_BUFFER (pll_clk),
|
|
|
|
.GLOBAL_BUFFER_OUTPUT (clk)
|
|
|
|
);
|
|
|
|
|
2022-10-06 07:23:30 -04:00
|
|
|
/* verilator lint_on PINMISSING */
|
|
|
|
|
|
|
|
|
2022-09-19 02:51:11 -04:00
|
|
|
//----------------------------------------------------------------
|
|
|
|
// reg_update.
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
always @(posedge clk)
|
|
|
|
begin : reg_update
|
|
|
|
rst_n_reg <= rst_n_new;
|
|
|
|
|
|
|
|
if (rst_ctr_we)
|
|
|
|
rst_ctr_reg <= rst_ctr_new;
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
// rst_logic.
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
always @*
|
|
|
|
begin : rst_logic
|
|
|
|
rst_n_new = 1'h1;
|
|
|
|
rst_ctr_new = 8'h0;
|
|
|
|
rst_ctr_we = 1'h0;
|
|
|
|
|
|
|
|
if (rst_ctr_reg < RESET_CYCLES) begin
|
|
|
|
rst_n_new = 1'h0;
|
|
|
|
rst_ctr_new = rst_ctr_reg + 1'h1;
|
|
|
|
rst_ctr_we = 1'h1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
endmodule // reset_gen
|
|
|
|
|
|
|
|
//======================================================================
|
|
|
|
// EOF reset_gen.v
|
|
|
|
//======================================================================
|