aboutsummaryrefslogtreecommitdiff
path: root/rtl/src/verilog/novena_clkmgr.v
blob: 2f8c02f4c60dae9a59b7b600163cca6dc713384d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
`timescale 1ns / 1ps

module novena_clkmgr
	(
		gclk_p, gclk_n,
		reset_mcu_b,
		sys_clk, sys_rst,
		bclk_in, bclk_out
	);
	
		//
		// Ports
		//
	input		wire	gclk_p;			// signal from clock pins
	input		wire	gclk_n;			//
	
	input		wire	reset_mcu_b;	// cpu reset (async)
	
	output	wire	sys_clk;			// buffered system clock output
	output	wire	sys_rst;			// system reset output (sync)
	
	input		wire	bclk_in;			// signal from clock pin
	output	wire	bclk_out;		// buffered clock output
	
	
		//
		// IBUFGDS
		//
	(* BUFFER_TYPE="NONE" *)
	wire gclk;
	
	IBUFGDS IBUFGDS_gclk
	(
		.I		(gclk_p),
		.IB	(gclk_n),
		.O		(gclk)
	);
	

		//
		// DCM
		//
	wire	dcm_reset;		// dcm reset
	wire	dcm_locked;		// output clock valid
	wire	gclk_missing;	// no input clock
	
	clkmgr_dcm dcm
	(
		.CLK_IN1					(gclk),
		.RESET					(dcm_reset),
		.INPUT_CLK_STOPPED	(gclk_missing),
		
		.CLK_OUT1				(sys_clk),
		.CLK_VALID				(dcm_locked)
	);
	
	
		//
		// DCM Reset Logic
		//
		
	/* DCM should be reset on power-up, when input clock is stopped or when the CPU gets reset. */
		
	reg	[15: 0]	dcm_rst_shreg	= {16{1'b1}};	// 16-bit shift register
	
	always @(posedge gclk or negedge reset_mcu_b or posedge gclk_missing)
		//
		if ((reset_mcu_b == 1'b0) || (gclk_missing == 1'b1))	dcm_rst_shreg	<= {16{1'b1}};
		else																	dcm_rst_shreg	<= {dcm_rst_shreg[14:0], 1'b0};
	
	assign dcm_reset = dcm_rst_shreg[15];
	
	
		//
		// System Reset Logic
		//
	
	/* System reset is asserted for 16 cycles whenever DCM aquires lock. */
	
	reg	[15: 0]	sys_rst_shreg	= {16{1'b1}};	// 16-bit shift register
	
	always @(posedge sys_clk or negedge reset_mcu_b or posedge gclk_missing or negedge dcm_locked)
		//
		if ((reset_mcu_b == 1'b0) || (gclk_missing == 1'b1) || (dcm_locked == 1'b0))	sys_rst_shreg	<= {16{1'b1}};
		else if (dcm_locked == 1'b1)																	sys_rst_shreg	<= {sys_rst_shreg[14:0], 1'b0};		
	
	assign sys_rst = sys_rst_shreg[15];
	
	
		//
		// BCLK BUFG
		//
	BUFG BUFG_BCLK
	(
		.I		(bclk_in),
		.O		(bclk_out)
	);
	
	
endmodule