使用计数器控制寄存器反转,很容易实现奇数倍分频,但是添加了占空比为50%这一限制条件的话,有些同学就会犯难,因为数字电路不存在小数,而奇数除以二却是一个小数,这导致占空比为50%无法实现。本文将通过图解的方式详细解答这个问题。
解这个题的思路非常简单,就是通过计数器控制两个寄存器实现两个占空比小于50%的奇数倍分频,但是这两个寄存器的时钟控制一个是上升沿触发,一个是下降沿触发,这会导致生成两个相位差为90度的时钟。对这两个时钟进行或运算,就可以得出结果。
Clk_out = Clk_reg1|Clk_reg2。
实现代码
module divfrequency(
clk,
rst_n,
Clk_out
);
input clk;
input rst_n;
output Clk_out;
parameter n = 3'd5;//n为变频数,可以变换
wire Clk_out;
reg clk_reg1;
reg clk_reg2;
reg [2:0]div_cnt;
wire [2:0]a;
wire [2:0]b;
assign a = n>>1;//n>>1相当于除以2然后取整
assign b = n - 1'b1;
always@(posedge clk or negedge rst_n )//计数器
if(!rst_n)
div_cnt <= 0;
else if(div_cnt == b)
div_cnt <= 0;
else
div_cnt <= div_cnt+ 1'b1;
always@(posedge clk or negedge rst_n )//第一个时钟寄存器
if(!rst_n)
clk_reg1 <= 0;
else if(div_cnt == 0)
clk_reg1 <= ~clk_reg1;
else if(div_cnt == a)
clk_reg1 <= ~clk_reg1;
always@(negedge clk or negedge rst_n )//第二个时钟寄存器
if(!rst_n)
clk_reg2 <= 0;
else if(div_cnt == 1) //由于是下降沿触发,而计数器是上升沿触发,故比第一个时钟多1
clk_reg2 <= ~clk_reg2;
else if(div_cnt == a + 1'b1 )//同上
clk_reg2 <= ~clk_reg2;
assign Clk_out = clk_reg1|clk_reg2;
endmodule
测试代码
`define clock_period 20
`timescale 1ns/1ns
module divfrequency_tb;
reg clk;
reg rst_n;
wire Clk_out;
initial
begin
clk = 1;
end
always #(`clock_period/2) clk = ~clk;
divfrequency u0(
clk,
rst_n,
Clk_out
);
initial
begin
rst_n =1;
#(`clock_period)
rst_n = 0;
#(`clock_period)
rst_n = 1;
#(`clock_period*40)
$stop;
end
endmodule
modelsim仿真结果