锁相环Verilog设计

  锁相环的设计以verilog程序编写有不同的方式,此次只是简单的进行设计,但与网上的大部分版本不同。

  采用鉴频鉴相器,K模加减计数器,脉冲加减计数器式数控振荡器,小数分频器。

  鉴频鉴相器的程序如下:

 

    

module DPLL_PFD(fin1,fin2,up,down);
input fin1,fin2;
output up,down;
wire reset;
reg up,down;
always@(posedge fin1 or negedge reset )
begin//实现D触发器的功能
if(reset==0) begin up=0; end
else begin up<=1;end
end

always@(posedge fin2 or negedge reset )
begin//实现D触发器的功能
if(reset==0) begin down<=0; end
else begin down<=1;end
end

assign reset=~(up&down);
endmodule

 

  K模加减计数器的设计程序如下

 

module DPLL_2KCOUNT1(up,down,reset,k,kclock,carry,borrow);
output carry,borrow;//输出carry,borrow
input[3:0] k; //输入四比特位k
input reset,kclock;//输入se,reset,kclock
input up,down;
reg[19:0] out;
reg[19:0] mo; //中间变量out,mo
always @(k)
begin
case(k) //给定k,得变模可逆计数器的模mo
4'b0001:mo<=7;
4'b0010:mo<=15;
4'b0011:mo<=31;
4'b0100:mo<=63;
4'b0101:mo<=127;
4'b0110:mo<=255;
4'b0111:mo<=511;
4'b1000:mo<=1023;
4'b1001:mo<=2047;
4'b1010:mo<=4095;
4'b1011:mo<=8191;
4'b1100:mo<=16383;
4'b1101:mo<=32767;
4'b1110:mo<=65535;
4'b1111:mo<=131072;
default:mo<=7;
endcase
end

