一、前言
本系列旨在提供100%准确的数字IC设计/验证手撕代码环节的题目,原理,RTL设计,Testbench和参考仿真波形,每篇文章的内容都经过仿真核对。快速导航链接如下:
1.奇数分频
2.偶数分频
3.半整数分批
4.小数/分数分频
5.序列检测器
6.模三检测器
7.饮料机
8.异步复位,同步释放
9.边沿检测(上升沿,下降沿,双边沿)
10.全加器,半加器
11.格雷码转二进制
12.单bit跨时钟域(打两拍,边沿同步,脉冲同步)
13.奇偶校验
14.伪随机数生成器[线性反馈移位寄存器]
15.同步FIFO
16.无毛刺时钟切换电路
应当说,手撕代码环节是面试流程中既重要又简单的一个环节,跟软件类的岗位相比起来,数字IC的手撕代码题目固定,数量有限,属于整个面试中必得分的一个环节,在这个系列以外,笔者同样推荐数字IC求职者使用“HdlBits”进行代码的训练
链接如下
HDLBits — Verilog Practice
二、偶数分频题目
1.实现二分频电路,满足50%占空比。
2.实现四分频电路,满足50%占空比。
3.实现任意偶数分频,满足50%占空比。
4.实现任意偶数分频,不需要满足占空比。
三、偶数分频电路原理
3.1 寄存器级联法
寄存器级联法能实现2^N的偶数分频,具体是采用寄存器结构的电路,每当时钟上升沿到来的时候输出结果进行翻转,以此来实现偶数分频,具体的时序图如下所示
3.2 计数器法
计数器法可以实现任意偶数分频,以六分频为例,电路需要实现的是:计数器从0开始计数至2,当clock上升沿取到clock=2时,输出clock进行翻转,具体的时序图如下
若我们想实现任意任意偶数分频,如10/12分频,我们只需要将计数器的最大值设定为(10/2-1)或(12/2-1)或(N/2-1),既可以实现相关的分频电路
四、寄存器级联法分频电路
4.1 二分频|四分频|八分频RTL设计
module even_divide(clk,rst_n,clk2,clk4,clk8); input clk; input rst_n; output reg clk2; output reg clk4; output reg clk8; always@(posedge clk or negedge rst_n) begin if(!rst_n) clk2 <= 1'b0; else clk2 <= !clk2; end always@(posedge clk2 or negedge rst_n) begin if(!rst_n) clk4 <= 1'b0; else clk4 <= !clk4; end always@(posedge clk4 or negedge rst_n) begin if(!rst_n) clk8 <= 1'b0; else clk8 <= !clk8; end endmodule
4.2 分频电路的Testbench
module even_divide_tb(); reg clk; reg rst_n; wire clk2; wire clk4; wire clk8; even_divide u1(.clk(clk),.rst_n(rst_n),.clk2(clk2),.clk4(clk4),.clk8(clk8)); always #5 clk = ~clk; initial begin clk = 0; rst_n = 1; #15 rst_n = 0; #25 rst_n = 1; #300; end endmodule
4.3 仿真波形
4.4 结果分析
可以发现,clk2为2分频电路输出,ck4为4分频电路输出,clk8为8分频电路输出,结果满足需求
五、计数器法分频电路
5.1 六分频RTL设计
module odd_divide(clk,rst_n,clk6); input clk; input rst_n; output reg clk6; parameter N = 3'd6; reg [2:0] count; always@(posedge clk or negedge rst_n) begin if(!rst_n | count == N/2 -1) count <= 3'd0; else count <= count + 1'd1; end always@(posedge clk or negedge rst_n) begin if(!rst_n) clk6 <= 3'b0; else if (count == N/2-1) clk6 <= ~clk6; else clk6 <= clk6; end endmodule
5.2 分频电路的testbench
`timescale 1ns/ 1ps module odd_divide_tb(); reg clk; reg rst_n; wire clk6; odd_divide u1(.clk(clk),.rst_n(rst_n),.clk6(clk6)); always #5 clk = ~clk; initial begin clk = 0; rst_n = 1; #15 rst_n = 0; #25 rst_n = 1; #300; end endmodule
5.3 仿真波形
5.4结果分析
可以发现:所需六分频电路得到实现,此处略去count计数器,当其等于2的时候clk6实现翻转。
六、不需要满足50%占空比的偶数分频
通常来说,满足50%占空比的要求更严格,假如对于占空比没有要求,我们也可以使用状态机去来实现六分频电路
定义六个状态:状态0时clk的输出为0,状态1,2,3,4,5时clk的输出为1,也可以同样的实现六分频电路,以此类推,可以实现任意偶数分频的电路,并通过状态的输出为1,控制特殊占空比