HDLBits刷题(PS/2 packet parser~Sequence recognition)

3.2.5.15 PS/2 packet parser
问题陈述:

PS/2鼠标协议发送三个字节长的消息。然而,在连续的字节流中,消息的开始和结束位置并不明显。唯一的指示是,每个三字节消息的第一个字节总是bit[3]=1(但其他两个字节的bit[3]可能是1或0,这取决于数据)。
我们想要一个有限状态机,在给定输入字节流时,搜索消息边界。我们将使用的算法是丢弃字节,直到看到bit[3]=1为止。然后我们假设这是消息的第1字节,并在所有3个字节都被接收(完成)后发出接收消息的信号。

FSM应该在成功接收到每个消息的第三个字节后立即在周期内发出信号。
一些时序来解释所需的行为
在无错误的情况下,每三个字节形成一条消息:
请添加图片描述
发生错误时,搜索字节1:
请添加图片描述
请注意,这1xx序列识别器不同。此处不允许重叠序列:
请添加图片描述

Verilog代码:

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
	parameter s0=0,s1=1,s2=2,s3=3;
    reg [1:0] state ,next;
    always@(*) begin
        case (state)
            s0: next=in[3]?s1:s0;
            s1: next=s2;
            s2: next=s3;
            s3: next=in[3]?s1:s0;
        endcase
    end
    always@(posedge clk) begin
        if(reset)
            state<=s0;
        else
            state<=next;
    end
    assign done=(state==s3);

endmodule

3.2.5.16 PS/2 packet parser and datapath
问题陈述:

现在,您有了一个状态机,它将识别PS/2字节流中的3字节消息,添加一个数据路径,它也将在接收到数据包时输出24位(3字节)消息(out_bytes[23:16]是第一个字节,out_bytes[15:8]是第二个字节,等等)。

每当断言done信号时,Out_bytes需要是有效的。您可以在其他时间输出任何内容(即,不关心)。
例如:
请添加图片描述

Verliog代码:

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 s0=2'b00,s1=2'b01,s2=2'b10,s3=2'b11;
    reg [1:0] state ,next;
    always@(*) begin
        case (state)
            s0: next=in[3]?s1:s0;
            s1: next=s2;
            s2: next=s3;
            s3: next=in[3]?s1:s0;
        endcase
    end
    always@(posedge clk) begin
        if(reset)
            state<=s0;
        else
            state<=next;
    end
    assign done=(state==s3);
    // New: Datapath to store incoming bytes.
    always@(posedge clk)
        begin
            case(state)
                s0: out_bytes[23:16]<=in;
                s1: out_bytes[15:8]<=in;
                s2: out_bytes[7:0]<=in;
                s3: out_bytes[23:16]<=in;
            endcase
        end
endmodule

3.2.5.17 Serial receiver
问题陈述:

在许多(较老的)串行通信协议中,每个数据字节都随一个起始位和一个停止位一起发送,以帮助接收方从位流中划定字节。一种常见的方案是使用1个开始位(0)、8个数据位和1个停止位(1)。当没有任何传输(空闲)时,线路也处于逻辑1。
设计一个有限状态机,当给定比特流时,它将识别字节是否被正确接收。因此,它需要识别起始位,等待所有8个数据位,然后验证停止位是否正确。如果停止位未按预期出现,则FSM必须等到它找到一个停止位后再尝试接收下一个字节。
一些时序图
无错误:
请添加图片描述
未找到停止位。第一个字节被丢弃:
请添加图片描述

Verilog代码:

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
	parameter start=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,stop=9,idle=10,Wait=11;
    reg [3:0] state,next;
    always@(*) begin
        case(state)
            start: next= in? start:s1;
            s1: next=s2;
            s2: next=s3;
            s3: next=s4;
            s4: next=s5;
            s5: next=s6;
            s6: next=s7;
            s7: next=s8;
            s8: next=stop;
            stop: next=in? idle:Wait;
            idle: next=in?start:s1;
            Wait:next=in? start:Wait;
        endcase
    end
        always@(posedge clk) begin
            if(reset)
                state<=start;
            else
                state<=next;
        end
        assign done=(state==idle);
endmodule

3.2.5.17 Serial receiver and datapath
问题陈述:

现在你有一个有限状态机,可以识别何时在串行比特流中正确接收到字节,添加一个数据路径来输出正确收到的数据字节。out_byte需要在done 为1时有效,否则不在乎。
请注意,串行协议首先发送最低有效位。
一些时序图
无错误:
请添加图片描述

Verilog代码:

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

    // Use FSM from Fsm_serial
	parameter start=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,stop=9,idle=10,Wait=11;
    reg [3:0] state,next;
    reg [7:0]temp;
    always@(*) begin
        case(state)
            start: next= in? start:s1;
            s1: next=s2;
            s2:  next=s3;
            s3: next=s4;
            s4: next=s5;
            s5: next=s6;
            s6: next=s7;
            s7: next=s8;
            s8: next=stop;
            stop: next=in? idle:Wait;
            idle: next=in?start:s1;
            Wait:next=in? start:Wait;
        endcase
    end
        always@(posedge clk) begin
            if(reset)
                state<=start;
            else
                state<=next;
        end
        assign done=(state==idle);
    // New: Datapath to latch input bits.
    always@(posedge clk) begin
        case(state)
            s1:temp[0]<=in;
            s2:temp[1]<=in;
            s3:temp[2]<=in;
            s4:temp[3]<=in;
            s5:temp[4]<=in;
            s6:temp[5]<=in;
            s7:temp[6]<=in;
            s8:temp[7]<=in;
        endcase
    end
    assign out_byte=done?temp:8'b0;
