blob: 6ae9721c97d1ff7d1d3f14090a96b038214de0f8 [file] [log] [blame]
/*
* sysmgr.v
*
* vim: ts=4 sw=4
*
* System Clock / Reset generation
*
* Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
* SPDX-License-Identifier: CERN-OHL-S-2.0
*/
`default_nettype none
module sysmgr (
input wire clk_in,
input wire rst_in,
output wire clk_sys,
output wire rst_sys,
output wire clk_48m,
output wire rst_48m
);
// Signals
wire pll_lock;
wire pll_reset_n;
wire clk_30m72_i;
wire rst_30m72_i;
wire clk_48m_i;
reg rst_48m_i;
reg [3:0] rst_cnt;
// Global input buffer for 30.72 MHz clock
SB_GB_IO #(
.PIN_TYPE(6'b000001),
) gb_in (
.PACKAGE_PIN(clk_in),
.GLOBAL_BUFFER_OUTPUT(clk_30m72_i),
);
// PLL instance
SB_PLL40_CORE #(
.DIVR(4'b0000),
.DIVF(7'b0011000),
.DIVQ(3'b100),
.FILTER_RANGE(3'b011),
.FEEDBACK_PATH("SIMPLE"),
.DELAY_ADJUSTMENT_MODE_FEEDBACK("FIXED"),
.FDA_FEEDBACK(4'b0000),
.SHIFTREG_DIV_MODE(2'b00),
.PLLOUT_SELECT("GENCLK"),
.ENABLE_ICEGATE(1'b0),
) pll_I (
.REFERENCECLK(clk_30m72_i),
.PLLOUTCORE(),
.PLLOUTGLOBAL(clk_48m_i),
.EXTFEEDBACK(1'b0),
.DYNAMICDELAY(8'h00),
.RESETB(pll_reset_n),
.BYPASS(1'b0),
.LATCHINPUTVALUE(1'b0),
.LOCK(pll_lock),
.SDI(1'b0),
.SDO(),
.SCLK(1'b0)
);
assign clk_sys = clk_30m72_i;
assign clk_48m = clk_48m_i;
// PLL reset generation
assign pll_reset_n = ~rst_in;
// Logic reset generation
always @(posedge clk_30m72_i or negedge pll_lock)
if (!pll_lock)
rst_cnt <= 4'h0;
else if (~rst_cnt[3])
rst_cnt <= rst_cnt + 1;
assign rst_30m72_i = ~rst_cnt[3];
always @(posedge clk_48m or posedge rst_30m72_i)
if (rst_30m72_i)
rst_48m_i <= 1'b1;
else
rst_48m_i <= 1'b0;
SB_GB rst_sys_gbuf_I (
.USER_SIGNAL_TO_GLOBAL_BUFFER(rst_30m72_i),
.GLOBAL_BUFFER_OUTPUT(rst_sys)
);
SB_GB rst_48m_gbuf_I (
.USER_SIGNAL_TO_GLOBAL_BUFFER(rst_48m_i),
.GLOBAL_BUFFER_OUTPUT(rst_48m)
);
endmodule // sysmgr