一个时钟周期为10ps,5个时钟周期对应43个时钟周期430ps=0.43ns
第一次尝试写出来的代码,5个周期输出是45个时钟周期450ps。检查后发现问题在于,8分频和9分频一直在进行,count也一直在进行。
正确的思路应该是:在count为1和3时只执行8分频,在count为0,2,4时只执行9分频。
//8.6分频,1个周期扩张成8.6个,也就是5个周期包括43个时钟周期。
//T=8.6 对应于M.N(即M=8|N = 6).
//T也可以表示为 T = M + b/(a+b) 这里的a+b=5
//将M通分,T = ( Ma+(M+1)b )/ a+b,这里我们发现组成小数分频使用了a个M分频和b个M+1分频的整数分频电路。
//这个方法被称作《双模前置小数分频》
//用a个8分频和b个9分频,8a+9b=43,a+b=5,解得a=2,b=3。两次8分频穿插在3次9分频之间,获得更好的分频时钟信号
module xiaoshufd(clk,rst,clkout);
input clk,rst;
output clkout;
reg clkoutr;
assign clkout=clkoutr;
reg [3:0] count;
reg clk2,clk4,clk8;
//parameter n=9;
reg [3:0] count9;
reg clk9;
//先写8分频,用寄存器就可以实现。
always @(posedge clk or negedge rst)
begin
if(!rst)
clk2<=0;
else clk2<=!clk2;//2分频
end
always @(posedge clk2 or negedge rst)
begin
if(!rst)
clk4<=0;
else clk4<=!clk4;//4分频
end
always @(posedge clk4 or negedge rst)
begin
if(!rst)
clk8<=0;
else clk8<=!clk8;//8分频
end
//9分频,用带n的那个程序
always @(posedge clk or negedge rst)
begin
if(!rst)
count9<=0;
else if(count9==8)
count9<=0;
else count9<=count9+3'd1;
end
always @(posedge clk or negedge rst)
begin
if(!rst)
clk9<=0;
else if(count9==4'd0 || count9==4'd1)
clk9<=!clk9;
else clk9<=clk9;
end
//定义输出
always @(posedge clk or negedge rst)
begin
if(!rst)
count<=0;
else if(count==4'd1||count==4'd3)
begin clkoutr<=clk8; count<=count+4'd1; end
else begin clkoutr<=clk9; count<=count+4'd1; end
end
endmodule
修改后的代码为:
//8.6分频,1个周期扩张成8.6个,也就是5个周期包括43个时钟周期。
//T=8.6 对应于M.N(即M=8|N = 6).
//T也可以表示为 T = M + b/(a+b) 这里的a+b=5
//将M通分,T = ( Ma+(M+1)b )/ a+b,这里我们发现组成小数分频使用了a个M分频和b个M+1分频的整数分频电路。
//这个方法被称作《双模前置小数分频》
//用a个8分频和b个9分频,8a+9b=43,a+b=5,解得a=2,b=3。两次8分频穿插在3次9分频之间,获得更好的分频时钟信号
module xiaoshufd(clk,rst,clkout);
input clk,rst;
output clkout;
reg clkoutr;
assign clkout=clkoutr;
reg [3:0] count;
//reg clk2,clk4,clk8;
reg [3:0] count8;
//reg clk9;
reg [3:0] count9;
//reg clk9;
//定义输出
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
count<=4'd0; count8<=4'd0; count9<=4'd0;
end
else if(count==4'd1||count==4'd3)
begin
if(count8<4'd7) begin count8<=count8+4'd1; count9<=4'd0; end
else begin count8<=4'd0; count<=count+4'd1; end
end
else if(count==4'd0||count==4'd2)
begin
if(count9<4'd8) begin count9<=count9+4'd1; count8<=4'd0; end
else begin count9<=4'd0; count<=count+4'd1; end
end
else if(count==4'd4)
if(count9<4'd8) begin count9<=count9+4'd1; count8<=4'd0; end
else begin count9<=4'd0; count<=4'd0; end
end
always @(*)
if(count8==4'd7 || count9==4'd8)
clkoutr=1'b1;
else clkoutr=1'b0;
endmodule
在8分频计数器清零也就是结束,在9分频计数器清零也就是结束时,增加一次count,也就是一个小周期的结束,总共5个小周期组成最后的大周期43个时钟。
学到了always新的用法,加*,后面所有的变量只要改变都会触发这个块。
`timescale 1ps/1ps
module xiaoshufdtest;
reg clk,rst;
wire clkout;
xiaoshufd t1(.clk(clk), .rst(rst), .clkout(clkout));
always #5 clk=~clk;
always
begin
clk=0;rst=1;
#10 rst=0;
#15 rst=1;
// #800 rst=0;
// #900 rst=1;
#2000 $stop;
end
endmodule