Verilog 锁相环参数动态自动生成,Xilinx MMCM 和 PLL 动态配置频率

news2024/11/15 23:58:53

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_46621272/article/details/130484100


Verilog 锁相环参数动态自动生成,Xilinx MMCM 和 PLL 动态配置频率


文章目录

    • 前言
    • 简介
    • Verilog 代码 pll_cfg_x1.v 自动计算生成 PLL_M、PLL_D、PLL_N
    • Verilog 代码 pll.v
    • Verilog 代码 pll_set.v
    • Verilog 仿真测试激励 pll_cfg_testbench.v
    • Verilog 顶层文件 pll_demo.v
    • 本文中的相关下载链接

前言

  • 本文介绍了Xilinx MMCM 和 PLL 的动态配置的方法
  • Verilog 代码计算生成 PLL_M、PLL_D、PLL_N
  • 动态输出一个自定义频率的时钟
  • 提供 VIVADO 仿真工程下载

简介

  • 本文直接采用 Xilinx MMCM/PLL 原语,没有采用 Clock Wizard IP
  • 模块综合后的电路图

在这里插入图片描述

  • 例化代码
    在这里插入图片描述
  • 动态配置的代码参考了官方的 xapp888 的例程,在文章后面有相关下载的链接
  • verilog 根据频率值(精确到HZ)自动计算 M/N/D 等锁相环参数

Verilog 代码 pll_cfg_x1.v 自动计算生成 PLL_M、PLL_D、PLL_N

  • 本代码经过了一些优化,能在 133MHz 下以较小的时间穷举计算出锁相环的各参数值。
  • 优化后的计算代码可能比较难理解,可以下载本文的VIVADO 仿真工程,在压缩包中有个未优化的原始计算代码(只能跑25MHz)
  • 计算中的约束条件如下

XILINX 7系列PLL时钟的条件约束
FIN 最小 10MHz 最大 800MHz,这个频率越大,最后计算出的频率越精准
FVCO_MIN 最小600MHz
FVCO_MAX 最大1200MHz - 1600MHz FPGA -1,-2,-3 芯片不同的后缀频率不同
PLL_D 输入分频系数,整数,1-106, 输入的分频频率 FIN/PLL_D , (FIN/PLL_D) >= 10MHz
PLL_D 的取值范围整数1-106
FVCO 为锁相环频率,FVCO >= FVCO_MIN && FVCO <= FVCO_MAX
FVCO = (FIN/PLL_D)*PLL_M
PLL_M 是个10bit的变量,是个定点小数,最小分辨率是 0.125
例如 PLL_M = 10’b01_1101_0011 就是 0x1d3/8=467/8=58.375
PLL_M 的取值范围小数 2.0-64.0, 10’b00_0001_0000-10’b10_0000_0000
clk_out 是 PLL 的输出频率,clk_out <= 800MHz
clk_out= FVCO/PLL_N=(FIN/PLL_D)*PLL_M/PLL_N
PLL_N 是输出分频系数
PLL_N 的取值范围整数1.0-128.0,最小分辨率是 0.125
例如 PLL_N = 10’b01_1101_0011 就是 0x1d3/8=467/8=58.375
多个 clk_out 输出是对应有多个 PLL_N,这几个输出共用这同一组 FIN,PLL_M,PLL_D,FVCO 系数

  • pll_cfg_x1.v
// XILINX 7系列PLL时钟的条件约束
// FIN 最小 10MHz 最大 800MHz,这个频率越大,最后计算出的频率越精准
// FVCO_MIN 最小600MHz 
// FVCO_MAX 最大1200MHz - 1600MHz FPGA -1,-2,-3 芯片不同的后缀频率不同
// PLL_D 输入分频系数,整数,1-106, 输入的分频频率  FIN/PLL_D , (FIN/PLL_D) >= 10MHz
// PLL_D 的取值范围整数1-106
// FVCO 为锁相环频率,FVCO >= FVCO_MIN && FVCO <= FVCO_MAX
// FVCO = (FIN/PLL_D)*PLL_M/8
// PLL_M 是个10bit的变量,是个定点小数,最小分辨率是 0.125
// 例如 PLL_M = 10'b01_1101_0011 就是 0x1d3/8=467/8=58.375
// PLL_M 的取值范围小数 2.0-64.0, 10'b00_0001_0000-10'b10_0000_0000
// clk_out 是 PLL 的输出频率,clk_out <= 800MHz
// clk_out= FVCO/PLL_N=(FIN/PLL_D)*PLL_M/PLL_N/8 
// PLL_N 是输出分频系数
// PLL_N 的取值范围整数1-128
// 多个 clk_out 输出是对应有多个 PLL_N,这几个输出共用这同一组 FIN,PLL_M,PLL_D,FVCO 系数

//在计算频率时,一些 0 误差的计算,结果很快就能输出(不到10ms)//一些频率无法做到 0 误差,只能尽可能的精确。在最糟糕的时候可能会有 600-700ms 的计算时间(100MHz)
module	pll_cfg_x1	#
(
	parameter	iCLK_N		= 1,				///< 输出数量 1-7
	parameter	FVCO_MIN	= 600*1000*1000,	///< XILINX 7 系FPGA FVCO 最小 600MHz
	parameter	FVCO_MAX	= 1440*1000*1000,	///< XILINX 7 系FPGA FVCO 最大频率-1 1200MHz,-2 1440MHz,-3 1600MHz
	parameter	FIN			= 100*1000*1000		///< 100MHz 输入频率
)
(
	input					clk,		//这个时钟是 DRP 参考时钟,和PLL 实际的输入时钟可以不同
										//这个代码中有些乘除法计算,建议用频率较低的时钟
	input					rst_n,
	input					star_cp,	//计算开始,这是个脉冲,高电平有效
	input	[31:0]			fout_freq,		//输出频率的频率值,单位HZ,如果有多个输出,选频率最高的值
	input	[iCLK_N*8-1:0]	divx,		//各路输出的分频比//这是个二维数组
	output	[15:0]			pll_m,		//计算输出结果,倍频值
	output	[15:0]			pll_d,		//计算输出结果,输入分频值
	output	[iCLK_N*16-1:0]	pll_n,		//计算输出结果,输出分频值//这是个二维数组
	output					pll_err,
	output					pll_done
);
//比如输出多个频率,out1=100MHz,out2=300MHz,out3=50MHz,out4=25MHz,
//fout_freq=300_000_000	//300MHz
//divx[07:00]	= fout_freq/out1=300/100=3;	//这必须能整除
//divx[15:08]	= fout_freq/out2=300/300=1;	//这必须能整除
//divx[23:16]	= fout_freq/out3=300/50 =6;	//这必须能整除
//divx[31:24]	= fout_freq/out3=300/25 =12;	//这必须能整除
//divx 的取值范围在 1-128 ,并且 divx * pll_n 必须小于等于 128
//pll_m 输出是个定点小数,二进制保留 3 位。最小颗粒是0.125 
//比如 pll_m 输出 197,这个值实际是 197/8=24.625

//D			=	1~80;
//M			=	2.0~64.0;	//步长0.125
//N			=	1.0~128.0;	//定点小数 iCLK_N==1 时步长为0.125,iCLK_N > 1 时步长为1//( Fin / D )	>= 10*10^6;			//10000000(10MHz)
//Fvco		=	( Fin / D  ) * M;
//fout_freq		=	Fvco/N;

	genvar		n;
	localparam	PLL_IDLE	= 0;
	localparam	PLL_MAX		= 1;
	localparam	PLL_START	= 2;
	localparam	PLL_OK		= 3;
	localparam	PLL_ERROR	= 4;
	localparam	F_MIN		= FVCO_MIN;
	localparam	F_MAX		= FVCO_MAX;
	localparam	PLL_N_STEP	= iCLK_N == 1 ? 1:8;

	reg		[15:0]	p_m		= 16;
	reg		[15:0]	p_n		= 1;
	reg		[15:0]	p_d		= 1;
	reg		[15:0]	s_m;
	reg		[15:0]	s_n;
	reg		[15:0]	s_d;
	reg				p_err	= 0;

	reg		[15:0]	s_m_r;
	reg		[15:0]	s_n_r[iCLK_N-1:0];
	reg		[15:0]	s_d_r;
	wire	[7:0]	divx_i[iCLK_N-1:0];
	
	reg				p_done	= 0;
	reg		[3:0]	st= 0;
	reg		[7:0]	i= 0;
	
	wire	[31:0]	fin_d;
	reg		[37:0]	f_vfo_m;
	reg		[37:0]	f_vfo_n;
	wire	[31:0]	differ_y;
	reg		[31:0]	differ_x = -1;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	wire	[15:0]	f_d_max;
	wire	[15:0]	f_m_max;
	reg		[15:0]	f_n_max;
	reg		[31:0]	fout_mult;

	wire	[31:0]	fd_rom	[255:0];		//建立一个表,用查表法来计算除法
	for(n=1;n<256;n=n+1)
	begin:for_rom_01
		assign	fd_rom[n]	= FIN/n;		//用查表法计算FIN/p_d
	end

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	assign	pll_done	= p_done;
	assign	pll_err		= p_err;

	for(n=0;n<iCLK_N;n=n+1)
	begin:for_xx1	
		assign	divx_i[n]				= divx[(n+1)*8-1:n*8];
		assign	pll_n[(n+1)*16-1:n*16]	= s_n_r[n] > 128*8 ? 128*8:s_n_r[n];
	end

	assign	pll_m		= s_m_r;
	assign	pll_d		= s_d_r;
//	assign	f_vfo_n		= fout_freq/8*p_n;
	assign	fin_d		= fd_rom[p_d];			//用查表法计算//FIN/p_d;
