Verilog-实现时钟分频(1KHZ、奇、偶分频,占空比为50%)
一、将系统时钟50MHZ分为占空比为50%的1khz时钟
本篇文章使用Xilinx公司的ISE软件
1. 频率:1HZ 周期为1/1HZ=1s。按照这个计算公式计算出频率为1khz的周期为1ms
2. 因为占空比为50%,在写代码时需要一个0.5ms的计数器
PS: 占空比:占空比是指在一个脉冲循环内,通电时间相对于总时间所占的比例。(在FPGA中我的理解为高电平在一个时钟周期所占的时间)
<代码如下>
1khz分频代码
module clk_1KHZ(clk,rst_n,clk_1khz );
input clk ; //50MHZ
input rst_n ;
output reg clk_1khz ; //T=1ms 占空比为50%
reg[17:0] cnt;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 1'b0;
else if (cnt == 18'd25_000 - 1)//
cnt <= 18'd0;
else
cnt <= cnt + 1'b1;
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_1khz <= 1'b0;
else if (cnt == 18'd24_999)
clk_1khz <= ~clk_1khz ;
else
clk_1khz <= clk_1khz ;
end
endmodule
1khz分频-testbench
module tb;
// Inputs
reg clk;
reg rst_n;
// Outputs
wire clk_1khz;
// Instantiate the Unit Under Test (UUT)
clk_1KHZ uut (
.clk(clk),
.rst_n(rst_n),
.clk_1khz(clk_1khz)
);
always #10 clk = ~clk;
initial begin
clk = 0;
rst_n = 0;
#100;
rst_n=1;
end
endmodule
二、偶数分频:
- 通过计数器实现,进行N倍偶数分频,通过时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,以此循环下去。(占空比为50%) ,以下代码实现8分频,可根据实际需求改变参数输出需要的时钟。
<代码如下>
偶数分频代码
module clk_div_o(clk,rst_n,div_clk_out);
input clk ;
input rst_n ;
output div_clk_out ;
//偶数分频部分
parameter N = 8 ;
reg div_clk_out;
reg [7:0] cnt ;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt <= 1; //从1计数
div_clk_out <= 0;
end
else begin
if(cnt==N/2)
begin
div_clk_out <= ~div_clk_out;
cnt <= 1;
end
else
cnt <= cnt + 1;
end
end
endmodule
偶数分频testbench
module tb;
// Inputs
reg clk;
reg rst_n;
// Outputs
wire div_clk_out;
// Instantiate the Unit Under Test (UUT)
clk_div_o uut (
.clk(clk),
.rst_n(rst_n),
.div_clk_out(div_clk_out)
);
always #10 clk = ~clk;
initial begin
// Initialize Inputs
clk = 0;
rst_n = 0;
#100
rst_n = 1;
end
endmodule
三、奇数分频:
-
以7分频为例。接下来会介绍两种实现方法(占空比为50%)
(1)高电平:低电平 = 4 :3(即 1:0 = 4 :3)
(2)低电平:高电平 = 4 :3(即 0:1 = 4 :3)
二者实现方式相同,这里只介绍第一种方法
时序图如下
由时序图看出分别用时钟上升沿和下降沿得到高电平:低电平 = 4 :3,然后将两者相与就可以得到7分频占空比为50%的时钟<代码如下>
奇数分频代码
module clk_div_j(clk,rst_n,clk_out );
input clk ;
input rst_n ;
output clk_out;
parameter N = 7;//分频数
reg [7:0] cnt_1;
reg [7:0] cnt_2;
reg clk_pos,clk_neg;
// 1:0 4:3 &
// 0:1 4:3 |
always @(posedge clk or negedge rst_n) //上升沿输出clk_pos
begin
if(!rst_n)
begin
clk_pos <= 0;
cnt_1 <= 1; //这里计数器从1开始
end
else
begin
if(clk_pos == 1)
begin
if(cnt_1 == (N+1)/2) //4
begin
clk_pos <= ~clk_pos;
cnt_1 <= 1;
end
else
cnt_1 <= cnt_1 + 1;
end
else if(cnt_1 == (N-1)/2) //3
begin
clk_pos <= ~clk_pos;
cnt_1 <= 1;
end
else
cnt_1 <= cnt_1 + 1;
end
end
always @(negedge clk or negedge rst_n)
//下降沿输出clk_neg
begin
if(!rst_n)
begin
clk_neg <= 0;
cnt_2 <= 1;
end
else
begin
if(clk_neg == 1)
begin
if(cnt_2 == (N+1)/2) //4
begin
clk_neg <= ~clk_neg;
cnt_2 <= 1;
end
else
cnt_2 <= cnt_2+1;
end
else
if(cnt_2 == (N-1)/2) //3
begin
clk_neg <= ~clk_neg;
cnt_2 <= 1;
end
else
cnt_2 <= cnt_2+1;
end
end
assign clk_out = clk_pos & clk_neg;
endmodule
奇数分频testbench
module tb;
// Inputs
reg clk;
reg rst_n;
// Outputs
wire clk_out;
// Instantiate the Unit Under Test (UUT)
clk_div_j uut (
.clk(clk),
.rst_n(rst_n),
.clk_out(clk_out)
);
always #10 clk = ~clk;
initial begin
clk = 0;
rst_n = 0;
#100;
rst_n = 1;
end
endmodule
本篇随笔为学习记录所用,如有错误,请各位指正批评。