奇数倍分频有多种实现方法,下面介绍常用的错位异或法的原理:
以下是一个3分频电路的verilog代码:
用testbenchwaveform产生逻辑仿真为:
[img]http://dl.iteye.com/upload/attachment/371630/2395a05a-599f-3ea0-aabc-305491915432.bmp[/img]
[color=darkred][size=medium]总结:这种错位异或法可以推广实现任意的奇数分频:对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发的模N计数,计数到某一选定值(这里俺一般选第一个时钟沿)时进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比非50%的奇数N分频时钟;再者同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相同值时,进行输出时钟翻转,同样经过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数N分频时钟。两个占空比非50%的N分频时钟相或运算,得到占空比为50%的奇数N分频时钟。[/size][/color]
以下是一个7分频电路的verilog代码:
逻辑仿真图为:
[img]http://dl.iteye.com/upload/attachment/371634/df653e6e-eea5-33d2-9ffc-c36bea852973.bmp[/img]
以下是一个3分频电路的verilog代码:
module clk_div_3(clk_in, rst_n, clk_out);
input clk_in;
input rst_n;
output clk_out;
reg [1:0] cnt_p, cnt_n;
reg clk_out_p, clk_out_n;
always @(posedge clk_in) begin
if(!rst_n) begin
cnt_p <= 0;
clk_out_p <= 0;
end
else begin
if(cnt_p == 2'b10)begin
cnt_p <= 2'b00;
clk_out_p <= clk_out_p;
end
else begin
cnt_p <= cnt_p + 1;
clk_out_p <= ~clk_out_p;
end
end
end
always @(negedge clk_in) begin
if(!rst_n) begin
cnt_n <= 0;
clk_out_n <= 0;
end
else begin
if(cnt_n == 2'b10)begin
cnt_n <= 2'b00;
clk_out_n <= clk_out_n;
end
else begin
cnt_n <= cnt_n + 1;
clk_out_n <= ~clk_out_n;
end
end
end
assign clk_out = clk_out_p | clk_out_n;
endmodule
用testbenchwaveform产生逻辑仿真为:
[img]http://dl.iteye.com/upload/attachment/371630/2395a05a-599f-3ea0-aabc-305491915432.bmp[/img]
[color=darkred][size=medium]总结:这种错位异或法可以推广实现任意的奇数分频:对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发的模N计数,计数到某一选定值(这里俺一般选第一个时钟沿)时进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比非50%的奇数N分频时钟;再者同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相同值时,进行输出时钟翻转,同样经过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数N分频时钟。两个占空比非50%的N分频时钟相或运算,得到占空比为50%的奇数N分频时钟。[/size][/color]
以下是一个7分频电路的verilog代码:
module clk_div_7(clk_in, rst_n, clk_out);
input clk_in;
input rst_n;
output clk_out;
reg [2:0] cnt_p, cnt_n;
reg clk_out_p, clk_out_n;
always @(posedge clk_in) begin
if(!rst_n) begin
cnt_p <= 0;
clk_out_p <= 0;
end
else begin
if(cnt_p == 3'b110) begin
cnt_p <= 0;
clk_out_p <= clk_out_p;
end
else if(cnt_p == 3'b011) begin
cnt_p <= cnt_p + 1;
clk_out_p = ~clk_out_p;
end
else if(cnt_p == 3'b000) begin
cnt_p <= cnt_p + 1;
clk_out_p = ~clk_out_p;
end
else begin
cnt_p <= cnt_p + 1;
clk_out_p <= clk_out_p;
end
end
end
always @(negedge clk_in) begin
if(!rst_n) begin
cnt_n <= 0;
clk_out_n <= 0;
end
else begin
if(cnt_n == 3'b110) begin
cnt_n <= 0;
clk_out_n <= clk_out_n;
end
else if(cnt_n == 3'b011) begin
cnt_n <= cnt_n + 1;
clk_out_n = ~clk_out_n;
end
else if(cnt_n == 3'b000) begin
cnt_n <= cnt_n + 1;
clk_out_n = ~clk_out_n;
end
else begin
cnt_n <= cnt_n + 1;
clk_out_n <= clk_out_n;
end
end
end
assign clk_out = clk_out_p | clk_out_n;
endmodule
逻辑仿真图为:
[img]http://dl.iteye.com/upload/attachment/371634/df653e6e-eea5-33d2-9ffc-c36bea852973.bmp[/img]