文章目录

1.占空比2.秒分频计数3.偶数分频4.奇数分频1. 占空比不为50%2. 占空比为50%

5.任意分频

👉声明:本文所使用的的所有代码均已编译并仿真通过,仿真结果附于文中。

👉注:更多精彩请看:

面试常问的verilog代码汇总 一文

1.占空比

占空比:理想的时钟模型是一个占空比为50%且周期固定的方波。时钟周期为T,TH为高脉冲宽度,TL为低脉冲宽度,T=TH+TL。占空比即为高脉冲宽度与周期之比,即TH / T。

2.秒分频计数

假设clk是24MHz系统时钟,秒分频产生s_pulse;秒计数模块对s_pulse计数,计数范围0~9,计数结果s_num的位宽为4 个bit位。 代码如下

module s_count(clk,rst_n,s_num);

input clk,rst_n;

output [3:0]s_num;

//因为24000000需要25位二进制来表达

reg [24:0]con_t;//秒脉冲分频计数

reg s_pulse;//秒脉冲尖

reg [3:0]s_num;

parameter fequency=24;//24MHZ

always@(posedge clk or negedge rst_n)begin

if(!rst_n) begin

con_t <= 0;

s_pulse <= 0;

s_num <= 0;

end

else begin

//时钟频率是24MHz,所以当con_t计数到(24*1000000-1)时,为1秒

if(con_t == fequency*1000000 -1)begin

con_t <= 0;

s_pulse <= 1;

end

else begin

con_t <= con_t + 1;

s_pulse <= 0;

end

end

//每出现一各秒脉冲尖,就计数一次

if(s_pulse == 1)begin

if(s_num == 9) s_num <= 0;//计到9个秒脉冲尖,就清零

else s_num <= s_num + 1;

end

end

endmodule

`timescale 1ns/1ps

module tb_s_count;

reg clk,rst_n;

wire[3:0] s_num;

s_count dut(.clk(clk),.rst_n(rst_n),.s_num(s_num));

initial begin

clk <= 0;

forever begin

#5 clk <= !clk;

end

end

initial begin

#10 rst_n <= 0;

repeat(10) @(posedge clk);

rst_n <= 1;

end

endmodule

仿真结果如下,时间关系,我就没跑完了。

3.偶数分频

偶分频电路指的是分频系数为 2、4、6、8 … 等偶数整数的分频电路 ;

当进行N倍偶数分频,采用计数器计数带分频时钟。当计数器从**0计数到 N/2 - 1 **时,输出时钟就翻转翻转。

若输入时钟为 24MHz,进行2分频,分频后的时钟频率为 (24/2) = 12 MHz

module div_6(clk_in,rst_n,clk_out);

input clk_in;

input rst_n;

output clk_out;//分频后的时钟

parameter div_num = 6;

reg clk_out;

reg [3:0]c_count;//分频计数器

always @(posedge clk_in or negedge rst_n) begin

if(!rst_n) begin

clk_out <= 4'd0;

c_count <= 4'd0;

end

//如果计数器还未计到 N/2 - 1

else if(c_count < ((div_num / 2 )- 1)) begin

c_count <= c_count + 1'b1;

clk_out <= clk_out;

end

//如果计数器还计到 N/2 - 1,那就翻转

else begin

c_count <= 4'd0;

clk_out <= ~clk_out;

end

end

endmodule

`timescale 1ns/1ps

module tb_div6;

reg clk_in,rst_n;

wire clk_out;

div_6 dut(.clk_in(clk_in),.rst_n(rst_n),.clk_out(clk_out));

initial begin

clk_in <= 0;

forever begin

#5 clk_in <= !clk_in;

end

end

initial begin

#10 rst_n <= 0;

repeat(10) @(posedge clk_in);

rst_n <= 1;

end

endmodule

仿真结果如下:

4.奇数分频

1. 占空比不为50%

通过对待分频时钟上升沿触发计数器进行计数来实现。三分频电路:进行模3计数,在时钟上升沿进行加 1操作,比如可以在计数器计数到1时,输出时钟进行翻转,计数到2时再次进行翻转,计数到 2时清零,从头开始计数。这样实现的三分频占空比为1/3。五分频电路: 进行模5计数,在时钟上升沿进行加 1 操作,计数器的值为 0、1 时,输出时钟信号不变;计数器的值为2、3、4 时,输出时钟信号 clk_div 为低电平。计数到 5 时清零,从头开始计数。五分频占空比为 40% 。

//5分频,占空比不为50%

