HDLBITS 笔记36:FSM串行、FSM串行数据

目录

题目1:serial receiver(FSM串行)

题目2:Fsm serialdata(FSM串行数据 )


 

题目1:serial receiver(FSM串行)

在许多(较旧的)串行通信协议中,每个数据字节都与一个起始位和一个停止位一起发送,以帮助接收方将字节与位流分隔开来。一种常见的方案是使用一个起始位 (0)、8 个数据位和 1 个停止位 (1)。当没有任何内容被传输(空闲)时,该线路也位于逻辑 1 处。

设计一个有限的状态机,该状态机将在给定位流时识别何时正确接收字节。它需要识别起始位,等待所有8个数据位,然后验证停止位是否正确。如果停止位未按预期出现,则 FSM 必须等到找到停止位后再尝试接收下一个字节。

无错误:

HDLBITS 笔记36:FSM串行、FSM串行数据_第1张图片

未找到停止位。丢弃第一个字节:

HDLBITS 笔记36:FSM串行、FSM串行数据_第2张图片

其中,状态图如下:

最终代码编写如下:

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    parameter s0 = 2'd0,s1 = 2'd1,s2 = 2'd2,s3 = 2'd3;
    reg [1:0] state ,next_state;
    reg [3:0] count;
    //组合逻辑
    always @(*)
        begin
            case(state)
                s0:begin
                    if(in == 1'b0)
                        next_state = s1;
                    else
                        next_state = s0;
                end
                s1:begin
                    if(count == 4'b0111)
                        next_state = s2;
                    else
                        next_state = s1;
                end
                s2:begin
                    if(in== 1'b0)
                        next_state = s3;
                    else
                        next_state = s0;
                end
                s3:begin
                    if(in == 1'b0)
                        next_state = s3;
                    else
                        next_state = s0;
                end
                default:next_state = s0;
            endcase
        end
                //时序逻辑
                always @(posedge clk)
                    begin
                        if(reset)
                            state <= s0;
                        else
                            state <= next_state;
                    end
    //输出逻辑
    always @(posedge clk)
        begin
            case(state)
                s0:begin
                    count <= 1'b0;
                    done <= 1'b0;
                end
                s1:begin
                    count = count+1'b1;
                end
                s2:begin
                    if(in == 1'b0)
                    done <= 1'b0;
                    else
                    done <= 1'b1;
                end
                s3:begin
                    count <= 1'b0;
                    done <= 1'b0;
                end
            endcase
        end
          
endmodule

仿真结果如下:

HDLBITS 笔记36:FSM串行、FSM串行数据_第3张图片

使用quartus ii 画出RTL 图: 注意在使用quartus ii 软件画rtl的时候,应该将done定义为reg型,否则软件会报错。即需要将output done改写为output reg done。

HDLBITS 笔记36:FSM串行、FSM串行数据_第4张图片

 状态流程图:

HDLBITS 笔记36:FSM串行、FSM串行数据_第5张图片

题目2:Fsm serialdata(FSM串行数据 )

现在,您已经有了一个有限的状态机,可以识别串行比特流中何时正确接收字节,请添加一个数据路径,该路径将输出正确接收的数据字节。out_byte需要有效,当完成为1时,否则就不在乎了。

请注意,串行协议首先发送最低有效位。

HDLBITS 笔记36:FSM串行、FSM串行数据_第6张图片

模块声明

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

分析:相比于上一题增加了一个输出端,其余不变。

代码编写如下:

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

    parameter s0 = 2'd0,s1 = 2'd1,s2 = 2'd2,s3 = 2'd3;
    reg [1:0] state ,next_state;
    reg [3:0] count;//计数器
    reg [7:0] temp;//作为缓存寄存器
    //组合逻辑
    always @(*)
        begin
            case(state)
                s0:begin
                    if(in == 1'b0)
                        next_state = s1;
                    else
                        next_state = s0;
                end
                s1:begin
                    if(count == 4'b0111)
                        next_state = s2;
                    else
                        next_state = s1;
                end
                s2:begin
                    if(in== 1'b0)
                        next_state = s3;
                    else
                        next_state = s0;
                end
                s3:begin
                    if(in == 1'b0)
                        next_state = s3;
                    else
                        next_state = s0;
                end
                default:next_state = s0;
            endcase
        end
                //时序逻辑
                always @(posedge clk)
                    begin
                        if(reset)
                            state <= s0;
                        else
                            state <= next_state;
                    end
    //输出逻辑
    always @(posedge clk)
        begin
            case(state)
                s0:begin//起始状态,还未读取数据
                    count <= 1'b0;
                    done <= 1'b0;
                end
                s1:begin//起始位,从s1到s2为数据传输过程
                    temp[count] <= in;//从in中开始读取数据,count作为temp索引
                    count = count+1'b1;//每读取一次则加1
                end
                s2:begin //进入s2,完成了读取数据的过程
                    if(in == 1'b0)
                    done <= 1'b0;
                    else
                    done <= 1'b1;
                    out_byte <= temp;
                end
                s3:begin
                    count <= 1'b0;
                    done <= 1'b0;
                end
            endcase
        end
          
endmodule

仿真结果:

HDLBITS 笔记36:FSM串行、FSM串行数据_第7张图片

  使用quartus ii 画出RTL 图: 注意在使用quartus ii 软件画rtl的时候,应该将done、out_byte定义为reg型,否则软件会报错。即需要将output done改写为output reg done,将output [7:0] out_byte改写为output reg [7:0] out_byte。

HDLBITS 笔记36:FSM串行、FSM串行数据_第8张图片

 状态转移图:

HDLBITS 笔记36:FSM串行、FSM串行数据_第9张图片

 通过观察题目1和题目2的状态转移图可知,两者的状态转移是一样的,这是因为两个题目的区别只是输出逻辑不同,时序逻辑是相同的。 观察两个题目的rtl图,可知在题目2中增加了8个缓冲寄存器temp和8个2选1数据选择器,这是因为在代码中增加了相应的数据缓冲器作为out_byte的输出缓存。

代码参考:HDLbits---Fsm serialdata_离离离谱的博客-CSDN博客

你可能感兴趣的:(HDLBITS学习笔记,fpga开发)