数字IC手撕代码-序列检测(状态机写法)

 前言:

        本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析、代码及波形,所有代码均经过本人验证。

目录如下:

1.数字IC手撕代码-分频器(任意偶数分频)

2.数字IC手撕代码-分频器(任意奇数分频)

3.数字IC手撕代码-分频器(任意小数分频)

4.数字IC手撕代码-异步复位同步释放

5.数字IC手撕代码-边沿检测(上升沿、下降沿、双边沿)

6.数字IC手撕代码-序列检测(状态机写法)

7.数字IC手撕代码-序列检测(移位寄存器写法)

8.数字IC手撕代码-半加器、全加器

9.数字IC手撕代码-串转并、并转串

10.数字IC手撕代码-数据位宽转换器(宽-窄,窄-宽转换)

11.数字IC手撕代码-有限状态机FSM-饮料机

12.数字IC手撕代码-握手信号(READY-VALID)

13.数字IC手撕代码-流水握手(利用握手解决流水线断流、反压问题)

14.数字IC手撕代码-泰凌微笔试真题

15.数字IC手撕代码-平头哥技术终面手撕真题

16.数字IC手撕代码-兆易创新笔试真题

17.数字IC手撕代码-乐鑫科技笔试真题(4倍频)

18.数字IC手撕代码-双端口RAM(dual-port-RAM)

        ...持续更新

为了方便可以收藏导览博客: 数字IC手撕代码-导览目录


目录

序列检测

状态机写法

代码

testbench

波形


序列检测

        一说到序列检测,你脑子里要立马跳出两种解法,一种是状态机写法, 一种是移位寄存器写法,看过一个面经,面试官让手撕一个 五位01序列的序列检测,作者用状态机写的,写完被批评代码太复杂,再写一个简单的方法(也即移位寄存器方法)最后没写出来。虽然第二种方法更简单更好用,但是我们两种方法都得会。

序列检测有什么用?

        如果让你实现一个电子锁,输入密码,密码正确就开,密码错误就不开,你会如何写代码?用if-else嵌套嘛,如果第一个数对了,再去判断第二个数,完了再判断第三个数,判断第四个。

        这种方法在输入密码位数比较少的时候可行,但是如果密码位数很多。而一个 if-else 语句最后被综合出来就是一个MUX,如果循环嵌套很多,那就是级联MUX,这会带来一连串长的组合逻辑,有很大的delay,且代码容易出错不好维护,因此这种方法是不可取的。

状态机写法

        我们引出有限状态机(FSM)来解决这个问题。

        要去写一个状态机,第一步要做的就是画出状态转移图,我们要知道总共有几个状态,以及状态和状态之间的跳转条件是什么。

        比如说我们做 序列检测 1011,检测到“1011”则输出1,没检测到输出0 

        先画出序列检测的状态转移图。 

        画状态转移图要注意,在一个状态中,如果检测错误,不是一定会跳到IDLE初始状态,也可能跳到相邻状态。比如在S4状态,如果在下一个时钟周期,input = 0,状态不会跳转到IDLE,因为上一个输入是1,连起来是10,所以反而会调到S2状态。

状态转移部分我们用三段式的写法。

第一段:状态转移,每当时钟上升沿到来的时候,当前状态跳转到下一个状态。

第二段:根据状态转移图写case,组合逻辑,要用阻塞性赋值。只要状态转移图画的对,这里就不会出错

第三段:结果输出,时钟上升沿到来的时候,检测当前状态是否是S4,如果是,则det信号输出1,否则输出0。在这里我们要知道,这第三段的写法是时序逻辑,所以det信号拉高会比当前状态跳转到S4迟一个周期。 

testbench

我们编写testbench,让data输入流为:011011011001

细心的小伙伴就发现我们这一串数据流里面,隐藏着两个1011.所以最终结果应该要输出2个1011才对,并且两个1011之间仅仅相隔了两个周期。 

波形

        检测到data信号输入1011后,det信号在时钟的下一个上升沿拉高,并且和我们testbench编写的数据流反馈一致:011011011001输出两个det高电平,且相距两个时钟周期,符合我们的设计。

状态机写序列检测1011到此结束。 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
三段式状态机是指在Verilog HDL中,使用三个always块来实现状态机的设计方法。其中,第一个always块用于状态转移,第二个always块用于状态转移条件的判断,第三个always块用于输出状态。这种设计方法的优势在于代码结构清晰,易于维护。 序列检测是指在输入序列检测是否存在某个特定的序列。在三段式状态机中,可以使用Moore型状态机来实现序列检测。Moore型状态机的输出仅与当前状态有关,因此输出和状态可以在一起。具体实现方法是,在第三个always块中,根据当前状态输出相应的值,然后在第二个always块中判断输入序列是否匹配特定的序列,如果匹配则进行状态转移。 下面是一个简单的三段式状态机代码实现,用于检测输入序列"1010": ``` module sequence_detector( input clk, input reset, input data, output reg match ); reg [1:0] state; parameter S0 = 2'b00; parameter S1 = 2'b01; parameter S2 = 2'b10; parameter S3 = 2'b11; always @(posedge clk, posedge reset) begin if (reset) begin state <= S0; end else begin case (state) S0: if (data) state <= S1; else state <= S0; S1: if (!data) state <= S2; else state <= S1; S2: if (data) state <= S3; else state <= S0; S3: if (!data) begin state <= S0; match <= 1; end else begin state <= S1; match <= 0; end endcase end end endmodule ``` 在这个代码中,第一个always块用于状态转移,第二个always块用于判断输入序列,第三个always块用于输出状态。当输入序列匹配"1010"时,输出match信号为1,否则为0。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃葱的酸菜鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值