endmodule

3.2.5.18 Serial receiver with parity checking
问题陈述:

我们想在串行接收器中添加奇偶校验。奇偶校验在每个数据字节后增加一位。我们将使用奇校验,其中接收的9位中的1的数量必须为奇数。例如,101001011满足奇偶校验(有5个1),而001001011不满足奇偶校验。
修改FSM和数据路径以执行奇偶校验。只有当一个字节被正确接收并且其奇偶校验通过时,才断言完成的信号。像串行接收器FSM,这个FSM需要识别起始位,等待所有9位(数据和奇偶校验),然后验证停止位是否正确。如果停止位没有出现,FSM必须等待,直到它找到一个停止位,然后再尝试接收下一个字节。

您可以使用以下模块来计算输入流的奇偶校验(它是一个带复位的TFF)。预期的用途是,应该给它输入位流,并在适当的时间重置,以便它计算每个字节中1位的数量。
module parity (
input clk,
input reset,
input in,
output reg odd);
always @(posedge clk)
if (reset) odd <= 0;
else if (in) odd <= ~odd;

endmodule
请注意,串行协议先先发送最低有效位,然后再发送8个数据位之后的奇偶校验位。
一些时序图
没有构图错误。第一个字节校验通过,第二个字节失败。
请添加图片描述

Verilog代码:

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //
	parameter idle=0,start=1,s0=2,s1=3,s2=4,s3=5,s4=6,s5=7,s6=8,s7=9,s8=10,stop=11,WAIT=12;
    wire[3:0] state,next;
    wire odd_bit;
    reg odd;
    wire res;
    always @(*)
        begin
            case(state)
                idle: next=in? idle:start;
                start:next=s0;
                s0:next=s1;
                s1:next=s2;
                s2:next=s3;
                s3:next=s4;
                s4:next=s5;
                s5:next=s6;
                s6:next=s7;
                s7:next=s8;
                s8:next=in?stop:WAIT;
                stop: next=in? idle:start;
                WAIT: next=in? idle:WAIT;
            endcase
        end
     always @(posedge clk)
        begin
            if(reset)
                state<=idle;
            else
                state<=next;
        end
    assign done=(odd==0&&state==stop);
    always@(posedge clk)
        begin
            case(state)
                start:out_byte[0]<=in;
                s0:out_byte[1]<=in;
                s1:out_byte[2]<=in;
                s2:out_byte[3]<=in;
                s3:out_byte[4]<=in;
                s4:out_byte[5]<=in;
                s5:out_byte[6]<=in;
                s6:out_byte[7]<=in;
                s7: odd_bit<=in;
                default: out_byte<=out_byte;
            endcase
        end
    always@(*)
        begin
            if(state==idle||state==stop)
                res<=1;
            else
                res<=0;
        end
    parity u0(clk,res,in,odd);
endmodule

3.2.5.19 Sequence recognition
问题陈述:

同步HDLC成帧涉及对数据的连续比特流进行解码,以寻找指示帧(数据包)开始和结束的比特模式。恰好看到六个连续的1 (即01111110)是指示帧边界的“标志”,发送方在5个连续的1后插入一个零,接收方必须检测并丢弃该0。如果有7个或者更多连续的1,我们还需要发出错误信号。
创建一个有限状态机来识别这三个序列:

0111110: 需要丢弃信号位(disc)。
01111110: 标记帧的开始/结束(flag)。
01111111…: 错误(7个或更多1s)(err)
当FSM被重置时,应该处于一个状态,就像之前的输入为0一样。
一下是一些说明所需操作的示例序列。
丢弃0111110:
请添加图片描述
标志01111110:
请添加图片描述
重置行为和错误01111111…:请添加图片描述

Verilog代码:

module top_module(
    input clk,
    input reset,    // Synchronous reset
    input in,
    output disc,
    output flag,
    output err);
	parameter s0=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,ERROR=7,DISC=8,FLAG=9;
    wire [3:0] state,next;
    always@(posedge clk)
        begin
            if(reset)
                state<=s0;
            else
                state<=next;
        end
    always@(*)
        begin
            case(state)
                s0:next=in?s1:s0;
                s1:next=in?s2:s0;
                s2:next=in?s3:s0;
                s3:next=in?s4:s0;
                s4:next=in?s5:s0;
                s5:next=in?s6:DISC;
                s6:next=in?ERROR:FLAG;
                ERROR:next=in?ERROR:s0;
                DISC:next=in?s1:s0;
                FLAG:next=in?s1:s0;
            endcase
        end
    assign err=(state==ERROR);
    assign flag=(state==FLAG);
    assign disc=(state==DISC);
                    
endmodule

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值