quartus动态配置pll reconfig

一、逻辑部分

1,需要添加两个ip,一个是是,altera_pll_reconfig,这个ip没啥要配的,主要就是搞个avalon总线出来提供寄存器给arm配
2,altera_pll

在这里插入图片描述
在这里插入图片描述
3,代码和连线。其中avalon总线从qsys引出来

pll_reconfig pll_reconfig_uut (
.mgmt_clk            (w_sys_clk_100m  ),//pic_eth_ref_clk
.mgmt_reset          (ncs_reset),
.mgmt_waitrequest    (),
.mgmt_read           (rcf_mgmt_rd_spi),
.mgmt_write          (rcf_mgmt_wr_spi),
.mgmt_readdata       (rcf_mgmt_rdata_spi),
.mgmt_address        (rcf_mgmt_addr_spi),
.mgmt_writedata      (rcf_mgmt_wdata_spi),
.reconfig_to_pll     (reconfig_to_pll_spi),
.reconfig_from_pll   (reconfig_from_pll_spi)
);

pll_10M_reconfig pll_10M_reconfig_uut (
.refclk                (w_sys_clk_100m  ),//pic_eth_ref_clk
.rst                   (ncs_reset),
.outclk_0              (clk_spi),
.locked                (),
.reconfig_to_pll       (reconfig_to_pll_spi),
.reconfig_from_pll     (reconfig_from_pll_spi)
);

二、软件部分

1,逻辑部分比较简单,没啥东西,主要软件如何通过avalon总线来配置这个reconfig ip比较麻烦点。本质是配置ip的144个寄存器,需要啃手册。

2,软件代码
void Pll1FreqReconfig(uint32 freq)
{
	float freqTemp = (float)freq / 1000000;
	int cIntCnt;
	float cFloatCnt;
	float fVco;
	float multiCnt;
	int multiIntPart;
	int multiFracPart;
	int vcoDiv2Enable;
	int finDivBypassen;
	int multiHCnt;
	int multiLCnt;
	int multiOddDiv;
	int nCounter;
	int mCounter;
	int cCounter;
	//计算 cIntCnt,vcoDiv2Enable,multiHCnt,multiLCnt,multiOddDiv
	if((freqTemp < 1) || (freqTemp > 600))
		return;
	else if((freqTemp >= 1) && (freqTemp <= 50))
	{
		cFloatCnt = 200 / freqTemp;
		cIntCnt = (int)cFloatCnt;
		fVco = freqTemp * 4 * cIntCnt;
		vcoDiv2Enable = 1;
		finDivBypassen = 0;
	}
	else if((freqTemp > 50) && (freqTemp <= 600))
	{
		cFloatCnt = 600 / freqTemp;
		cIntCnt = (int)cFloatCnt;
		fVco = freqTemp * 2 * cIntCnt;
		vcoDiv2Enable = 0;
		finDivBypassen = 1;
	}
	multiCnt = fVco / 100;//ref_clk = 100
	multiIntPart = (int)multiCnt;
	multiFracPart = (int)((multiCnt - multiIntPart) * 16777216);
	if (multiIntPart & 0x1)//multiIntPart为奇数
	{
		multiHCnt = (multiIntPart >> 1) + 1;
		multiLCnt = multiIntPart >> 1;
		multiOddDiv = 1;
	}
	else
	{
		multiHCnt = multiIntPart >> 1;
		multiLCnt = multiIntPart >> 1;
		multiOddDiv = 0;
	}
	//寄存器操作 addr:0x00-0x3f
	WritePLL1Reg(PLL1_MODE_REGISTER, 0x1);//set the Altera PLL Reconfg IP core to operate in polling mode
	nCounter = ((finDivBypassen << 16) + 0x0101) & 0x1ffff;
	WritePLL1Reg(PLL1_N_COUNTER, nCounter);//set N counter Bypass or not
	mCounter = ((multiOddDiv << 17) + (0 << 16) + (multiHCnt << 8) + multiLCnt) & 0x3ffff;
	WritePLL1Reg(PLL1_M_COUNTER, mCounter);//reconfgure the M counter
	WritePLL1Reg(PLL1_M_COUNTER_FRACTIONAL_VALUE_K, multiFracPart);//M counter Fractional Value (K) register
	cCounter = ((cIntCnt << 8) + cIntCnt) & 0xffff;
	WritePLL1Reg(PLL1_C_COUNTER, cCounter);//reconfgure the C0 counter
	WritePLL1Reg(PLL1_VCO_DIV_SETTING, vcoDiv2Enable);//Enable or disable /2 divider for VCO
	WritePLL1Reg(PLL1_START_REGISTER, 0x1);//start the reconfguration
	ReadPLL1Reg(PLL1_STATUS_REGISTER);//until a value of 1 is read from the status register, indicating a successful reconfguration
}

枚举

enum
{
	PLL0_MODE_REGISTER,
	PLL0_STATUS_REGISTER,
	PLL0_START_REGISTER,
	PLL0_N_COUNTER,
	PLL0_M_COUNTER,
	PLL0_C_COUNTER,
	PLL0_DYNAMIC_PHASE_SHIFT,
	PLL0_M_COUNTER_FRACTIONAL_VALUE_K,
	PLL0_BANDWIDTH_SETTING,
	PLL0_CHARGE_PUMP_SETTING,
	PLL0_VCO_DIV_SETTING = 0x1c,
	PLL0_MIF_BASE_ADDRESS = 0x1f
};
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值