verilog HDLBits刷题[Finite State Machines]“Fsm hdlc”---Sequence recognition
1、题目
Synchronous HDLC framing involves decoding a continuous bit stream of data to look for bit patterns that indicate the beginning and end of frames (packets). Seeing exactly 6 consecutive 1s (i.e., 01111110) is a "flag" that indicate frame boundaries. To avoid the data stream from accidentally containing "flags", the sender inserts a zero after every 5 consecutive 1s which the receiver must detect and discard. We also need to signal an error if there are 7 or more consecutive 1s.
Create a finite state machine to recognize these three sequences:
- 0111110: Signal a bit needs to be discarded (disc).
- 01111110: Flag the beginning/end of a frame (flag).
- 01111111...: Error (7 or more 1s) (err).
When the FSM is reset, it should be in a state that behaves as though the previous input were 0.
Here are some example sequences that illustrate the desired operation.
Discard 0111110:
2、分析(借助豆包)
- 初始复位:默认前一个输入比特为
0; - 持续统计数据流中连续 1 的个数:
- 每收到 1 个 1,连续 1 计数 + 1;收到 0,连续 1 计数立刻清零,回到初始状态;
- 三类触发信号定义:
disc:连续5 个 1后紧跟 1 个 0(0 11111 0),该 0 需要丢弃,disc 拉高 1 周期;flag:连续6 个 1后紧跟 1 个 0(0 111111 0),代表帧边界,flag 拉高 1 周期;err:出现7 个及以上连续 1,持续报错,只要连续 1≥7,err 持续拉高,直到出现 0 清零;
- 时序要求:
- disc、flag:检测到对应序列后延迟 1 个时钟周期输出(时钟同步寄存输出);
- err:进入 7 个 1 错误态时立刻实时输出,无延迟;
- 同步复位,复位后所有输出清零、回到初始状态。设计思路
- 状态划分:
状态 含义 S0 前一位是 0,连续 1 个数 = 0(复位初始态) S1~S6 连续 1 的个数分别为 1~6 S7 连续 1≥7,错误状态 - 状态跳转规则
- 任意状态收到
in=1:状态 + 1; - 任意状态收到
in=0:直接跳回 S0,连续 1 清零; - S7 收到 1 则保持 S7,收到 0 回到 S0 解除报错。
- 任意状态收到
- 输出拆分设计
- err:Moore 组合输出,仅由当前状态决定,S7 立刻置 1,消除滞后;
- disc/flag:Mealy 时序寄存输出,延迟一拍,匹配评测参考波形时序。
刚开始思路混乱,设置状态为:IDEL,连续5个1,连续6个1,连续7个1,并借助计数器,但是计数器的处理没处理成功。问了ai,确实设置状态为每一bit最好。
3、代码
module top_module( input clk, input reset, // Synchronous reset 同步复位 input in, // 串行比特输入流 output reg disc,// 5个1后接0,丢弃该0标志 output reg flag,// 6个1后接0,帧边界标志 output reg err // 7个及以上连续1,错误标志 ); // 状态宏定义:状态编号 = 当前已接收连续1的个数 localparam S0 = 0; // 连续1个数0,上一比特为0(复位初始态) localparam S1 = 1; // 连续1个1 localparam S2 = 2; // 连续2个1 localparam S3 = 3; // 连续3个1 localparam S4 = 4; // 连续4个1 localparam S5 = 5; // 连续5个1(比特填充检测点) localparam S6 = 6; // 连续6个1(帧标志检测点) localparam S7 = 7; // 连续≥7个1(错误状态) reg [2:0] curr_state; // 当前状态寄存器 reg [2:0] next_state; // 下一状态组合逻辑变量 //===================== 时序逻辑:状态寄存器更新(同步复位)===================== // 时钟上升沿更新当前状态,复位强制回到初始S0 always @(posedge clk) begin if(reset) begin curr_state <= S0; end else begin curr_state <= next_state; end end //===================== 组合逻辑:状态跳转逻辑 ===================== always @(*) begin next_state = S0; // 默认赋值,避免组合逻辑生成锁存器 case(curr_state) S0: next_state = in ? S1 : S0; // 来1→1个1,来0保持清零 S1: next_state = in ? S2 : S0; S2: next_state = in ? S3 : S0; S3: next_state = in ? S4 : S0; S4: next_state = in ? S5 : S0; S5: next_state = in ? S6 : S0; // 5个1:再来1→6个1,来0清零 S6: next_state = in ? S7 : S0; //6个1:再来1→进入错误态,来0清零 S7: next_state = in ? S7 : S0; //≥7个1:持续保持错误,来0退出报错 default: next_state = S0; //异常状态兜底清零 endcase end //===================== 组合逻辑:err实时输出 ===================== // Moore输出:仅由当前状态决定,进入S7立刻报错,无延迟 always @(*) begin err = (curr_state == S7) ? 1'b1 : 1'b0; end //===================== 时序逻辑:disc、flag寄存输出(延迟1拍) ===================== // disc、flag需要延迟1个时钟周期输出,和参考波形对齐 always @(posedge clk) begin //复位时两个标志强制清零 if(reset) begin disc <= 1'b0; flag <= 1'b0; end else begin disc <= 1'b0; flag <= 1'b0; case(curr_state) // 当前是5个1,下一比特为0,下一拍拉高disc S5: if(in == 1'b0) disc <= 1'b1; // 当前是6个1,下一比特为0,下一拍拉高flag S6: if(in == 1'b0) flag <= 1'b1; default:; endcase end end endmodule