题解 | #任意小数分频#

任意小数分频

https://www.nowcoder.com/practice/24c56c17ebb0472caf2693d5d965eabb

`timescale 1ns/1ns

module div_M_N(
 input  wire clk_in,
 input  wire rst,
 output wire clk_out
);
parameter M_N = 8'd87; 
parameter c89 = 8'd24; // 8/9时钟切换点
parameter div_e = 5'd8; //偶数周期
parameter div_o = 5'd9; //奇数周期
//*************code***********//

//clk_in只有整数,所以无法实现0.3个clk_in,所以小数分频不是精确的一个clk_out内输出8.3个clk_in,
//因为单个clk_in是最小的计数单位是整数,所以只能实现平均意义上的分频,比如本题8.7分频,
//那我们就在87个clk_in中输出10个clk_out,就相当于是8.7分频了,3*8+7*9=87,所以可以假设87个clk_in
//中3个8分频和7个9分频

reg flag;//标志是8分频还是9分频

reg clk_out_r;//因为题目clk_out给的是wire,所以定义一个reg转换一下
reg [6:0] cnt;//计数器,每87个时钟后清零

reg [3:0] cnt_div;//分频计数器,在8、9分频的一半时候跳转

//标志位,当计数器达到8,9分频器的交界翻转,即flag为0时是8分频器输出,1时是9分频器输出
//这里切记不要忘了cnt ==(M_N-1)时也要进行翻转
always @(posedge clk_in or negedge rst)begin
    if(~rst)
    flag <= 1'b0;
    else
    flag <= ((cnt==(c89-1))|(cnt ==(M_N-1)))?(~flag):flag;

end


//整个大周期计数器,从0到87-1共87个数
always @(posedge clk_in or negedge rst)begin
    if(~rst)
    cnt <= 1'b0;
    else
    cnt <= (cnt==(M_N-1))?0:cnt+1;
end


//这是分频器的计数器,8分频时计数器从0-7共8个数,9分频器从0-8共计9个数,
//这部分的作用是为了后面的clk_out翻转,clk_out要在分频器中间进行跳转
always @(posedge clk_in or negedge rst)begin
    if(~rst)
    cnt_div <= 4'b0;
    else if(~flag)
    cnt_div <= (cnt_div == (div_e-1))?1'b0:cnt_div+1;
    else if(flag)
    cnt_div <= (cnt_div == (div_o-1))?1'b0:cnt_div+1;
end


//这部分就是输出了,因为8分频器和9分频器中间都是4(9的分频器可以取4或者5),所以其实下面两个else的条件是一样的
//但是不知道为什么9分频器的条件改成cnt_div==5不行,按理来说可以,题目中的波形太小了懒得看,可能题目规定了
always @(posedge clk_in or negedge rst)begin
    if(~rst)
    clk_out_r <= 1'b0;
    else if(~flag)
    clk_out_r <= ((cnt_div==0)|(cnt_div==4))?(~clk_out_r):(clk_out_r);
    else if(flag)
    clk_out_r <= ((cnt_div==0)|(cnt_div==4))?(~clk_out_r):(clk_out_r);
    
end


assign clk_out = clk_out_r; 




//*************code***********//
endmodule

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务