//	assign	f_vfo_m		= fd_rom[p_d]/8*p_m;	//用查表法计算//FIN/p_d/8*p_m;
	assign	differ_y	= f_vfo_m > f_vfo_n ? (f_vfo_m-f_vfo_n):(f_vfo_n-f_vfo_m);

	assign	f_d_max		= FIN/10_000_000;
	assign	f_m_max		= FVCO_MAX/FIN*p_d*8;

	always @(posedge clk)
	begin
		if(rst_n == 0)
		begin
			st			<= PLL_IDLE;
			p_err		<= 0;
			p_done		<= 0;
		end
		else
		case(st)
		PLL_IDLE:
		begin
			f_vfo_n	<= fout_freq;//fout_freq*p_n
			f_vfo_m	<= fin_d/8*16;

			p_d			<= 1;
			p_m			<= 16;
			p_n			<= 8;
			p_done		<= 0;
			differ_x	<= -1;
			f_n_max		<= 8;
			fout_mult	<= fout_freq;
			if(star_cp == 1)
				st		<= PLL_MAX;
		end
		PLL_MAX:
		begin
			if(f_n_max < 128*8 && fout_mult < F_MAX)
			begin
				f_n_max		<= f_n_max + PLL_N_STEP;
				fout_mult	<= fout_mult + fout_freq/8*PLL_N_STEP;
			end
			else
				st			<= PLL_START;
		end
		PLL_START:
		begin
			p_err		<= 0;
			p_done		<= 0;

			if(p_d > 106 || p_d > f_d_max)
				st	<= PLL_ERROR;
			else if(fin_d >= 10*1000*1000 && f_vfo_m >= F_MIN && f_vfo_m <= F_MAX && f_vfo_n >= F_MIN && f_vfo_n <= F_MAX && p_n != 9)
			begin
				if(differ_y < differ_x)
				begin
					s_d			<= p_d;
					s_m			<= p_m;
					s_n			<= p_n;
					differ_x	<= differ_y;
				end
				if(differ_y == 0)
					st	<= PLL_OK;
			end

			if(p_m < 512 && p_m <= f_m_max)
			begin
				p_m	<= p_m + 1;
				f_vfo_m<= f_vfo_m+fin_d/8;
			end
			else
			begin
				p_m		<= 16;
				if(p_n < 128*8 && p_n <= f_n_max)
				begin
					p_n	<= p_n + PLL_N_STEP;
					f_vfo_n	<= f_vfo_n + fout_freq/8*PLL_N_STEP;	//fout_freq*p_n
					f_vfo_m	<= fin_d/8*16;
				end
				else
				begin
					p_n	<= 8;
					f_vfo_n	<= fout_freq;
					f_vfo_m	<= fd_rom[p_d+1]/8*16;
					if(p_d <= 106 && p_d <= f_d_max)
						p_d	<= p_d + 1;
				end
			end
		end
		PLL_OK:
		begin
			st		<= PLL_IDLE;
			p_done	<= 1;
			s_d_r	<= s_d;
			s_m_r	<= s_m;
			for(i=0;i<iCLK_N;i=i+1)
				s_n_r[i]	<= s_n * divx_i[i];
		end
		PLL_ERROR:
		begin
			if(differ_x == 32'hffff_ffff)
			begin
				p_err	<= 1;
				st		<= PLL_IDLE;
			end
			else
				st		<= PLL_OK;
		end
		default:
		begin
			st		<= PLL_IDLE;
			p_done	<= 0;
		end
		endcase
	end

endmodule


Verilog 代码 pll.v

  • 这代码是例化锁相环参数计算和例化 MMCM 动态加载的代码
  • 当输入频率 fout_freq 的值发生变化时,自动启动锁相环参数的计算和加载
module	pll	#
(
	parameter	iCLK_N		= 2,				///< *输出数量 1-7
	parameter	FVCO_MIN	= 600*1000*1000,	//600MHz
	parameter	FVCO_MAX	= 1440*1000*1000,	//-1 1200MHz,-2 1440MHz,-3 1600MHz
	parameter	FIN			= 100*1000*1000		//输入频率100MHz
)
(
	input						drp_clk,
	input						rst_n,
	input	[31:0]				fout_freq,
	input	[iCLK_N*8-1:0]		divx,		//各路输出的分频比列

	input   					clk_in,
    output						pll_locked,
	output  [iCLK_N-1:0]		clk_out
);


	wire	[15:0]			pll_m;
	wire	[15:0]			pll_d;
	wire	[iCLK_N*16-1:0]	pll_n;
	wire					pll_done;
	reg		[31:0]			ss_r1=0;
	reg		[31:0]			ss_r2=0;
	reg						star_cp=0;
////////////////////////////////////////////////////////////////////////////////////////////////
//这段代码,是监测 fout_freq 是否发生变化,变化后产生 star_cp 脉冲,启动 PLL 设置
////////////////////////////////////////////////////////////////////////////////////////////////
	always @(posedge drp_clk)
	begin
		if(rst_n == 0)
		begin
			ss_r1	<= 0;
			ss_r2	<= 0;
		end
		else if(pll_locked == 1)
		begin
			ss_r1	<= fout_freq;
			ss_r2	<= ss_r1;
		end
	end

	always @(posedge drp_clk)
	begin
		if(rst_n == 0)
			star_cp	<= 0;
		else if(ss_r1 != ss_r2)		//监测 fout_freq 发生了变化
			star_cp	<= 1;			//产生 star_cp 脉冲,启动 PLL 设置
		else
			star_cp	<= 0;
	end
////////////////////////////////////////////////////////////////////////////////////////////////
pll_cfg_x1	#
(
	.iCLK_N		(iCLK_N),
	.FVCO_MIN	(FVCO_MIN),
	.FVCO_MAX	(FVCO_MAX),
	.FIN		(FIN)
)
pll_cfg_ux
(
	.clk		(drp_clk),
	.rst_n		(rst_n),
	.star_cp	(star_cp),
	.fout_freq	(fout_freq),
	.divx		(divx),
	.pll_m		(pll_m),
	.pll_d		(pll_d),
	.pll_n		(pll_n),
	.pll_err	(),
	.pll_done	(pll_done)
);

pll_set		#
(
	.iCLK_N		(iCLK_N),
	.iFREQ_IN	(FIN),		///< *输入时钟频率
	.iPLL_M		(297.0),	///< *倍频系数
	.iPLL_D		(5),		///< *输入分频系数
	.iPLL_N0	(5),		///< *输出分频系数
	.iPLL_N1	(5)			///< *输出分频系数

)
pll_set_ux
(
	.star_cp	(pll_done),
	.drp_clk	(drp_clk),
    .clk_in		(clk_in),
	.rst_n		(rst_n),
	.m_pll_n	(pll_n),
	.m_pll_m	(pll_m),
	.m_pll_d	(pll_d),
    .pll_locked	(pll_locked),
	.clk_out	(clk_out)
);

endmodule



Verilog 代码 pll_set.v

  • MMCM 动态加载的代码,主要参考了官方的 xapp888 中的代码
//下面这组缺省的参数是输入100MHz,FVCO=iFREQ_IN/iPLL_D*iPLL_M/8=1250MHz,输出=FVCO/iPLL_N=125MHz
module	pll_set		#
(
	parameter	iFREQ_IN	= 100*1000*1000,		///< *输入时钟频率
	parameter	iPLL_M		= 400.0,				///< *倍频系数
	parameter	iPLL_D		= 4,					///< *输入分频系数
	parameter	iPLL_N0		= 10,					///< *输出分频系数
	parameter	iPLL_N1		= 64,					///< *输出分频系数
	parameter	iPLL_N2		= 64,					///< *输出分频系数
	parameter	iPLL_N3		= 64,					///< *输出分频系数
	parameter	iPLL_N4		= 64,					///< *输出分频系数
	parameter	iPLL_N5		= 64,					///< *输出分频系数
	parameter	iPLL_N6		= 64,					///< *输出分频系数
	parameter	iCLK_N		= 1						///< *输出数量
)
(
	input					star_cp,
	input   				drp_clk,
    input   				clk_in,
	input   				rst_n,
	input   [iCLK_N*16-1:0]	m_pll_n,
	input   [15:0]			m_pll_m,
	input   [15:0]			m_pll_d,
    output					pll_locked,
	output	[iCLK_N-1:0]	clk_out
);

	parameter	BANDWIDTH	= "OPTIMIZED";	//// "HIGH", "LOW" or "OPTIMIZED"	"LOW_SS"
	genvar	n;

	wire	[15:0]		m_clkout_d[6:0];

	for(n=0;n<7;n=n+1)
	begin:for_md0
		if(n < iCLK_N)
			assign	m_clkout_d[n]	= m_pll_n[(n+1)*16-1:n*16];
		else
			assign	m_clkout_d[n]	= 128*8;
	end
	

	// These signals are used as direct connections between the MMCM_ADV and the
	// MMCM_DRP.
	(* mark_debug = "true" *)	wire	[15:0]	di;
	(* mark_debug = "true" *)	wire	[6:0]	daddr;
	(* mark_debug = "true" *)	wire	[15:0]	dout;
	(* mark_debug = "true" *)	wire			den;
	(* mark_debug = "true" *)	wire			dwe;
	wire			dclk;
	wire			rst_mmcm;
	wire			drdy;
	wire			locked;

	wire			clkfb_bufgout;
	wire			clkfb_bufgin;

	wire	[6:0]	clk_bufgin;

    assign          pll_locked  = locked;


	BUFR BUFG_FB
	(
		.O(clkfb_bufgout),
		.I(clkfb_bufgin)
	);
	for(n=0;n<iCLK_N;n=n+1)
	begin:for_bufg
		BUFG BUFG_CLK0
		(
			.O(clk_out[n]),
			.I(clk_bufgin[n])
		);
	end


	// MMCM_ADV that reconfiguration will take place on
	MMCME2_ADV	#
	(
		// "HIGH", "LOW" or "OPTIMIZED"
		.BANDWIDTH				(BANDWIDTH),
		.DIVCLK_DIVIDE			(iPLL_D),			// (1 to 106)
		.CLKFBOUT_MULT_F		(iPLL_M/8),			// (2 to 64)
		.CLKFBOUT_PHASE			(0.0),
		.CLKFBOUT_USE_FINE_PS	("FALSE"),
		// Set the clock period (ns) of input clocks
		.CLKIN1_PERIOD			(1000*1000*1000/iFREQ_IN),
		.REF_JITTER1			(0.0),
		.CLKIN2_PERIOD			(10.000),
		.REF_JITTER2			(0.0),

		// CLKOUT parameters:
		// DIVIDE: (1 to 128)
		// DUTY_CYCLE: (0.01 to 0.99) - This is dependent on the divide value.
		// PHASE: (0.0 to 360.0) - This is dependent on the divide value.
		// USE_FINE_PS: (TRUE or FALSE)

		.CLKOUT0_DIVIDE_F		(iPLL_N0),
		.CLKOUT0_DUTY_CYCLE		(0.5),
		.CLKOUT0_PHASE			(0.0),
		.CLKOUT0_USE_FINE_PS	("FALSE"),

		.CLKOUT1_DIVIDE			(iPLL_N1),
		.CLKOUT1_DUTY_CYCLE		(0.5),
		.CLKOUT1_PHASE			(0.0),
		.CLKOUT1_USE_FINE_PS	("FALSE"),

		.CLKOUT2_DIVIDE			(iPLL_N2),
		.CLKOUT2_DUTY_CYCLE		(0.5),
		.CLKOUT2_PHASE			(0.0),
		.CLKOUT2_USE_FINE_PS	("FALSE"),

		.CLKOUT3_DIVIDE			(iPLL_N3),
		.CLKOUT3_DUTY_CYCLE		(0.5),
		.CLKOUT3_PHASE			(0.0),
		.CLKOUT3_USE_FINE_PS	("FALSE"),

		.CLKOUT4_DIVIDE			(iPLL_N4),
		.CLKOUT4_DUTY_CYCLE		(0.5),
		.CLKOUT4_PHASE			(0.0),
		.CLKOUT4_USE_FINE_PS	("FALSE"),
		.CLKOUT4_CASCADE		("FALSE"),

		.CLKOUT5_DIVIDE			(iPLL_N5),
		.CLKOUT5_DUTY_CYCLE		(0.5),
		.CLKOUT5_PHASE			(0.0),
		.CLKOUT5_USE_FINE_PS	("FALSE"),

		.CLKOUT6_DIVIDE			(iPLL_N6),
		.CLKOUT6_DUTY_CYCLE		(0.5),
		.CLKOUT6_PHASE			(0.0),
		.CLKOUT6_USE_FINE_PS	("FALSE"),

		// Misc parameters
		.COMPENSATION			("ZHOLD"),
		.STARTUP_WAIT			("FALSE")
	)
	mmcme2_test_inst
	(
		.CLKFBOUT				(clkfb_bufgin),
		.CLKFBOUTB				(),

		.CLKFBSTOPPED			(),
		.CLKINSTOPPED			(),

		// Clock outputs
		.CLKOUT0				(clk_bufgin[0]),
		.CLKOUT0B				(),
		.CLKOUT1				(clk_bufgin[1]),
		.CLKOUT1B				(),
		.CLKOUT2				(clk_bufgin[2]),
		.CLKOUT2B				(),
		.CLKOUT3				(clk_bufgin[3]),
		.CLKOUT3B				(),
		.CLKOUT4				(clk_bufgin[4]),
		.CLKOUT5				(clk_bufgin[5]),
		.CLKOUT6				(clk_bufgin[6]),

		// DRP Ports
		.DO						(dout),				// (16-bits)
		.DRDY					(drdy),
		.DADDR					(daddr),			// 5 bits
		.DCLK					(dclk),
		.DEN					(den),
		.DI						(di),				// 16 bits
		.DWE					(dwe),

		.LOCKED					(locked),
		.CLKFBIN				(clkfb_bufgout),

		// Clock inputs
		.CLKIN1					(clk_in),
		.CLKIN2					(),
		.CLKINSEL				(1'b1),

		// Fine phase shifting
		.PSDONE					(),
		.PSCLK					(1'b0),
		.PSEN					(1'b0),
		.PSINCDEC				(1'b0),

		.PWRDWN					(1'b0),
		.RST					(rst_mmcm)
	);

	clock_mmcme2_drp	#
	(
		.S1_BANDWIDTH		(BANDWIDTH)	// "HIGH", "LOW" or "OPTIMIZED"	"LOW_SS"
	)
	mmcme2_drp_inst
	(
	
		.s1_clkfbout_mult	(m_pll_m),
		.s1_divclk_divide	(m_pll_d),
		.s1_clkout0_divide	(m_clkout_d[0]),
		.s1_clkout1_divide	(m_clkout_d[1]),
		.s1_clkout2_divide	(m_clkout_d[2]),
		.s1_clkout3_divide	(m_clkout_d[3]),
		.s1_clkout4_divide	(m_clkout_d[4]),
		.s1_clkout5_divide	(m_clkout_d[5]),
		.s1_clkout6_divide	(m_clkout_d[6]),
			
		.drp_den			(star_cp),
		.drp_sclk			(drp_clk),
		.drp_rst_n			(rst_n),
		.drp_srdy			(),
	//////////////////////////////////////////////////////////////////////////////////////////////////
		.DO					(dout),
		.DRDY				(drdy),
		.LOCKED				(locked),
		.DWE				(dwe),
		.DEN				(den),
		.DADDR				(daddr),
		.DI					(di),
		.DCLK				(dclk),
		.RST_MMCM			(rst_mmcm)
	);


endmodule

module clock_mmcme2_drp	#
(
		parameter S1_BANDWIDTH  			= "LOW"		// "HIGH", "LOW" or "OPTIMIZED"	"LOW_SS"

)
(
		input	[15:0]	s1_clkfbout_mult,
		input	[15:0]	s1_divclk_divide,
		input	[15:0]	s1_clkout0_divide,
		input	[15:0]	s1_clkout1_divide,
		input	[15:0]	s1_clkout2_divide,
		input	[15:0]	s1_clkout3_divide,
		input	[15:0]	s1_clkout4_divide,
		input	[15:0]	s1_clkout5_divide,
		input	[15:0]	s1_clkout6_divide,

		
		input			drp_den,
		input			drp_sclk,
		input			drp_rst_n,
		output	reg		drp_srdy,
//////////////////////////////////////////////////////////////////////////////////////////////////
		input	[15:0]			DO,
		input					DRDY,
		input					LOCKED,
		output	reg			DWE,
		output	reg			DEN,
		output	reg [6:0]		DADDR,
		output	reg [15:0]	DI,
		output					DCLK,
		output	reg			RST_MMCM
);

	function [31:0] mmcm_divider
	(
		input	[7:0]	divide		// Max divide is 128
	);

	reg	[6:0]	high_time;
	reg	[6:0]	low_time;
	reg			w_edge;
	reg			no_count;

	begin
		if(divide <= 1)
		begin
			high_time	= 1;
			w_edge		= 0;
			low_time	= 1;
			no_count	= 1;
		end
		else
		begin
			high_time	= divide >> 1;
			w_edge		= divide[0];
			low_time	= divide - high_time;
			no_count	= 0;
		end
		mmcm_divider[31:16] = {8'b0,w_edge,no_count,6'b0};
		mmcm_divider[15:00] = {4'b0,high_time[5:0],low_time[5:0]};
	end
	endfunction

	function [35:0] mmcm_divider_frac
	(
		input [9:0] mult	 // Max mult is 128
	);
		reg  [7:0]     lt_frac;
		reg  [7:0]     ht_frac;
		reg            wf_fall_frac;
		reg            wf_rise_frac;

		reg [15:0]     drp_reg1;
		reg [15:0]     drp_reg2;
		reg  [3:0]     drp_regshared;


	begin
		lt_frac = mult[9:4] - (mult[3:0] <= 9);
		ht_frac = mult[9:4] - (mult[3:0] <= 8);
		wf_fall_frac = ((mult[3:0] >=2) && (mult[3:0] <=9)) || (mult == 'h11);
		wf_rise_frac = (mult[3:0] >=1) && (mult[3:0] <=8);

		drp_regshared[3:0] = { mult[3:1], wf_fall_frac};
		drp_reg2[15:0] = { 1'b0, mult[2:0], 1'b1, wf_rise_frac, 10'h0};
		drp_reg1[15:0] = { 4'b0, ht_frac[5:0], lt_frac[5:0] };
		mmcm_divider_frac[35:0] =   {drp_regshared, drp_reg2, drp_reg1};
	end
	endfunction

	
	wire	[9:0]	lookup_low	[63:0];

	assign	lookup_low[00]	=	10'b0010_1111_00; // 1
	assign	lookup_low[01]	=	10'b0010_1111_00; // 2
	assign	lookup_low[02]	=	10'b0010_1111_00; // 3
	assign	lookup_low[03]	=	10'b0010_1111_00; // 4
	assign	lookup_low[04]	=	10'b0010_0111_00; // ....
	assign	lookup_low[05]	=	10'b0010_1011_00;
	assign	lookup_low[06]	=	10'b0010_1101_00;
	assign	lookup_low[07]	=	10'b0010_0011_00;
	assign	lookup_low[08]	=	10'b0010_0101_00;
	assign	lookup_low[09]	=	10'b0010_0101_00;
	assign	lookup_low[10]	=	10'b0010_1001_00;
	assign	lookup_low[11]	=	10'b0010_1110_00;
	assign	lookup_low[12]	=	10'b0010_1110_00;
	assign	lookup_low[13]	=	10'b0010_1110_00;
	assign	lookup_low[14]	=	10'b0010_1110_00;
	assign	lookup_low[15]	=	10'b0010_0001_00;
	assign	lookup_low[16]	=	10'b0010_0001_00;
	assign	lookup_low[17]	=	10'b0010_0001_00;
	assign	lookup_low[18]	=	10'b0010_0110_00;
	assign	lookup_low[19]	=	10'b0010_0110_00;
	assign	lookup_low[20]	=	10'b0010_0110_00;
	assign	lookup_low[21]	=	10'b0010_0110_00;
	assign	lookup_low[22]	=	10'b0010_0110_00;
	assign	lookup_low[23]	=	10'b0010_0110_00;
	assign	lookup_low[24]	=	10'b0010_0110_00;
	assign	lookup_low[25]	=	10'b0010_1010_00;
	assign	lookup_low[26]	=	10'b0010_1010_00;
	assign	lookup_low[27]	=	10'b0010_1010_00;
	assign	lookup_low[28]	=	10'b0010_1010_00;
	assign	lookup_low[29]	=	10'b0010_1010_00;
	assign	lookup_low[30]	=	10'b0010_1100_00;
	assign	lookup_low[31]	=	10'b0010_1100_00;
	assign	lookup_low[32]	=	10'b0010_1100_00;
	assign	lookup_low[33]	=	10'b0010_1100_00;
	assign	lookup_low[34]	=	10'b0010_1100_00;
	assign	lookup_low[35]	=	10'b0010_1100_00;
	assign	lookup_low[36]	=	10'b0010_1100_00;
	assign	lookup_low[37]	=	10'b0010_1100_00;
	assign	lookup_low[38]	=	10'b0010_1100_00;
	assign	lookup_low[39]	=	10'b0010_1100_00;
	assign	lookup_low[40]	=	10'b0010_1100_00;
	assign	lookup_low[41]	=	10'b0010_1100_00;
	assign	lookup_low[42]	=	10'b0010_1100_00;
	assign	lookup_low[43]	=	10'b0010_1100_00;
	assign	lookup_low[44]	=	10'b0010_1100_00;
	assign	lookup_low[45]	=	10'b0010_1100_00;
	assign	lookup_low[46]	=	10'b0010_1100_00;
	assign	lookup_low[47]	=	10'b0010_0010_00;
	assign	lookup_low[48]	=	10'b0010_0010_00;
	assign	lookup_low[49]	=	10'b0010_0010_00;
	assign	lookup_low[50]	=	10'b0010_0010_00;
	assign	lookup_low[51]	=	10'b0010_0010_00;
	assign	lookup_low[52]	=	10'b0010_0010_00;
	assign	lookup_low[53]	=	10'b0010_0010_00;
	assign	lookup_low[54]	=	10'b0010_0010_00;
	assign	lookup_low[55]	=	10'b0010_0010_00;
	assign	lookup_low[56]	=	10'b0010_0010_00;
	assign	lookup_low[57]	=	10'b0010_0010_00;
	assign	lookup_low[58]	=	10'b0010_0010_00;
	assign	lookup_low[59]	=	10'b0010_0010_00; // ....
	assign	lookup_low[60]	=	10'b0010_0010_00; // 61
	assign	lookup_low[61]	=	10'b0010_0010_00; // 62
	assign	lookup_low[62]	=	10'b0010_0010_00; // 63
	assign	lookup_low[63]	=	10'b0010_0010_00; // 64

	wire	[9:0]	lookup_low_ss	[63:0];

	assign	lookup_low_ss[00]	=	10'b0010_1111_11; // 1
	assign	lookup_low_ss[01]	=	10'b0010_1111_11; // 2
	assign	lookup_low_ss[02]	=	10'b0010_1111_11; // 3
	assign	lookup_low_ss[03]	=	10'b0010_1111_11; // 4
	assign	lookup_low_ss[04]	=	10'b0010_0111_11; // ....
	assign	lookup_low_ss[05]	=	10'b0010_1011_11;
	assign	lookup_low_ss[06]	=	10'b0010_1101_11;
	assign	lookup_low_ss[07]	=	10'b0010_0011_11;
	assign	lookup_low_ss[08]	=	10'b0010_0101_11;
	assign	lookup_low_ss[09]	=	10'b0010_0101_11;
	assign	lookup_low_ss[10]	=	10'b0010_1001_11;
	assign	lookup_low_ss[11]	=	10'b0010_1110_11;
	assign	lookup_low_ss[12]	=	10'b0010_1110_11;
	assign	lookup_low_ss[13]	=	10'b0010_1110_11;
	assign	lookup_low_ss[14]	=	10'b0010_1110_11;
	assign	lookup_low_ss[15]	=	10'b0010_0001_11;
	assign	lookup_low_ss[16]	=	10'b0010_0001_11;
	assign	lookup_low_ss[17]	=	10'b0010_0001_11;
	assign	lookup_low_ss[18]	=	10'b0010_0110_11;
	assign	lookup_low_ss[19]	=	10'b0010_0110_11;
	assign	lookup_low_ss[20]	=	10'b0010_0110_11;
	assign	lookup_low_ss[21]	=	10'b0010_0110_11;
	assign	lookup_low_ss[22]	=	10'b0010_0110_11;
	assign	lookup_low_ss[23]	=	10'b0010_0110_11;
	assign	lookup_low_ss[24]	=	10'b0010_0110_11;
	assign	lookup_low_ss[25]	=	10'b0010_1010_11;
	assign	lookup_low_ss[26]	=	10'b0010_1010_11;
	assign	lookup_low_ss[27]	=	10'b0010_1010_11;
	assign	lookup_low_ss[28]	=	10'b0010_1010_11;
	assign	lookup_low_ss[29]	=	10'b0010_1010_11;
	assign	lookup_low_ss[30]	=	10'b0010_1100_11;
	assign	lookup_low_ss[31]	=	10'b0010_1100_11;
	assign	lookup_low_ss[32]	=	10'b0010_1100_11;
	assign	lookup_low_ss[33]	=	10'b0010_1100_11;
	assign	lookup_low_ss[34]	=	10'b0010_1100_11;
	assign	lookup_low_ss[35]	=	10'b0010_1100_11;
	assign	lookup_low_ss[36]	=	10'b0010_1100_11;
	assign	lookup_low_ss[37]	=	10'b0010_1100_11;
	assign	lookup_low_ss[38]	=	10'b0010_1100_11;
	assign	lookup_low_ss[39]	=	10'b0010_1100_11;
	assign	lookup_low_ss[40]	=	10'b0010_1100_11;
	assign	lookup_low_ss[41]	=	10'b0010_1100_11;
	assign	lookup_low_ss[42]	=	10'b0010_1100_11;
	assign	lookup_low_ss[43]	=	10'b0010_1100_11;
	assign	lookup_low_ss[44]	=	10'b0010_1100_11;
	assign	lookup_low_ss[45]	=	10'b0010_1100_11;
	assign	lookup_low_ss[46]	=	10'b0010_1100_11;
	assign	lookup_low_ss[47]	=	10'b0010_0010_11;
	assign	lookup_low_ss[48]	=	10'b0010_0010_11;
	assign	lookup_low_ss[49]	=	10'b0010_0010_11;
	assign	lookup_low_ss[50]	=	10'b0010_0010_11;
	assign	lookup_low_ss[51]	=	10'b0010_0010_11;
	assign	lookup_low_ss[52]	=	10'b0010_0010_11;
	assign	lookup_low_ss[53]	=	10'b0010_0010_11;
	assign	lookup_low_ss[54]	=	10'b0010_0010_11;
	assign	lookup_low_ss[55]	=	10'b0010_0010_11;
	assign	lookup_low_ss[56]	=	10'b0010_0010_11;
	assign	lookup_low_ss[57]	=	10'b0010_0010_11;
	assign	lookup_low_ss[58]	=	10'b0010_0010_11;
	assign	lookup_low_ss[59]	=	10'b0010_0010_11; // ....
	assign	lookup_low_ss[60]	=	10'b0010_0010_11; // 61
	assign	lookup_low_ss[61]	=	10'b0010_0010_11; // 62
	assign	lookup_low_ss[62]	=	10'b0010_0010_11; // 63
	assign	lookup_low_ss[63]	=	10'b0010_0010_11; // 64

	wire	[9:0]	lookup_high	[63:0];

	assign	lookup_high[00]	=	10'b0010_1111_00; // 1
	assign	lookup_high[01]	=	10'b0100_1111_00; // 2
	assign	lookup_high[02]	=	10'b0101_1011_00; // 3
	assign	lookup_high[03]	=	10'b0111_0111_00; // 4
	assign	lookup_high[04]	=	10'b1101_0111_00; // ....
	assign	lookup_high[05]	=	10'b1110_1011_00;
	assign	lookup_high[06]	=	10'b1110_1101_00;
	assign	lookup_high[07]	=	10'b1111_0011_00;
	assign	lookup_high[08]	=	10'b1110_0101_00;
	assign	lookup_high[09]	=	10'b1111_0101_00;
	assign	lookup_high[10]	=	10'b1111_1001_00;
	assign	lookup_high[11]	=	10'b1101_0001_00;
	assign	lookup_high[12]	=	10'b1111_1001_00;
	assign	lookup_high[13]	=	10'b1111_1001_00;
	assign	lookup_high[14]	=	10'b1111_1001_00;
	assign	lookup_high[15]	=	10'b1111_1001_00;
	assign	lookup_high[16]	=	10'b1111_0101_00;
	assign	lookup_high[17]	=	10'b1111_0101_00;
	assign	lookup_high[18]	=	10'b1100_0001_00;
	assign	lookup_high[19]	=	10'b1100_0001_00;
	assign	lookup_high[20]	=	10'b1100_0001_00;
	assign	lookup_high[21]	=	10'b0101_1100_00;
	assign	lookup_high[22]	=	10'b0101_1100_00;
	assign	lookup_high[23]	=	10'b0101_1100_00;
	assign	lookup_high[24]	=	10'b0101_1100_00;
	assign	lookup_high[25]	=	10'b0011_0100_00;
	assign	lookup_high[26]	=	10'b0011_0100_00;
	assign	lookup_high[27]	=	10'b0011_0100_00;
	assign	lookup_high[28]	=	10'b0011_0100_00;
	assign	lookup_high[29]	=	10'b0011_0100_00;
	assign	lookup_high[30]	=	10'b0011_0100_00;
	assign	lookup_high[31]	=	10'b0011_0100_00;
	assign	lookup_high[32]	=	10'b0011_0100_00;
	assign	lookup_high[33]	=	10'b0011_0100_00;
	assign	lookup_high[34]	=	10'b0011_0100_00;
	assign	lookup_high[35]	=	10'b0011_0100_00;
	assign	lookup_high[36]	=	10'b0011_0100_00;
	assign	lookup_high[37]	=	10'b0011_0100_00;
	assign	lookup_high[38]	=	10'b0011_0100_00;
	assign	lookup_high[39]	=	10'b0011_0100_00;
	assign	lookup_high[40]	=	10'b0011_0100_00;
	assign	lookup_high[41]	=	10'b0010_1000_00;
	assign	lookup_high[42]	=	10'b0010_1000_00;
	assign	lookup_high[43]	=	10'b0010_1000_00;
	assign	lookup_high[44]	=	10'b0010_1000_00;
	assign	lookup_high[45]	=	10'b0010_1000_00;
	assign	lookup_high[46]	=	10'b0111_0001_00;
	assign	lookup_high[47]	=	10'b0111_0001_00;
	assign	lookup_high[48]	=	10'b0100_1100_00;
	assign	lookup_high[49]	=	10'b0100_1100_00;
	assign	lookup_high[50]	=	10'b0100_1100_00;
	assign	lookup_high[51]	=	10'b0100_1100_00;
	assign	lookup_high[52]	=	10'b0110_0001_00;
	assign	lookup_high[53]	=	10'b0110_0001_00;
	assign	lookup_high[54]	=	10'b0101_0110_00;
	assign	lookup_high[55]	=	10'b0101_0110_00;
	assign	lookup_high[56]	=	10'b0101_0110_00;
	assign	lookup_high[57]	=	10'b0010_0100_00;
	assign	lookup_high[58]	=	10'b0010_0100_00;
	assign	lookup_high[59]	=	10'b0010_0100_00; // ....
	assign	lookup_high[60]	=	10'b0010_0100_00; // 61
	assign	lookup_high[61]	=	10'b0100_1010_00; // 62
	assign	lookup_high[62]	=	10'b0011_1100_00; // 63
	assign	lookup_high[63]	=	10'b0011_1100_00; // 64


	wire	[9:0]	lookup_optimized	[63:0];
	
	assign	lookup_optimized[00]	=	10'b0010_1111_00; // 1
	assign	lookup_optimized[01]	=	10'b0100_1111_00; // 2
	assign	lookup_optimized[02]	=	10'b0101_1011_00; // 3
	assign	lookup_optimized[03]	=	10'b0111_0111_00; // 4
	assign	lookup_optimized[04]	=	10'b1101_0111_00; // ....
	assign	lookup_optimized[05]	=	10'b1110_1011_00;
	assign	lookup_optimized[06]	=	10'b1110_1101_00;
	assign	lookup_optimized[07]	=	10'b1111_0011_00;
	assign	lookup_optimized[08]	=	10'b1110_0101_00;
	assign	lookup_optimized[09]	=	10'b1111_0101_00;
	assign	lookup_optimized[10]	=	10'b1111_1001_00;
	assign	lookup_optimized[11]	=	10'b1101_0001_00;
	assign	lookup_optimized[12]	=	10'b1111_1001_00;
	assign	lookup_optimized[13]	=	10'b1111_1001_00;
	assign	lookup_optimized[14]	=	10'b1111_1001_00;
	assign	lookup_optimized[15]	=	10'b1111_1001_00;
	assign	lookup_optimized[16]	=	10'b1111_0101_00;
	assign	lookup_optimized[17]	=	10'b1111_0101_00;
	assign	lookup_optimized[18]	=	10'b1100_0001_00;
	assign	lookup_optimized[19]	=	10'b1100_0001_00;
	assign	lookup_optimized[20]	=	10'b1100_0001_00;
	assign	lookup_optimized[21]	=	10'b0101_1100_00;
	assign	lookup_optimized[22]	=	10'b0101_1100_00;
	assign	lookup_optimized[23]	=	10'b0101_1100_00;
	assign	lookup_optimized[24]	=	10'b0101_1100_00;
	assign	lookup_optimized[25]	=	10'b0011_0100_00;
	assign	lookup_optimized[26]	=	10'b0011_0100_00;
	assign	lookup_optimized[27]	=	10'b0011_0100_00;
	assign	lookup_optimized[28]	=	10'b0011_0100_00;
	assign	lookup_optimized[29]	=	10'b0011_0100_00;
	assign	lookup_optimized[30]	=	10'b0011_0100_00;
	assign	lookup_optimized[31]	=	10'b0011_0100_00;
	assign	lookup_optimized[32]	=	10'b0011_0100_00;
	assign	lookup_optimized[33]	=	10'b0011_0100_00;
	assign	lookup_optimized[34]	=	10'b0011_0100_00;
	assign	lookup_optimized[35]	=	10'b0011_0100_00;
	assign	lookup_optimized[36]	=	10'b0011_0100_00;
	assign	lookup_optimized[37]	=	10'b0011_0100_00;
	assign	lookup_optimized[38]	=	10'b0011_0100_00;
	assign	lookup_optimized[39]	=	10'b0011_0100_00;
	assign	lookup_optimized[40]	=	10'b0011_0100_00;
	assign	lookup_optimized[41]	=	10'b0010_1000_00;
	assign	lookup_optimized[42]	=	10'b0010_1000_00;
	assign	lookup_optimized[43]	=	10'b0010_1000_00;
	assign	lookup_optimized[44]	=	10'b0010_1000_00;
	assign	lookup_optimized[45]	=	10'b0010_1000_00;
	assign	lookup_optimized[46]	=	10'b0111_0001_00;
	assign	lookup_optimized[47]	=	10'b0111_0001_00;
	assign	lookup_optimized[48]	=	10'b0100_1100_00;
	assign	lookup_optimized[49]	=	10'b0100_1100_00;
	assign	lookup_optimized[50]	=	10'b0100_1100_00;
	assign	lookup_optimized[51]	=	10'b0100_1100_00;
	assign	lookup_optimized[52]	=	10'b0110_0001_00;
	assign	lookup_optimized[53]	=	10'b0110_0001_00;
	assign	lookup_optimized[54]	=	10'b0101_0110_00;
	assign	lookup_optimized[55]	=	10'b0101_0110_00;
	assign	lookup_optimized[56]	=	10'b0101_0110_00;
	assign	lookup_optimized[57]	=	10'b0010_0100_00;
	assign	lookup_optimized[58]	=	10'b0010_0100_00;
	assign	lookup_optimized[59]	=	10'b0010_0100_00; // ....
	assign	lookup_optimized[60]	=	10'b0010_0100_00; // 61
	assign	lookup_optimized[61]	=	10'b0100_1010_00; // 62
	assign	lookup_optimized[62]	=	10'b0011_1100_00; // 63
	assign	lookup_optimized[63]	=	10'b0011_1100_00; // 64
	
	wire	[39:0]	lookup	[63:0];

	assign	lookup[00]	=	40'b00110_00110_1111101000_1111101001_0000000001;
	assign	lookup[01]	=	40'b00110_00110_1111101000_1111101001_0000000001;
	assign	lookup[02]	=	40'b01000_01000_1111101000_1111101001_0000000001;
	assign	lookup[03]	=	40'b01011_01011_1111101000_1111101001_0000000001;
	assign	lookup[04]	=	40'b01110_01110_1111101000_1111101001_0000000001;
	assign	lookup[05]	=	40'b10001_10001_1111101000_1111101001_0000000001;
	assign	lookup[06]	=	40'b10011_10011_1111101000_1111101001_0000000001;
	assign	lookup[07]	=	40'b10110_10110_1111101000_1111101001_0000000001;
	assign	lookup[08]	=	40'b11001_11001_1111101000_1111101001_0000000001;
	assign	lookup[09]	=	40'b11100_11100_1111101000_1111101001_0000000001;
	assign	lookup[10]	=	40'b11111_11111_1110000100_1111101001_0000000001;
	assign	lookup[11]	=	40'b11111_11111_1100111001_1111101001_0000000001;
	assign	lookup[12]	=	40'b11111_11111_1011101110_1111101001_0000000001;
	assign	lookup[13]	=	40'b11111_11111_1010111100_1111101001_0000000001;
	assign	lookup[14]	=	40'b11111_11111_1010001010_1111101001_0000000001;
	assign	lookup[15]	=	40'b11111_11111_1001110001_1111101001_0000000001;
	assign	lookup[16]	=	40'b11111_11111_1000111111_1111101001_0000000001;
	assign	lookup[17]	=	40'b11111_11111_1000100110_1111101001_0000000001;
	assign	lookup[18]	=	40'b11111_11111_1000001101_1111101001_0000000001;
	assign	lookup[19]	=	40'b11111_11111_0111110100_1111101001_0000000001;
	assign	lookup[20]	=	40'b11111_11111_0111011011_1111101001_0000000001;
	assign	lookup[21]	=	40'b11111_11111_0111000010_1111101001_0000000001;
	assign	lookup[22]	=	40'b11111_11111_0110101001_1111101001_0000000001;
	assign	lookup[23]	=	40'b11111_11111_0110010000_1111101001_0000000001;
	assign	lookup[24]	=	40'b11111_11111_0110010000_1111101001_0000000001;
	assign	lookup[25]	=	40'b11111_11111_0101110111_1111101001_0000000001;
	assign	lookup[26]	=	40'b11111_11111_0101011110_1111101001_0000000001;
	assign	lookup[27]	=	40'b11111_11111_0101011110_1111101001_0000000001;
	assign	lookup[28]	=	40'b11111_11111_0101000101_1111101001_0000000001;
	assign	lookup[29]	=	40'b11111_11111_0101000101_1111101001_0000000001;
	assign	lookup[30]	=	40'b11111_11111_0100101100_1111101001_0000000001;
	assign	lookup[31]	=	40'b11111_11111_0100101100_1111101001_0000000001;
	assign	lookup[32]	=	40'b11111_11111_0100101100_1111101001_0000000001;
	assign	lookup[33]	=	40'b11111_11111_0100010011_1111101001_0000000001;
	assign	lookup[34]	=	40'b11111_11111_0100010011_1111101001_0000000001;
	assign	lookup[35]	=	40'b11111_11111_0100010011_1111101001_0000000001;
	assign	lookup[36]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[37]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[38]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[39]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[40]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[41]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[42]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[43]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[44]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[45]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[46]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[47]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[48]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[49]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[50]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[51]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[52]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[53]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[54]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[55]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[56]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[57]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[58]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[59]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[60]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[61]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[62]	=	40'b11111_11111_0011111010_1111101001_0000000001;
	assign	lookup[63]	=	40'b11111_11111_0011111010_1111101001_0000000001;

	
	// Make sure the memory is implemented as distributed
	(* ram_style = "distributed" *)
	reg	[38:0]  ram [23:0];
	reg	[7:0]   ram_addr;
	reg	[7:0]   ram_rd_addr	= 255;
	reg	[38:0]  ram_do;
	reg			drp_sen=0;
	reg			next_srdy;

	reg	[5:0]	next_ram_addr;
	reg	[6:0]	next_daddr;
	reg			next_dwe;
	reg			next_den;
	reg			next_rst_mmcm;
	reg	[15:0]	next_di;
	
	reg	[31:0]	s1_clkout0;
	reg	[31:0]	s1_clkout1;
	reg	[31:0]	s1_clkout2;
	reg	[31:0]	s1_clkout3;
	reg	[31:0]	s1_clkout4;
	reg	[31:0]	s1_clkout5;
	reg	[31:0]	s1_clkout5x;
	reg	[31:0]	s1_clkout6;
	reg	[31:0]	s1_clkout6x;
	reg	[31:0]	s1_clkfbout;
	reg	[31:0]	s1_divclk;
	wire	[7:0]	s1_clkfbout_mult_int;
	
	reg	[3:0]	frac_ck0;
	reg	[3:0]	frac_fb;
	
	reg	[39:0]	s1_lock;
	reg	[9:0]	s1_digital_filt;
	assign DCLK = drp_sclk;

	always @ (posedge drp_sclk)
	begin
		if(drp_rst_n == 0)
			ram_rd_addr	<= #1 255;
		else if(drp_den == 1)
			ram_rd_addr	<= #1 0;
		else if(ram_rd_addr != 255)
			ram_rd_addr	<= #1 ram_rd_addr + 1;
	end
   
	always @ (posedge drp_sclk)
	begin
		if(drp_rst_n == 0 || drp_den == 1)
			drp_sen	<= #1 0;
		else if(ram_rd_addr == 32)
			drp_sen	<= #1 1;
		else
			drp_sen	<= #1 0;
	end

	
	assign	s1_clkfbout_mult_int	= s1_clkfbout_mult/8;

	always @ (posedge drp_sclk)
	begin

		{frac_fb,s1_clkfbout}	<= #1 mmcm_divider_frac(s1_clkfbout_mult);

		s1_clkout1	<= #1 mmcm_divider(s1_clkout1_divide/8);
		s1_clkout2	<= #1 mmcm_divider(s1_clkout2_divide/8);
		s1_clkout3	<= #1 mmcm_divider(s1_clkout3_divide/8);
		s1_clkout4	<= #1 mmcm_divider(s1_clkout4_divide/8);
		s1_clkout5x	<= #1 mmcm_divider(s1_clkout5_divide/8);
		s1_clkout6x	<= #1 mmcm_divider(s1_clkout6_divide/8);
		s1_clkout6[15:00]		<= #1 s1_clkout6x[15:0];
		s1_clkout6[31:16]		<= #1 {s1_clkout6x[31:30], frac_fb[3:0],s1_clkout6x[25:16]};

		s1_clkout5[15:00]		<= #1 s1_clkout5x[15:0];
		if(s1_clkout0_divide[2:0] != 0)
		begin
			{frac_ck0,s1_clkout0}	<= #1 mmcm_divider_frac(s1_clkout0_divide);
			s1_clkout5[31:16]		<= #1 {s1_clkout5x[31:30], frac_ck0[3:0],s1_clkout5x[25:16]};
		end
		else
		begin
			s1_clkout0				<= #1 mmcm_divider(s1_clkout0_divide/8);
			s1_clkout5[31:16]		<= #1 s1_clkout5x[31:16];
		end

		s1_divclk	<= #1 mmcm_divider(s1_divclk_divide);

		if(s1_clkfbout_mult_int !=0)
		begin
			s1_digital_filt		<= #1	S1_BANDWIDTH == "LOW"		?	lookup_low		[s1_clkfbout_mult_int-1]:
										S1_BANDWIDTH == "LOW_SS"	?	lookup_low_ss	[s1_clkfbout_mult_int-1]:
										S1_BANDWIDTH == "HIGH"		?	lookup_high		[s1_clkfbout_mult_int-1]:
										S1_BANDWIDTH == "OPTIMIZED" ?	lookup_optimized[s1_clkfbout_mult_int-1]:0;

			s1_lock				<= #1	lookup[s1_clkfbout_mult_int-1];					
		end
		else
		begin
			s1_digital_filt		<= #1	S1_BANDWIDTH == "LOW"		?	lookup_low		[0]:
										S1_BANDWIDTH == "LOW_SS"	?	lookup_low_ss	[0]:
										S1_BANDWIDTH == "HIGH"		?	lookup_high		[0]:
										S1_BANDWIDTH == "OPTIMIZED" ?	lookup_optimized[0]:0;

			s1_lock				<= #1	lookup[0];					
		end
	end

	always @ (posedge drp_sclk)
	begin
		case(ram_rd_addr)
		0:	ram[0]	<= #1 {7'h28, 16'h0000, 16'hffff};				// store the power bits
		1:	ram[1]	<= #1 {7'h08, 16'h1000, s1_clkout0[15:0]};
		2:	ram[2]	<= #1 {7'h09, 16'h8000, s1_clkout0[31:16]};		// store clkout0
		
	  
		3:	ram[3]	<= #1 {7'h0a, 16'h1000, s1_clkout1[15:0]};		// store clkout1
		4:	ram[4]	<= #1 {7'h0b, 16'hfc00, s1_clkout1[31:16]};

		5:	ram[5]	<= #1 {7'h0c, 16'h1000, s1_clkout2[15:0]};		// store clkout2
		6:	ram[6]	<= #1 {7'h0d, 16'hfc00, s1_clkout2[31:16]};

		7:	ram[7]	<= #1 {7'h0e, 16'h1000, s1_clkout3[15:0]};		// store clkout3
		8:	ram[8]	<= #1 {7'h0f, 16'hfc00, s1_clkout3[31:16]};

		9:	ram[9]	<= #1 {7'h10, 16'h1000, s1_clkout4[15:0]};		// store clkout4
		10:	ram[10]	<= #1 {7'h11, 16'hfc00, s1_clkout4[31:16]};

		11:	ram[11]	<= #1 {7'h06, 16'h1000, s1_clkout5[15:0]};		// store clkout5
		12:	ram[12]	<= #1 {7'h07, 16'hc000, s1_clkout5[31:16]};

		13:	ram[13]	<= #1 {7'h12, 16'h1000, s1_clkout6[15:0]};		// store clkout6
		14:	ram[14]	<= #1 {7'h13, 16'hc000, s1_clkout6[31:16]};

		15:	ram[15]	<= #1 {7'h16, 16'hc000, {2'h0, s1_divclk[23:22], s1_divclk[11:0]} };		// store the input divider

		16:	ram[16]	<= #1 {7'h14, 16'h1000, s1_clkfbout[15:0]};		// store feedback
		17:	ram[17]	<= #1 {7'h15, 16'h8000, s1_clkfbout[31:16]};

		18:	ram[18]	<= #1 {7'h18, 16'hfc00, {6'h00, s1_lock[29:20]} };
		19:	ram[19]	<= #1 {7'h19, 16'h8000, {1'b0 , s1_lock[34:30], s1_lock[9:0]} };
		20:	ram[20]	<= #1 {7'h1a, 16'h8000, {1'b0 , s1_lock[39:35], s1_lock[19:10]} };
		
		21:	ram[21]	<= #1 {7'h4e, 16'h66ff,s1_digital_filt[9], 2'h0,s1_digital_filt[8:7], 2'h0,s1_digital_filt[6], 8'h00 };
		22:	ram[22] <= #1 {7'h4f, 16'h666f,s1_digital_filt[5], 2'h0,s1_digital_filt[4:3], 2'h0,s1_digital_filt[2:1], 2'h0, s1_digital_filt[0], 4'h0 };
		default:	ram[ram_rd_addr]	<= #1 0;
		endcase
	end

   // Output the initialized ram value based on ram_addr each clock cycle
	always @ (posedge drp_sclk)
	begin
		ram_do<= #1 ram[ram_addr];
	end

	//**************************************************************************
	// Everything below is associated whith the state machine that is used to
	// Read/Modify/Write to the MMCM.
	//**************************************************************************

	// State Definitions
	localparam	RESTART		= 4'h1;
	localparam	WAIT_LOCK	= 4'h2;
	localparam	WAIT_SEN	= 4'h3;
	localparam	ADDRESS		= 4'h4;
	localparam	WAIT_A_DRDY	= 4'h5;
	localparam	BITMASK		= 4'h6;
	localparam	BITSET		= 4'h7;
	localparam	WRITE		= 4'h8;
	localparam	WAIT_DRDY	= 4'h9;

	// State sync
	reg	[3:0]	current_state	= RESTART;
	reg	[3:0]	next_state		= RESTART;

	// These variables are used to keep track of the number of iterations that
	//    each state takes to reconfigure.
	// STATE_COUNT_CONST is used to reset the counters and should match the
	//    number of registers necessary to reconfigure each state.
	localparam		STATE_COUNT_CONST	= 23;
	reg	[4:0]	state_count			= STATE_COUNT_CONST;
	reg	[4:0]	next_state_count	= STATE_COUNT_CONST;

	// This block assigns the next register value from the state machine below
	always @ (posedge drp_sclk)
	begin
		DADDR		<= #1 next_daddr;
		DWE			<= #1 next_dwe;
		DEN			<= #1 next_den;
		RST_MMCM	<= #1 next_rst_mmcm;
		DI			<= #1 next_di;

		drp_srdy	<= #1 next_srdy;

		ram_addr	<= #1 next_ram_addr;
		state_count	<= #1 next_state_count;
	end

   // This block assigns the next state, reset is syncronous.
	always @(posedge drp_sclk)
	begin
		if(drp_rst_n == 0)
			current_state	<= #1 RESTART;
		else
			current_state	<= #1 next_state;
	end

	always @ (*)
	begin
		// Setup the default values
		next_srdy			= 1'b0;
		next_daddr			= DADDR;
		next_dwe			= 1'b0;
		next_den			= 1'b0;
		next_rst_mmcm		= RST_MMCM;
		next_di				= DI;
		next_ram_addr		= ram_addr;
		next_state_count	= state_count;

		case	(current_state)
		// If RST is asserted reset the machine
		RESTART:
		begin
			next_daddr			= 7'h00;
			next_di				= 16'h0000;
			next_ram_addr		= 6'h00;
			next_rst_mmcm		= 1'b1;
			next_state			= WAIT_LOCK;
		end

		 // Waits for the MMCM to assert LOCKED - once it does asserts SRDY
		WAIT_LOCK:
		begin
			// Make sure reset is de-asserted
			next_rst_mmcm		= 1'b0;
			// Reset the number of registers left to write for the next
			// reconfiguration event.
			next_state_count	= STATE_COUNT_CONST ;
			next_ram_addr		= 8'h00;

			if(LOCKED)
			begin
				// MMCM is locked, go on to wait for the SEN signal
				next_state		= WAIT_SEN;
				// Assert SRDY to indicate that the reconfiguration module is
				// ready
				next_srdy		= 1'b1;
			end
			else
			begin
				// Keep waiting, locked has not asserted yet
				next_state		= WAIT_LOCK;
			end
		end

		// Wait for the next SEN pulse and set the RAM addr appropriately
		//    based on SADDR
		WAIT_SEN:
		begin
			next_ram_addr		= 8'h00;
			if (drp_sen)
			begin
				next_ram_addr	= 8'h00;
				// Go on to address the MMCM
				next_state		= ADDRESS;
			end
			else
			begin
				// Keep waiting for SEN to be asserted
				next_state		= WAIT_SEN;
			end
		end

		// Set the address on the MMCM and assert DEN to read the value
		ADDRESS:
		begin
			// Reset the DCM through the reconfiguration
			next_rst_mmcm		= 1'b1;
			// Enable a read from the MMCM and set the MMCM address
			next_den			= 1'b1;
			next_daddr			= ram_do[38:32];

			// Wait for the data to be ready
			next_state			= WAIT_A_DRDY;
		end

		// Wait for DRDY to assert after addressing the MMCM
		WAIT_A_DRDY:
		begin
			if (DRDY)			// Data is ready, mask out the bits to save
				next_state		= BITMASK;
			else				// Keep waiting till data is ready
				next_state		= WAIT_A_DRDY;
		end

		// Zero out the bits that are not set in the mask stored in ram
		BITMASK:
		begin
			// Do the mask
			next_di				= ram_do[31:16] & DO;
			// Go on to set the bits
			next_state			= BITSET;
		end

		// After the input is masked, OR the bits with calculated value in ram
		BITSET:
		begin
			// Set the bits that need to be assigned
			next_di				= ram_do[15:0] | DI;
			// Set the next address to read from RAM
			next_ram_addr		= ram_addr + 1'b1;
			// Go on to write the data to the MMCM
			next_state			= WRITE;
		end

		// DI is setup so assert DWE, DEN, and RST_MMCM.  Subtract one from the
		//    state count and go to wait for DRDY.
		WRITE:
		begin
			// Set WE and EN on MMCM
			next_dwe			= 1'b1;
			next_den			= 1'b1;

			// Decrement the number of registers left to write
			next_state_count	= state_count - 1'b1;
			// Wait for the write to complete
			next_state			= WAIT_DRDY;
		end

		// Wait for DRDY to assert from the MMCM.  If the state count is not 0
		//    jump to ADDRESS (continue reconfiguration).  If state count is
		//    0 wait for lock.
		WAIT_DRDY:
		begin
			if(DRDY)
			begin
				// Write is complete
				if(state_count > 0)
				// If there are more registers to write keep going
					next_state	= ADDRESS;
				else
				// There are no more registers to write so wait for the MMCM
				// to lock
				next_state		= WAIT_LOCK;
			end
			else
			begin
				// Keep waiting for write to complete
				next_state		= WAIT_DRDY;
			end
		end

		// If in an unknown state reset the machine
		default:
		begin
			next_state = RESTART;
		end
		endcase
	end
endmodule


Verilog 仿真测试激励 pll_cfg_testbench.v


///////////////////////////////////////////////////////////////////////

`timescale 1ns / 100ps

module pll_cfg_testbench;

reg			rst_n;
reg			clk;
parameter CLK_PERIOD	= 20;		//50MHz

initial	begin
	rst_n 		= 0;
	#(10 * CLK_PERIOD)
	rst_n	= 1;
end

initial
	clk = 0;
always
begin
	clk = #(CLK_PERIOD/2.0) ~clk;
end
	
wire	pll_locked;
wire	pll_clk_out0;
wire	pll_clk_out1;

pll_demo	pll_ux1
(
	.sys_clk		(clk),
    .pll_locked		(pll_locked),
	.pll_clk_out0	(pll_clk_out0),
	.pll_clk_out1	(pll_clk_out1)
);
endmodule

Verilog 顶层文件 pll_demo.v


module	pll_demo	#
(
	parameter	iCLK_N		= 1	///< *输出数量 1-7
)
(
	input				sys_clk,
    output				pll_locked,
	output  			pll_clk_out0,
	output  			pll_clk_out1
);

parameter	FVCO_MIN	= 600*1000*1000;	//600MHz
parameter	FVCO_MAX	= 1440*1000*1000;	//-1 1200MHz,-2 1440MHz,-3 1600MHz
parameter	FIN			= 100*1000*1000;

//下面这组缺省的参数是输入100MHz,FVCO=iFREQ_IN/iPLL_D*iPLL_M/8=800MHz,输出=FVCO/iPLL_N=100MHz

wire					drp_clk;
wire					clk_100m;
wire					rst_n;
wire	[31:0]			divx;
wire	[iCLK_N-1:0]	clk_out;
reg		[2:0]			fcnt = 0;

wire	[31:0]			fout_freq[7:0];
assign	fout_freq[0] = 765.432*1000*1000;
assign	fout_freq[1] = 543.210*1000*1000;
assign	fout_freq[2] = 321.098*1000*1000;
assign	fout_freq[3] = 109.876*1000*1000;
assign	fout_freq[4] = 098.765*1000*1000;
assign	fout_freq[5] = 076.543*1000*1000;
assign	fout_freq[6] = 054.321*1000*1000;
assign	fout_freq[7] = 032.109*1000*1000;

assign	divx[7:0]	= 1;
//assign	divx[15:8]	= 1;

assign	pll_clk_out0	= clk_out[0];
assign	pll_clk_out1	= clk_out[1];

clk_wiz_pll_100m pll_u1
(
	.clk_out1	(clk_100m),
	.clk_out2	(drp_clk),
	.locked		(rst_n),
	.clk_in1	(sys_clk)
);
////////////////////////////////////////////////////////////////////////////////////////////////
//在 iCLK_N = 1 时,只有1路输出,计算精度比较高
//在 iCLK_N > 1 时,有多路输出,各路输出的频率必须有个公倍数
//比如输出多个频率,out1=100MHz,out2=300MHz,out3=50MHz,out4=25MHz,
//fout_freq=300_000_000	//300MHz,fout_freq必须选这组频率中的最大的值
//divx[07:00]	= fout_freq/out1=300/100=3;	//这必须能整除
//divx[15:08]	= fout_freq/out2=300/300=1;	//这必须能整除
//divx[23:16]	= fout_freq/out3=300/50 =6;	//这必须能整除
//divx[31:24]	= fout_freq/out4=300/25 =12;//这必须能整除
//divx 的取值范围在 1-128 ,并且 divx * pll_n 必须小于等于 128

pll	#
(
	.iCLK_N		(iCLK_N),	//时钟输出通道数量 1-7
	.FVCO_MIN	(FVCO_MIN),	//600MHz
	.FVCO_MAX	(FVCO_MAX),	//-1 1200MHz,-2 1440MHz,-3 1600MHz
	.FIN		(FIN)		//100MHz
)
pll_ux
(
	.drp_clk			(drp_clk),
	.rst_n				(rst_n),
	.fout_freq			(fout_freq[fcnt]),
	.divx				(divx),

	.clk_in				(clk_100m),
	.pll_locked			(pll_locked),
	.clk_out			(clk_out)
);

reg	[1:0]	locked_r = 0;

always@(posedge	drp_clk)
begin
	if(rst_n == 0)
		locked_r	<= 0;
	else
	begin
		locked_r[0]	<= pll_locked;
		locked_r[1]	<= locked_r[0];
	end
end

always@(posedge	drp_clk)
begin
	if(rst_n == 0)
		fcnt	<= 0;
	else if(locked_r == 2'b10)		//此 DEMO 利用 pll_locked 的下降沿来切换频率值并重新计算锁相环的值
									//在实际应用中,可以在任何时候改变频率的值。
		fcnt	<= fcnt + 1;	
end

endmodule


本文中的相关下载链接

  • XAPP888 例程、文档 Xilinx FPGA 动态重新配置频率
  • Verilog 锁相环参数动态自动生成,Xilinx MMCM 和 PLL 动态配置频率 vivado 仿真工程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/487676.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务器中了勒索病毒,升级后的Malox勒索病毒特征,勒索病毒解密数据恢复

Mallox勒索病毒是网络上较为流行的勒索病毒&#xff0c;但是随着黑客加密技术的不断升级&#xff0c;Mallox勒索病毒的新升级版本Malox勒索病毒已经开始出现。Malox勒索病毒是一种最近在网络上广泛传播的恶意软件&#xff0c;其感染方式多种多样&#xff0c;主要以加密受害人的…

【五一创作】版本控制-从零开始学Git-02 Git中的基本概念与工作流程

前言 前面学习了版本控制系统和分布式版本控制系统-Git的相关入门知识【五一创作】版本控制-从零开始学Git-01什么是Git 一、Git中的最基本概念 注意:.git目录是一个隐藏文件夹&#xff0c;默认不可见,需要设置后才能显示出来。 二、Git状态与结构关系 2.1 三种状态 modif…

Zigbee 无线串口通信模块( DL-22 )

文章目录 一、DL-22简介二、模块配置三、串口通信(透明传输) 一、DL-22简介 DL-22无线串口模块为串口转2.4G无线模块&#xff0c;可以通过无线将两个或者多个串口连接起来。串口发入模块的数据会被模块使用无线发出&#xff0c;收到无线数据的模块会将这个数据使用串口发出&am…

大数据分析案例-基于XGBoost算法构建居民收入分类预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

互联网明厨亮灶智慧监管算法 yolov7

互联网明厨亮灶智慧监管系统基于pythoyolov7网络模型AI视觉图像分析技术&#xff0c;互联网明厨亮灶智慧监管算法模型可以识别人员行为及穿戴是否合规&#xff0c;不穿厨师服、不按要求穿戴厨师帽或者佩戴口罩和手套、行为如违规在后厨抽烟、出现老鼠等情景。近几年来&#xff…

数字化转型导师坚鹏:数字化时代企业管理变革与创新营销

数字化时代企业管理变革与创新营销 课程背景&#xff1a; 很多饮水机企业存在以下问题&#xff1a; 不清楚数字化时代企业面临的机遇与挑战&#xff1f; 不知道如何利用大数据发现问题与机会&#xff1f; 不清楚如何进行精准的数字化营销&#xff1f; 不知道如何进行…

【ChatGPT】ChatGPT+MindShow三分钟生成PPT

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 第一步&#xff1a;获取PPT内容大概&#xff1a; 1.打开ChatGPT镜像 2.向他提问&#xff0c;提问格式如下&#xff0c;主题替换成你想获得的信息。比如某本书的拆解&#xff0c;…

数据可视化第二版-拓展-网约车分析案例

文章目录 数据可视化第二版-拓展-网约车分析案例竞赛介绍 1等奖作品-虾虾蟹蟹哈哈的作品引言&#xff1a;背景度量指标 & 结论过程数据与思考一、数据处理二、大盘存量数据一览1. 分城市关键指标变化情况2. 各项指标相关性分析 三、数量维度分析1. 城市间比较1.1 工作日 vs…

HTML和CSS

1、概述 超文本标记语言&#xff08;HyperText Markup Language&#xff09;简称&#xff1a;HTML&#xff1b;是一种用于创建网页的标准标记语言。HTML 不是一种编程语言&#xff0c;而是一种标记语言&#xff1b;HTML文档也叫做 web 页面。 运行后的浏览器页面 我的第一个标…

鲁大师4月安卓新机性能/流畅榜:ROG游戏手机7摘得性能桂冠 vivo登顶流畅榜

性能榜&#xff1a;ROG 游戏手机7众望所归&#xff0c;摘得性能桂冠 2023年4月的手机市场也是异常火爆&#xff0c;各大厂商纷纷推出自己的旗舰手机。骁龙8 Gen2仍然是厂商们的首选芯片&#xff0c;不论是“小米照相机”、vivo折叠机还是ROG 游戏机&#xff0c;他们都纷纷搭载了…

你不能不知道的string类的基础知识

文章目录 前言string类1. 为什么要学习string类1.1 C语言中的字符串不够好用 2. 标准库中的string类2.1 string类(了解)2.2 string类的常用接口说明2.3 string类对象的容量操作2.4string类对象的访问及遍历操作2.5 string类对象的修改操作2.6 string类非成员函数2.7 vs和g下str…

《花雕学AI》大揭秘:ChatGPT 如何让你的聊天机器人更智能、更有趣、更有用

你是否想过有一个可以和你聊天、陪你玩耍、帮你学习、给你创意的机器人&#xff1f;如果你的答案是肯定的&#xff0c;那么你一定会喜欢 ChatGPT。 ChatGPT 是一个基于 GPT-3 或者 GPT-4 技术的聊天机器人&#xff0c;可以与人类进行自然和流畅的对话。GPT-4 是目前最先进的自…

[Gitops--8]微服务前置中间件部署

微服务前置中间件部署 1. MySQL主从 1.1 创建持久化存储 使用project-admin账号 进入sangomall项目 [存储],[存储卷],sangomall-mysql-master-pvc storageclass创建详见K8s集群中部署KubeSphere 2.1章节 在k8s环境下可以看到这个sc rootks-master:~/yaml# kubectl get sc NA…

Cadence Allegro(1):手动PCB封装制作(以TYPE-C 16Pin为例)

Cadence Allegro 16.6&#xff08;1&#xff09;&#xff1a;手动PCB封装制作&#xff08;以TYPE-C 16Pin为例&#xff09; 前提摘要&#xff1a; PCB设计软件版本&#xff1a; 焊盘设计 &#xff1a;Pad Designer 16.6PCB设计 &#xff1a;PCB Editor 16.6 个人说明&#xf…

【HarmonyOS】自定义组件之ArkUI实现通用标题栏组件

【关键字】 标题栏、常用内置组件整合、ArkUI、自定义组件 1、写在前面 在上一篇文章中我们通过Java语言实现了一个通用的标题栏组件&#xff0c;有需要的可以看下&#xff0c;文章地址&#xff1a; 华为开发者论坛 现在很多朋友都已经转战ArkTS语言了&#xff0c;那么今天…

项目集的定义及管理

一、什么是项目集 项目集是相互关联且被协调管理的项目、子项目集和项目集活动&#xff0c;以便获得分别管理所无法获 得的效益。 以项目集的形式管理项目、子项目集及项目集活动能确保项目集组件的战略和工作计划根据各组 件的成果做出相应调整&#xff0c;或者按照发起组织的…

PWM控制舵机

文章目录 运行环境&#xff1a;1.1 原理1)A板原理图2)PA8引脚配置3)定时器Timers配置 2.1代码解释1)定时器1初始化函数2)启动定时器中断3)启动PWM/设置占空比4)launch设置5) 编译调试 3.1实验效果 运行环境&#xff1a; ubuntu18.04.melodic 宏基暗影骑士笔记本 stm32f427IIH6…

JAVA常用的工具类

文章目录 1 集合工具类1.1 java.util.Collections1.1.1 基本操作1.1.2 转换线程安全集合 1.2 org.springframework.util.CollectionUtils1.3 org.apache.commons.collections.CollectionUtils1.4 org.apache.commons.lang.ArrayUtils1.5 org.apache.commons.lang3.ArrayUtils1.…

[Java] 中的具体集合

文章目录 集合根接口List列表&#xff08;线性表&#xff09;Queue & Deque双端队列 Set集合HashSet源码应用 TreeSet源码 Map映射Map的底层实现HashMapLinkedHashMapTreeMap Maps methodcompute()merge()replace()remove() Stream流Collections工具类 集合表示一组对象&am…

Reactor 第九篇 WebFlux重构个人中心,效果显著

1 重构背景 原有的开发人员早已离职&#xff0c;代码细节没人知道&#xff0c;经过了一段时间的维护&#xff0c;发现有以下问题&#xff1a; 个人中心系统的特征就是组装各个业务的接口&#xff0c;输出个人中心业务需要的数据&#xff0c;整个系统调用了几十个第三方业务线的…