本人之前写的这部分代码犯了一个大错,就是always@(posedge clk or negedge clk or negedge rstn),这样对应的触发器就是说要既能支持上升沿触发又要支持下降沿触发,这样是不对的。错误的现象我仍然保留,放在文末。
正确的奇数分频代码如下;
module div_n(
input clk,
input rstn,
output wire div_clk
);
parameter num=7;//想要几分频就可以写(奇数)
reg [7:0]count1;
reg [7:0]count2;
//reg [7:0]count_sum;
wire clk_n;
reg div_clk1;
reg div_clk2;
assign clk_n=~clk;
always@(posedge clk )
if(!rstn)
count1<=0;
else if(count1==num-1)
begin count1<=0;end
else
count1<=count1+1;
always@(posedge clk )
if(!rstn)
div_clk1<=0;
else if(count1<=(num-1)>>1&&count1>=1)
div_clk1<=1;
else div_clk1<=0;
always@(posedge clk_n )
if(!rstn)
count2<=0;
else if(count2==num-1)
begin count2<=0;end
else
count2<=count2+1;
always@(posedge clk_n )
if(!rstn)
div_clk2<=0;
else if(count2<=(num-1)>>1&&count2>=1)
div_clk2<=1;
else div_clk2<=0;
assign div_clk=div_clk1||div_clk2;
endmodule
module div_n_tst();
reg clk;
reg rstn;
wire div_clk;
div_n u_div_n(
.clk(clk),
.rstn(rstn),
.div_clk(div_clk)
);
initial
begin
clk=1;
rstn=0;
#20 rstn=1;
#1000 rstn=0;
#20 $finish;
end
always #10 clk=~clk;
endmodule
七分频现象:
偶数分频比较简单,直接计数时钟上升沿即可。
这部分代码我建议大家能够把电路也画出来,面试可能会问到,这部分我是看别人的公众号(小鱼学IC)内容学习的,推荐大家去看,还有计数器也是除了要会写代码,对应的电路也要会,计数器的电路我总结的了的,大家可以看我的博客https://blog.csdn.net/qq_38374491/article/details/119217177?spm=1001.2014.3001.5501。
以下为之前错误写法///
今天倒腾了一下分频,首先一定要区分分频和倍频。分频是降低频率的,输入n个时钟周期输出一个时钟。
这个代码的核心是对输入时钟的上升沿和下降沿进行计数。因此对奇数和偶数分频都适用。要注意翻转条件是有2个的(我才开始只写了一个翻转条件,导致写的是4分频结果是8分频)。
通用的奇偶分频代码来了:
计数器值:对时钟上升沿和下降沿计数,若为3分频(设分频数为num),那么上升沿和下降沿就有6个,从0开始就计数到5(2num-1);
翻转条件:计数值为num-1和2num-1时翻转,画一个图就能理解了。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/01/10 16:02:45
// Design Name:
// Module Name: div
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module div_n(
input clk,
input rstn,
output reg clk_n
);
parameter num=3;//分频数
reg [7:0]count;
always@(posedge clk or negedge clk or negedge rstn)
if(!rstn)
count<=0;
else if(count==2*num-1)
begin count<=0;end
else
count<=count+1;
always@(posedge clk or negedge clk or negedge rstn)
if(!rstn)
clk_n<=0;
else if(count==num-1)
clk_n<=~clk_n;
else if(count==2*num-1)
clk_n<=~clk_n;
else clk_n<=clk_n;
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/01/10 16:11:29
// Design Name:
// Module Name: div_4_tst
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module div_n_tst();
reg clk;
reg rstn;
wire clk_n;
div_n u_div_n(
.clk(clk),
.rstn(rstn),
.clk_n(clk_n)
);
initial
begin
clk=1;
rstn=0;
#10 rstn=1;
#1000 rstn=0;
#20 $finish;
end
always #10 clk=~clk;
endmodule