关于Verilog HDL实现奇数分频

verilog代码:

module div_3#(parameter DIV = 7)( //改变参数DIV的值就可以改变分频时钟的频率

input clk ,//时钟
input rst_n ,//复位
//输出信号定义
output wire clk_out
);

//信号定义
reg [3:0] cnt0 ;//15分频以上需要改变计数器的位宽
wire add_cnt0 ;
wire end_cnt0 ;

reg [3:0] cnt1 ;
wire add_cnt1 ;
wire end_cnt1 ;

//计数器

always @(posedge clk or negedge rst_n)begin //对系统时钟上升沿计数
if(!rst_n)begin
cnt0 <= 0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end

assign add_cnt0 = 1'b1;
assign end_cnt0 = add_cnt0 && cnt0 == DIV-1;

always @(negedge clk or negedge rst_n)begin //对系统时钟下降沿计数
if(!rst_n)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end

assign add_cnt1 = 1'b1;
assign end_cnt1 = add_cnt1 && cnt1 == DIV-1;


assign clk_out = cnt0 > (DIV>>1) | cnt1 > (DIV>>1);//DIV>>1,将DIV除以2,我们这里进行7分频,由于N-1/2,故clk_out = (cnt0 > 3) | (cnt1 > 3);
//cnt0>3 | cnt0>3 //由于将上升沿和下降沿计数值进行或操作,故7分频后得到的clk_out,高低电平各持续3.5周期
//0~6
endmodule

TestBench编写:

`timescale 1 ns/1 ns  //时间单位,时间精度

module div_3_tb();

//时钟和复位
reg clk ;
reg rst_n;

//输出信号
wire clk_out;

parameter CYCLE = 20;//时钟周期,单位为ns,可在此修改时钟周期。
parameter RST_TIME = 3 ;//复位时间,此时表示复位3个时钟周期的时间。

//待测试的模块例化
div_3 div_3(
.clk (clk ),
.rst_n (rst_n ),
.clk_out (clk_out )

);

defparam div_3.DIV = 7;

//生成本地时钟50M
initial clk = 0;
always #(CYCLE/2) clk=~clk;

//产生复位信号
initial begin
rst_n = 1;
#2;
rst_n = 0;
#(CYCLE*RST_TIME);//RST_TIME个时钟周期后
rst_n = 1;

#(CYCLE*100);//运行100个周期
$stop;//退出
end

endmodule

 

 从modelsim中可以观察仿真结果

posted @ 2021-03-11 14:41  txzing  阅读(245)  评论(0编辑  收藏  举报