题解 | #时钟分频(偶数)#【计数器实现】
时钟分频(偶数)
https://www.nowcoder.com/practice/49a7277c203a4ddd956fa385e687a72e
思路
本道题的解决思路有很多。这里介绍计数器的方法。为什么执着于计数器方法呢?因为小编认为计数器方法是解决分频问题最根本的办法。无论多少次分频,都可以使用这种方法来解决。
通过观察题目的波形图我们可以看出,clk_out2是每经历一个完整周期就要翻转一次,clk_out4是每经历两个完整周期就要翻转一次,clk_out8是每经历4个完整周期就要翻转一次。
如果能考虑到上面的点,那么思路就很清晰了。接下来就只是一些细节问题。
代码
`timescale 1ns/1ns module even_div ( input wire rst , input wire clk_in, output wire clk_out2, output wire clk_out4, output wire clk_out8 ); //*************code***********// reg clk_out2_r=0,clk_out4_r=0,clk_out8_r=0; reg [2:0]cnt; always @(posedge clk_in or negedge rst) begin if (!rst)begin cnt=0; end else begin if (cnt==3'd3)cnt<=0; else cnt<=cnt+1; // cnt=cnt+1; end end always @(posedge clk_in or negedge rst)begin if (!rst)begin clk_out2_r=0; clk_out4_r=0; clk_out8_r=0; end else begin clk_out2_r=~clk_out2_r; if (cnt==0||cnt==3'b010)clk_out4_r<=~clk_out4_r; if (cnt==0)clk_out8_r=~clk_out8_r; end end assign clk_out2=clk_out2_r; assign clk_out4=clk_out4_r; assign clk_out8=clk_out8_r; //*************code***********// endmodule
细节问题:
实不相瞒。小编做这道题目时,花了大量时间。因为clk_out4的时钟一直对不上。究其原因,还是小编太菜了,呜呜呜呜,哭晕在厕所了。。。。。
- 如何做到三个clk最开始都是高
观察波形图不难发现,当rst为1后的第一个clk_in上升沿,三个clk_outx都是1。所以如何做到最开始三个clk_outx都是1呢?很简单,当cnt计数到0时,就让它们翻转。
2.为何计数器是cnt<=cnt+1;
最开始小编写的是cnt=cnt+1,但最后一直通不过【小编也是因为这花费了很多时间。。。】。小编去问cha老师,cha老师说,用cnt=cnt+1也是可以的,但是会有一些问题,如下:
咱也不知道会有啥逻辑错误和难以调试的问题。反正为了保险,咱还是统一全部用cnt<=cnt+1吧。
3.为何clk_out4_r是在cnt=0或cnt=2时变化?而不是在cnt=0或cnt=1时变化?
这个问题就要看看此代码的波形图:
发现没?clk_out4是在cnt为0或者为2时翻转的。咱小伙伴就要问了,明明从0开始计数,为什么不在0和1处翻转,而在0和2呀?原因是,rst为0时,cnt就为0了,当rst为1后的第一次clk_in上升沿时,cnt此时变成1了。所以第一轮的cnt计数不是从0开始的,而是从1开始计数的。