always @(posedge kclock or negedge reset)
begin
if(reset==0) out<=0;//reset信号
else if(reset==1) //下面行使计数器功能
begin
if(down==1) //se=1,减法计数
begin
if(out!=20'd0) out<=out-20'd1;
else if(out==20'd0) out<=mo-20'd1;
end
else if(up==1)//se=0,加法计数
begin
if(out!=mo) out<=out+20'd1;
else if(out==mo) out<=2;
end
end
end
assign carry=(reset)&up&(out==mo); //carry 信号的输出
assign borrow=(reset)&down&(out==0); //borrow 信号的输出
endmodule

 

  脉冲加减式数控振荡器的设计程序如下:

module DPLL_3count(idclock,inc,dec,idout,reset);
output idout;
input idclock;
input inc,dec;
input reset;
wire Q1, Qn1, Q2, Qn2, Q3, Qn3;
wire Q4, Qn4, Q5, Qn5, Q6, Qn6;
wire Q7, Qn7, Q8, Qn8, Q9, Qn9;
wire D7, D8;
//下面是根据图四对其进行结构描述
FFD FFD1(idclock, reset, dec, Q1, Qn1);
FFD FFD2(idclock, reset, inc, Q2, Qn2);
FFD FFD3(idclock, reset, Q1, Q3, Qn3);
FFD FFD4(idclock, reset, Q2, Q4, Qn4);
FFD FFD5(idclock, reset, Q3, Q5,Qn5);
FFD FFD6(idclock, reset, Q4, Q6,Qn6);
assign D7=((Q9 & Qn1 & Q3)|(Q9 & Q5 & Qn3));
assign D8=((Qn9 & Qn2 & Q4)|(Qn9 & Q6 & Qn4));
FFD FFD7(idclock, reset, D7, Q7, Qn7 );
FFD FFD8(idclock, reset, D8, Q8, Qn8);
JK FFJK(idclock, reset, Qn7, Qn8, Q9, Qn9);
assign idout = (!idclock)&Q9; //idout输出
endmodule

 

脉冲加减计数器中应用的D触发器

module FFD(idclock,reset,a,b,c);
input idclock,reset,a;
output b,c;
reg b,c;

always@(posedge idclock or negedge reset or posedge a or posedge b)
begin//实现D触发器的功能
if(reset==0) begin b<=0;c<=1; end
else begin b<=a;c<=(~a);end
end
endmodule

      脉冲加减计数器中应用的JK触发器

module JK(idclock,reset,j,k,q,qn);
input idclock,reset,j,k;
output q,qn;
reg q,qn;

always@(posedge idclock or negedge reset)
begin//实现JK触发器的功能
if(!reset) begin q<=1'b0 ;qn<='b1;end
else if(reset)
begin
case({j,k})
2'b00: begin q<=q; qn<=qn; end
2'b01: begin q<=1'b0;qn<='b1;end
2'b10: begin q<=1'b1;qn<=1'b0;end
2'b11: begin q<=~q;qn<=~qn; end
endcase
end
end
endmodule

 

  小数分频器,此次是吞脉冲小数分频,整体上实现小数分频

module DPLL_fenpin(N1,F1,reset,clk,clkout4);//此次为任意小数分频
input reset,clk;


wire clkout2;
wire clkout3;
output reg clkout4;
input [3:0]N1;
input [3:0]F1;

reg clkout1;
reg [4:0]cnt;

 

reg delete,clkout;

integer count,count1;
initial
begin
cnt=0;delete=0;
clkout=0;
clkout1=0;
count=0;
count1=0;
end
always@(posedge clk)
begin:control

if(reset==0)
begin
count=0;
delete=0;
end
else
begin
count=count+1;
if(count>=N1)
begin
count=0;
count1=count1+F1;
if(count1>=(10+F1))
begin
delete=0;
count1<=count1-(10+F1);
end
else
delete=1;
end
else delete=1;
end
end
always @(*)
begin
if(delete==0)
clkout=1;
else
clkout=clk;
end
always @(posedge clkout)
begin
if(cnt==(N1-1))
begin
cnt<=0;
end
else
cnt<=cnt+5'd1;
end

always @(posedge clkout)
begin
if(cnt==(N1-1)/2) // N分频器 (N为偶数)
begin
clkout1=~clkout1;
end
else if(cnt==N1-1)
begin
clkout1=~clkout1;
end
end

assign clkout2=clkout; //1的输出
assign clkout3=clkout1;//除1以外的输出

always @(*)
if(N1==1)
clkout4=clkout2;
else
clkout4=clkout3;

endmodule

 

 

顶层模块的设计程序如下:

module DPLL(fin,fout2,kclock50,reset,idout,key_in,key_in1,clkout);
output fin;//输入参考信号
input reset; //复位信号
input kclock50; //4与5时钟 50M
output clkout;
wire [3:0] cnt1;
wire kclock60; //6的时钟 66M
wire kclock80; //7与8的时钟 80M
wire kclock100; //9的时钟 100M
wire kclock30; //2与3的时钟 30M
wire kclock10; //1的时钟 15M
//output kclock6; //环路滤波器的时钟
wire locked;
//input[3:0] k; //K变模的模值
//input keyup;
input key_in;
input key_in1;
output fout2; //分频之后反馈信号
wire kclock; //选择的时钟
output idout; //倍频信号
//output N2;
//output F2;
wire carry,borrow;//进位借位信号
//output up;
//output down;
//output fout1; //吞脉冲信号
wire key_flag;
wire [19:0] cnt;
wire en_cnt;
wire nedge,pedge;
wire [19:0] cnt2;
wire en_cnt1;
wire nedge1,pedge1;
reg [3:0]N;
reg [3:0]F;
wire [3:0]N2;
wire [3:0]F2;
wire key_flag1;
//initial
//begin N=7;F=0;
//end

wire idclock,up,down,fout1,fout3,count,key_state,key_state1;

//时钟产生锁相环
pll0 DPLL0(.areset(!reset),
.inclk0(kclock50),
.c0(kclock30),
.c1(kclock60),
.c2(kclock80),
.c3(kclock100),
.c4(fin),
.locked(locked)
);

 

DPLL_PFD DPLL1(fin,fout2,up,down);//鉴频鉴相器

DPLL_2KCOUNT1 DPLL3(.up(up),
.down(down),
.reset(reset),
.k(4'd2),
.kclock(kclock100),
.carry(carry),
.borrow(borrow)
);// K变模可逆计数器


DPLL_3count DPLL4(kclock,carry,borrow,idout,reset);// 脉冲加减电路

 

//小数分频
DPLL_fenpin DPLL6(.N1(N2),
.F1(F2),
.reset(reset),
.clk(idout),
.clkout4(fout2)
);

endmodule

  建议顶层设计模块自己编程,因为只是添加了锁相环的几个部分,在主程序中海油其他模块,所以自己设计顶层模块较为方便。

  这个程序有多问题,例如小数分频程序会添加噪声,没有滤除,还有用鉴频鉴相器连上了K模加减计数器,可以实现,但没有理论论证的文献。最后要注意的是在testbench 里边加数控振荡器的时钟的时候,一定是2N倍的输入参考信号的频率,否则输出会自己改变,但是波形并不好。但是可以体现出锁相环改变频率,锁定相位的功能。

 

转载于:https://www.cnblogs.com/zzjtry/p/6879528.html

你可能感兴趣的:(锁相环Verilog设计)