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

2021-04-15 14:57:33 浏览数 (2)

本系列内容来自于知乎专栏,链接如下:https://zhuanlan.zhihu.com/c_1131528588117385216 本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题,并附上解答和一些作者个人的理解,相信无论是想 7 分钟精通 Verilog,还是对 Verilog 和数电知识查漏补缺的同学,都能从中有所收获。

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赋值。

代码语言:javascript复制
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帧涉及从连续的比特流中解码寻找某一帧(即数据包)的开始和结束位置的位模式。(对位模式不太理解的可以参见zhuanlan.zhihu.com/p/46)。如果接收到连续的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返回初始状态,需要的状态比较多,但不要灰心,慢慢画一下。

代码语言:javascript复制
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

0 人点赞