本题是一道常规的FSM设计题,记录的目的是状态机的状态中出现了忽略输入的状态。
经过分析不难发现,此题的FSM需要四个状态,分别是:IDLE状态(初始状态,也可以表示接收到了一个0的状态)、已接收1状态(S1),已接收1x状态(S2,x表示不关心in[3]输入)以及已接收1xx状态(S3)。由此我们可以画出如下所示Moore型状态机的状态转移图。
需要注意的是题目中时序图描述中的这一句话:
Note that this is not the same as a 1xx sequence recognizer.Overlapping sequences are not allowed here…
也就是说这不是一个“1xx”序列检测器,并不检测重叠序列,只有在状态走过1xx并输出done = 1之后才重新开始判断下一个状态是回到IDLE还是直接进入S1,即使in[3]的输入序列是“1111”,也不会重复输出1,对于状态图来说就是S3不会出现指向自身的状态转换。
最后给出题目的Verilog HDL:
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
localparam IDLE = 4'b0001, S1 = 4'b0010, S2 = 4'b0100, S3 = 4'b1000;
reg [3:0] state;
reg [3:0] next_state;
// State transition logic (combinational)
always @(*)
case(state)
IDLE : next_state = in[3] ? S1 : IDLE;
S1 : next_state = S2;
S2 : next_state = S3;
S3 : next_state = in[3] ? S1 : IDLE;
endcase
// State flip-flops (sequential)
always @(posedge clk)
if(reset)
state <= IDLE;
else
state <= next_state;
// Output logic
assign done = (state == S3);
endmodule
第二题(Fsm ps2data),我们可以实现一个24bit的移位寄存器(left shift register)。每当有新的字节输入时,该移位寄存器就左移8位并将新的字节移入,再将输出信号直接与模块输出out_bytes
相连,这样每个时钟上升沿输出的out_bytes
就是该上升沿之前三个输入的字节(最先出现的在最高字节)。
到这里我们可以发现,由于out_bytes
只在done = 1
时有效,其余状态下不关心。那么这个输出其实是和done无关的,无论done
输出是0还是1,out_bytes
均输出此时刻之前的三个输入字节,在done = 1
输出题目要求的三个字节只是恰好而已,24bits移位寄存器并没有对此做出判断。所以只需要在代码对应位置添加如下代码即可:
// New: Datapath to store incoming bytes.
reg [23:0] datapath;
always @(posedge clk)
if(reset)
datapath <= 24'd0;
else
//datapath <= {datapath[15:0], in}; Also a way to output.
datapath <= datapath << 8 | in;
assign out_bytes = datapath;
PS:第一次见到这里编译需要排队