由于本人一直以来,用的三段式状态机,第三段写法都是组合逻辑写法,但是近期有小伙伴面试小公司,写到状态机的第三段时候,按照我一直用到的组合逻辑来写第三段,提供输出,被提出了质疑,曰:我们一直用的都是时序逻辑来写第三段?
由于本人从来没有遇到过这种质疑,所以具体什么情况也不是太清楚,仅仅以此篇博客来作为一种测试,解答第三段如何写的问题。
以序列检测器为例,我们分别提供组合逻辑以及时序逻辑来实现第三段,并通过行为仿真来验证其功能的正确性:
要求无重叠检测序列01010,分别给出状态转移图以及Verilog设计。
组合逻辑写法
首先给出状态转移图,为了方便,使用Moore状态机的画法。
相应的Verilog描述为:
module seq_detect(input clk,input rst_n,input seq_in,output reg out);//detect sequence 01010//first step: define parameter and state
parameter s0 = 6'b0000_01, s1 = 6'b0000_10, s2 = 6'b0001_00, s3 = 6'b0010_00,
s4 = 6'b0100_00, s5 = 6'b1000_00;reg [5:0] cur_state, nxt_state;//三段式状态机
//第一段:时序逻辑
always@(posedge clk or negedge rst_n) beginif(~rst_n) cur_state <= s0;else cur_state <= nxt_state;
end//第二段:组合逻辑
always@(*) beginnxt_state = s0;case(cur_state) s0: if(seq_in == 0) nxt_state = s1;else nxt_state = s0;s1: if(seq_in == 1) nxt_state = s2;else nxt_state = s1;s2: if(seq_in == 0) nxt_state = s3;else nxt_state = s0;s3: if(seq_in == 1) nxt_state = s4;else nxt_state = s1;s4: if(seq_in == 0) nxt_state = s5;else nxt_state = s0;s5: if(seq_in == 1) nxt_state = s0;else nxt_state = s1;default: nxt_state = s0;endcaseend//第三段:组合逻辑
always@(*) beginif(cur_state == s5) out = 1;else out = 0;
end//第三段:时序逻辑
/*
always@(posedge clk or negedge rst_n) beginif(~rst_n) out <= 0;else if(nxt_state == s5) out <= 1;else out <= 0; end
*/
endmodule
给出testbench文件:
`timescale 1ns/1ps
module seq_detect_tb();//输入输出分别转化为reg,wire
reg clk;
reg rst_n;
reg seq_in;
wire out;parameter PERIOD = 4;
//设计时钟
initial beginclk = 0;# PERIOD/2clk = ~clk;end//设计复位以及输入
initial begin
rst_n = 0;
seq_in = 1;
#5
rst_n = 1; forever begin@(posedge clk)seq_in = 0;@(posedge clk)seq_in = 1; endend//例化设计模块得到输出
seq_detect inst_seq_detect(
.clk(clk),
.rst_n(rst_n),
.seq_in(seq_in),
.out(out)
);endmodule
行为仿真图:
如何最后一段换成时序逻辑,则仿真结果为:
可以发现,二者仿真结果一致,所以无论第三段是组合逻辑还是时序逻辑都可以,但是本人却觉得组合逻辑更让人容易理解,输入只需要根据当前状态进行判断即可。
千万不要在存有质疑了。