LJgibbs · 2020年10月28日

HDLBits:在线学习 Verilog (二十八 · Problem 135-139)

转载自:知乎
作者:月半臻与逗小逗

首先附上传送门:

Fsm ps2data - HDLBits​hdlbits.01xz.net

Problem 135 PS/2 packet parser and datapath / Fsm ps2data

牛刀小试

现在,已经写了一个PS/2接口的状态机,该状态机可以标识PS/2字节流中的三字节消息。请在这个状态机中添加一条数据路径,该数据路径可以在接收数据包的同时输出24bits(3字节)的消息(out\_bytes[23:16]为第一字节,out\_bytes[15:8]为第二字节,以此类推)。

当发出接收完成信号done时,out\_bytes必须是有效的,其他时候可以输出任何的内容(即不在乎输出什么。)

小提示:使用前一题Problem 134 PS/2 packet parser / Fsm ps2 中的状态机,并添加用于捕捉输入字节的数据路径即可。

解答与分析

本题在前一题的三个没有输出动作的状态上添加out\_bytes等于输入即可完成。值得注意的是状态4可以跳转为状态2,所以状态4也需要对out\_bytes赋值。

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output [23:0] out_bytes,
    output done); //

    // FSM from fsm_ps2
    parameter A = 2'b00;
    parameter B = 2'b01;
    parameter C = 2'b10;
    parameter D = 2'b11;
    
    reg [1:0] state,next_state;
    
    always@(posedge clk)
        if(reset)
            state<=A;
        else
            state<=next_state;
    
    always@(*)
        case(state)
            A:next_state=in[3]?B:A;
            B:next_state=C;
            C:next_state=D;
            D:next_state=in[3]?B:A;
        endcase
    
    assign done = state ==D;

    // New: Datapath to store incoming bytes.
    always@(posedge clk)
        case(state)
            A:out_bytes[23:16]<=in;
            B:out_bytes[15: 8]<=in;
            C:out_bytes[ 7: 0]<=in;
            D:out_bytes[23:16]<=in;
        endcase

endmodule

Problem136 ~ Problem138 为串行接收器的部分,已经由小伙伴们完成了。附上链接,又可以偷懒啦~~~感谢

@近朱者赤

近朱者赤:HDLBits:Serial Receiver系列问题​zhuanlan.zhihu.com图标

Problem 139 Sequuence recognition / Fsm hdlc

同步HDLC帧涉及从连续的比特流中解码寻找某一帧(即数据包)的开始和结束位置的位模式。(对位模式不太理解的可以参见https://zhuanlan.zhihu.com/p/46317118)。如果接收到连续的6个1(即01111110),即是帧边界的“标志”。同时为了避免输入的数据流中意外包含这个帧边界“标志”,数据的发送方必须在数据中连续的5个1之后插入一个0,而数据的接收方必须将这个多余的0检测出来并丢弃掉。同时,如果输入检测到了了连续7个或更多的1时,接收方还需要发出错误信号。

牛刀小试

下面请创建一个有限状态机来识别上述的三个序列:

  1. 输入0111110:插入的信号位需要丢弃(Discarded, disc)。
  2. 输入01111110:标记(Flag)帧的开始/结束(flag)。
  3. 输入01111111 ...:错误(Reeor)(7个或更多的1)(err)。

重置FSM时,其状态应恢复到之前输入0的状态。

以下是一些示例序列,详细的说明了状态机所需的操作。

输入0111110,需要舍弃后面的0

输入01111110,判断为帧的开始/结束

复位逻辑和输入连续7个以上的1

小提示:

1、请使用10个状态以内的摩尔机。

2、状态图:

状态图

解答与分析

这道题可能比较难理解,不知道题干在说什么,但是看了下面的波形图还是能理解一些的,就是对连续输入的比特流进行判断,当连续输入5个1时,下一拍disc=1,当连续输入6个1时,flag=1,当输入的1数量超过7个时,将err置1,如果一旦有0输入,则返回初始状态。

此题还是建议自己去想一下状态转移是怎么样的,需要很多个状态,检测到1向下跳,检测到0返回初始状态,需要的状态比较多,但不要灰心,慢慢画一下。

module top_module(
    input clk,
    input reset,    // Synchronous reset
    input in,
    output disc,
    output flag,
    output err);
    
    parameter none=4'd0;
    parameter one=4'd1;
    parameter two=4'd2;
    parameter three=4'd3;
    parameter four=4'd4;
    parameter five=4'd5;
    parameter six=4'd6;
    parameter error=4'd7;
    parameter discard=4'd8;
    parameter flag_=4'd9;
    
    reg [3:0] state;
    reg [3:0] next_state;
    
    always@(posedge clk)
        if(reset)
            state<=none;
        else
            state<=next_state;
    
    always@(*)
        case(state)
            none   :next_state=in?one:none;
            one    :next_state=in?two:none;
            two    :next_state=in?three:none;
            three  :next_state=in?four:none;
            four   :next_state=in?five:none;
            five   :next_state=in?six:discard;
            six    :next_state=in?error:flag_;
            error  :next_state=in?error:none;
            discard:next_state=in?one:none;
            flag_  :next_state=in?one:none;
        endcase
    
    assign disc = state == discard;
    assign flag = state == flag_;
    assign err  = state == error;

endmodule

推荐阅读

关注此系列,请关注专栏FPGA的逻辑
推荐阅读
关注数
10488
内容数
502
FPGA Logic 二三事
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息