一、前言
本系列旨在提供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.使用verilog代码,设计电路,检测序列为1001,检测到的时候输出1,没检测到的时候输出0
这里的序列可以替换成任意一个,采用相同的思路进行设计即可
三、序列检测器原理
不管是什么样的序列检测器,我们都可以采用状态机的方法进行设计,以例1为参考,检测1001,我们需要5个状态,当复位信号到来的时候,返回IDLE状态,正常输入序列1001至状态S4时,output=1,其余时候output都为0,需要注意针对s1,s2,s3,s4,非1001序列输入的状态跳变并非全部到IDLE,也有跳变到相邻状态的可能性
这里再提出一种方法,使用4bit移位寄存器,每个时钟信号到来时,右移一位输入序列并进行比较,当移位寄存器内的data为1001时,输出1,其余状态输出0.
四、RTL设计
module sequence_check(clk,rst_n,sequence,test); input clk; input rst_n; input sequence; output test; parameter IDLE = 3'b000, s1 = 3'b001 ,s2 = 3'b010, s3 = 3'b011 , s4 = 3'b100; reg [2:0] state,nstate; always@(posedge clk or negedge rst_n) begin if(!rst_n) state <= IDLE; else state <= nstate; end always@(*) begin case(state) IDLE: nstate = sequence?s1:IDLE; s1: nstate = !sequence?s2:s1; s2: nstate = !sequence?s3:s1; s3: nstate = sequence ?s4:IDLE; s4: nstate = sequence ?s1:IDLE; default nstate = IDLE; endcase end assign test = state == s4 ? 1 : 0 ; endmodule
五、testbench设计
`timescale 1ns/1ps module sequence_check_tb(); reg clk; reg rst_n; reg sequence; wire test; sequence_check u1(.clk(clk),.rst_n(rst_n),.sequence(sequence),.test(test)); always #5 clk = !clk; always #9.999 sequence = $random; initial begin clk = 0; rst_n = 1; #10 rst_n = 0; #16 rst_n = 1; #2000 $stop; end endmodule
六、仿真分析
结果分析,当时钟上升沿到来时采到的信号为1001时,output输出为1,其余结果输出为0,设计符合预期