OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9504|回复: 1

CPLD 数字锁相环

[复制链接]

2

主题

130

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1870
金钱
1870
注册时间
2011-9-16
在线时间
419 小时
发表于 2015-3-16 17:03:36 | 显示全部楼层 |阅读模式
5金钱
最近刚刚开始学习CPLD,需要用到数字锁相环,网上找了段代码,修修改改,总感觉工作不是很正常,请有经验的朋友帮忙看下,不吝赐教。

使用的芯片是ALTRA   MAX3000系列的EPM3064A  64宏单元  开发环境quartus II   编译下载能得到输出,复位也能受控。中心频率781.25KH

注释都是凭自己的理解添加的,也不知道对不对。
以下是代码:

[mw_shl_code=c,true]/*全数字锁相环verilog源代码*/ module DPLL2 (reset,clk,signal_in,signal_out,signal_out2,syn); //锁相环模块,复位 时钟 信号输入 信号输出 同步 parameter para_K=4; //模K参数 //parameter para_N=8; //模N分频参数 input reset; //复位输入端口 input clk; //时钟输入端口 input signal_in; //信号输入端口 output signal_out; //信号输出端口 output signal_out2; //信号输出反相端口 output syn; //同步信号输出端口 reg signal_out; //信号输出寄存器 reg signal_out2; //信号输出寄存器 reg dpout; //相位差信号寄存器 reg delclk; //减时钟信号寄存器 reg addclk; //加时钟信号寄存器 reg add_del_clkout; //加减时钟信号输出 reg [7:0]up_cnt; //8位二进制上下计数器 reg [7:0]down_cnt; //8位二进制上下计数器 reg [2:0]cnt8; //8分频计数器,加减脉冲分频计数器 reg [8:0]cnt_N; //N分频计数器,系统时钟经8分频(脉冲加减),再经N分频 reg syn; //同步寄存器 reg dpout_delay; //相位差信号延时,相当于上个时钟周期的时候信号输入与输出的异或值,通过判断与本次的异或值来检测上升沿或下降沿 reg [8:0]cnt_dpout_high; //异或值的高电平计数器 reg [8:0]cnt_dpout_low; //异或值的低电平计数器,当同步时输入信号与输出信号差90度,异或后的信号为1/2输入信号周期占空比50%的 //的方波信号,通过比较高电平与低电平的时间来判断是否同步。 /******phase detector*****/ //相位检测 always@(signal_in or signal_out) //信号输入或信号输出 begin dpout<=signal_in^signal_out; //相位比较值等于信号输入与信号输出异或 end /******synchronization establish detector*****/ //同步建立检测 always@(posedge clk or negedge reset) //在时钟上升沿或复位下降沿 begin if(!reset) dpout_delay<='b0; //如果复位为0,输出相位差延迟等于二进制0 else dpout_delay<=dpout; //否则,输出相位比较延迟等于检测到的相位比较值,把异或值延迟一个时钟周期,用于判定异或信号的边沿 end always@(posedge clk or negedge reset) //在时钟上升沿或复位下降沿 begin if(!reset) //如果复位 begin cnt_dpout_high<='b0; cnt_dpout_low<='b0; //异或值的高电平计数器为0,异或值的低电平计数器为0 //如果复位,同步信号清零 end else if(dpout) //如果本次测试相位差为高电平 if(dpout_delay==0) //如果上次测得相位差为低电平,即异或值的上升沿 cnt_dpout_high<='b0; //异或值的高电平计数器清零,高电平计数开始 else if(cnt_dpout_high==8'b11111111) cnt_dpout_high<='b0; //如果相位差高计数器等于255,异或值的高电平计数器清零避免数据溢出 else cnt_dpout_high<=cnt_dpout_high+1; //否则异或值的高电平计数器累加一 else if(!dpout) //如果本次次测试得到相位差为低电平 if(dpout_delay==1) cnt_dpout_low<='b0; //如果上次测得相位差为高电平,异或值的低电平计数器等于0,低电平计数开始 else //否则 if(cnt_dpout_low==8'b11111111) cnt_dpout_low<='b0; //如果异或值的低电平计数器等于255,异或值的低电平计数器清零避免数据溢出 else cnt_dpout_low<=cnt_dpout_low+1; //否则异或值的低电平计数器累加一 end always@(posedge clk or negedge reset) //自时钟上升沿或复位下降沿 begin if(!reset) syn<='b0; //如果复位,同步信号清零 else if((dpout&&!dpout_delay)||(!dpout&&dpout_delay)) //如果相位差与上 相位差累计取反 或 相位差取反与上 相位差累计 if(cnt_dpout_high[8:0]-cnt_dpout_low[8:0]<=4) syn<='b1; //else if(cnt_dpout_low[8:0]-cnt_dpout_high[8:0]<=4) syn<='b1; //如果相位差计数器高减相位差计数器低等于相位差计数器低减相位差计数器高等于4 同步信号等于1 else syn<='b0; //否则同步信号等于0 不同步 end /****up down couter with mod=K****/ //模K加减计数器 always@(posedge clk or negedge reset) //在时钟上升沿或复位下降沿 begin if(!reset) begin //如果低电平复位 delclk<='b0; //减时钟等于0 addclk<='b0; //加时钟等于0 up_cnt<='b00000000; //加减计数器清零 down_cnt<='b0; end else //否则 begin if(!dpout) //如果异或值为低电平 begin delclk<='b0; //减时钟等于0 if(up_cnt==para_K-1) //如果加减计数器等于4-1,相当于计数器满,超出预设模值 begin up_cnt<='b00000000; //加减计数器等于0,清零 addclk<='b1; //加时钟等于1,输出进位脉冲 end else //否则 begin up_cnt<=up_cnt+1; //加减计数器等于加减计数器加1 addclk<='b0; //加时钟等于0 end end else begin addclk<='b0; //加时钟等于0 if(down_cnt=='b0) //如果加减计数器等于0 begin down_cnt<=para_K-1; //加减计数器等于4-1 delclk<='b0; //减时钟等于0 end else if(down_cnt==1) //如果加减计数器等于1 begin delclk<='b1; //减时钟等于1,输出借位脉冲 down_cnt<=down_cnt-1; //加减计数器等于加减计数器减一 end else down_cnt<=down_cnt-1; //加减计数器等于加减计数器减 delclk<='b0; end end end /******add and delete clk*****/ //8分频计数器内进行加减时钟操作 always@(posedge clk or negedge reset) //在时钟上升沿或复位下降沿 begin if(!reset) //如果复位 begin cnt8<='b000; //8分频计数器清零 end else begin if(cnt8=='b111) //8分频计数器等于7,相当于计数满。 begin cnt8<='b000; //8分频计数器等于0,清零 end else if(addclk&&!syn) //如果加时钟与不同步 begin cnt8<=cnt8+2; //8分频计数器等于8分频计数器加2(相当于减了一个脉冲) 1+1+1(+2)+1+1+1=7个CLK时间 频率升高 end else if(delclk&&!syn) //如果减时钟与不同步 cnt8<=cnt8; //8分频计数器值保持不变(相当于加一个脉冲)1+1+1+1+1(+1)+1+1=9个CLK时间 else cnt8<=cnt8+1; //否则8分频计数器等于8分频计数器加一(相当于8分频计数器按正常时钟累加)1+1+1+1+1+1+1+1=8个CLK时间 end end always@(cnt8 or reset) begin if(!reset) //如果复位 add_del_clkout<='b0; //加减计数器等于0 else add_del_clkout<=cnt8[2]; //加减计数器等于8计数器(3位)(最大值7) end /******counter with mod=N******/ //模N分频计数器(分频数为para—N,时钟源为posedge add_del_clkout,以及负跳变沿复位信号) always@(posedge add_del_clkout or negedge reset) //在加减计数器上升沿或复位下降沿 begin if(!reset) //如果复位 begin cnt_N<='b0000; //分频计数器N等于0 signal_out<='b0; //信号输出等于0(地点平) signal_out2<='b0; end else //否则 begin if(cnt_N==7) //如果分频计数器等于15,相当于计数到了16(从0开始) begin cnt_N<='b0000; //分频计数器清零 signal_out<='b0; //信号输出等于低电平 signal_out2<='b1; end else //否则 if(cnt_N==3) //如果分频计数器等于参数16-1除以2,相当于计数到了7,即16的一半。 begin signal_out<='b1; //信号输出等于高电平 signal_out2<='b0; cnt_N<=cnt_N+1; //分频计数器累加1 end else //否则 cnt_N<=cnt_N+1; //分频计数器累加一 end end endmodule //DPLL由 鉴相器 模K加减计数器 脉冲加减电路 同步建立侦察电路 模N分频器 构成. //整个系统的中心频率(即signal_in和signal_out的码速率的2倍) //为clk/8/N. 模K加减计数器的K值决定DPLL的精度和同步建立时间,K越大,则同步建立时间长,同步精度高.反之则短,低. [/mw_shl_code]



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2015-3-16 17:03:37 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-23 05:01

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表