module div_5(clk,rst_n,clk_div);

input clk;

input rst_n;

output clk_div;

parameter NUM_DIV = 5;//分频数

reg[2:0] cnt1; //上升沿采样计数值

reg clk_div;//上升沿采样计数

always @(posedge clk or negedge rst_n) begin

if(!rst_n)

cnt1 <= 0;

else if(cnt1 < (NUM_DIV - 1))

cnt1 <= cnt1 + 1'b1;

else

cnt1 <= 0; //等于NUM_DIV时计数器复位

end

always @(posedge clk or negedge rst_n) begin

if(!rst_n)

clk_div <= 1'b1;

else if(cnt1 < (NUM_DIV-1)/2)//时钟翻转

clk_div <= 1'b1;//计数器值为0,1时,时钟信号为高

else

clk_div <= 1'b0;//计数器值为2,3,4时,时钟信号为低

end

endmodule

`timescale 1ns/1ps

module tb_div5_30;

reg clk,rst_n;

wire clk_div;

div_5 dut(.clk(clk),.rst_n(rst_n),.clk_div(clk_div));

initial begin

clk <= 0;

forever begin

#5 clk <= !clk;

end

end

initial begin

#10 rst_n <= 0;

repeat(10) @(posedge clk);

rst_n <= 1;

end

endmodule

实现了占空比不为50%的五分频

2. 占空比为50%

当奇分频需要保持分频后的时钟占空比为 50%时 ,就不能像偶分频那样直接在分频系数的一半时使时钟信号翻转(高电平一半,低电平一半)。在此我们需要利用输入时钟上升沿和下降沿来进行设计。

法一:可以通过待分频时钟下降沿触发计数,和上升沿同样的方法计数进行三分频,然后下降沿产生的三分频时钟和上升沿产生的时钟进行相或运算,即可得到占空比为50%的三分频时钟。

法二:对进行奇数倍n分频时钟,首先进行n/2分频(带小数,即等于(n-1)/2+0.5),然后再进行二分频得到占空比为50%的奇数倍分频。

//法一实现5分频

module div_5(clk,rst_n,clk_div);

input clk;

input rst_n;

output clk_div;

parameter NUM_DIV = 5;//分频数

reg[2:0] cnt1; //上升沿采样计数值

reg[2:0] cnt2;//下升沿采样计数值

reg clk_div1, clk_div2;//上升沿采样计数和下降沿采样计数的时钟

assign clk_div = clk_div1 | clk_div2;//上升沿采样计数和下降沿采样计数的时钟相或

//上升沿计数

always @(posedge clk or negedge rst_n) begin

if(!rst_n)

cnt1 <= 0;

else if(cnt1 < NUM_DIV - 1)

cnt1 <= cnt1 + 1'b1;

else

cnt1 <= 0; //等于NUM_DIV时计数器复位

end

always @(posedge clk or negedge rst_n) begin

if(!rst_n)

clk_div1 <= 1'b1;

else if(cnt1 < NUM_DIV / 2)//时钟翻转

clk_div1 <= 1'b1;

else

clk_div1 <= 1'b0;

end

//下降沿计数

always @(negedge clk or negedge rst_n) begin

if(!rst_n)

cnt2 <= 0;

else if(cnt2 < NUM_DIV - 1)

cnt2 <= cnt2 + 1'b1;

else

cnt2 <= 0;

end

always @(negedge clk or negedge rst_n) begin

if(!rst_n)

clk_div2 <= 1'b1;

else if(cnt2 < NUM_DIV / 2)//时钟翻转,要与上升沿同计数值

clk_div2 <= 1'b1;

else

clk_div2 <= 1'b0;

end

endmodule

`timescale 1ns/1ps

module tb_div5_50;

reg clk,rst_n;

wire clk_div;

div_5 dut(.clk(clk),.rst_n(rst_n),.clk_div(clk_div));

initial begin

clk <= 0;

forever begin

#5 clk <= !clk;

end

end

initial begin

#10 rst_n <= 0;

repeat(10) @(posedge clk);

rst_n <= 1;

end

endmodule

仿真结果如下,实现了占空比为50%的五分频电路

5.任意分频

对于实现占空比为50% 的N倍奇数分频。有以下步骤:

首先时钟上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比非50%奇数N分频时钟;同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相同值时,进行输出时钟时钟翻转。然后经过(N-1)/2时,输出时钟再次翻转,生成占空比非50%的奇数N分频时钟。两个占空比非50%的N分频时钟相或运算,得到占空比为50%的奇数n分频时钟。