题解 | #任意小数分频#
任意小数分频
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