HDLBits-Fsm serialdata

在许多(较旧的)串行通信协议中,每个数据字节与一个起始位和一个停止位一起发送,以帮助接收器从比特流中划分字节。一种常见的方案是使用一个起始位(0)、8个数据位和1个停止位(1)。当无任何传输(空闲)时,线路也处于逻辑1。

 

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

现在,您有了一个有限状态机,可以识别在串行位流中何时正确接收字节,添加一个数据路径,该路径将输出正确接收的数据字节。当done为1时,out_字节必须有效,否则为don-care。
请注意,串行协议首先发送最低有效位。

cnt都是从0开始的,上升沿加1

cnt计数器,计算接收的数据数量0-7 ,cnt=8时候判断in是否为停止位,来判断是否进入stop状态

n_state比c_state早一拍

如果使用c_state,那么会丢失第一个数字

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

    // Use FSM from Fsm_serial
    parameter idle    =3'd0;
    parameter start   =3'd1;
    parameter data    =3'd2;
    parameter stop 	  =3'd3;
    parameter hunluan =3'd4;
    reg [2:0] c_state,n_state;
    always@(posedge clk)begin
        if(reset)
            c_state<=idle;
        else
            c_state<=n_state;	
    end
    
    always@(*)begin
        case(c_state)
            idle   :n_state=(in==0)?start:idle;
            start  :n_state=data;
            //没有接收到停止位,这个字节被抛弃
            //直到等到停止位,才开始下一个字节
            data   :n_state=(cnt==8)?((in==1)?stop:hunluan):data;
            hunluan:n_state=(in)?idle:hunluan;
            stop   :n_state=(in==0)?start:idle;
        endcase  
    end
    reg [3:0]cnt;
    always@(posedge clk)begin
        if(reset)
            cnt<=0;
        else if(n_state==data)
            cnt<=cnt+1'b1;
        else
            cnt<=0;   //其他状态下cnt为0
    end
    
    assign done=(c_state==stop);

    // New: Datapath to latch input bits.
    reg [7:0]out;
    always@(posedge clk)begin
        if(reset)
            out<=0;
        else if(n_state==data)
            out[cnt]<=in;
            //out<={in,out[7:1]};
        else
            out<=out;
    end
    assign out_byte=out;

endmodule

我们想给串行接收器增加奇偶校验。奇偶校验在每个数据字节后添加一个额外的位。我们将使用奇数奇偶校验,其中接收到的9位中的1数必须是奇数。例如,101001011满足奇数奇偶校验(有5个1),但001001011不满足。
更改FSM和数据路径以执行奇数奇偶校验。仅当正确接收字节且奇偶校验通过时,才断言done信号。与串行接收器FSM一样,该FSM需要识别起始位,等待所有9位(数据和奇偶校验),然后验证停止位是否正确。如果停止位未按预期出现,则FSM必须等到找到停止位后再尝试接收下一个字节。

您可以使用以下模块来计算输入流的奇偶校验(这是一个带重置的TFF)。其预期用途是,应为其提供输入位流,并在适当的时间重置,以便其计算每个字节中的1位数。

两种做法

方法一:仍然使用n_state

方法二:状态start和data结合在一起,那么就可以使用c_state

奇偶校验的关键:奇偶模块的复位信号,在方法一n_state!=data时候有效,

                                                                    方法二c_state!=start时候有效

注意:奇偶校验的前提是有停止位,在组合逻辑中判断

            有停止位并且奇偶校验为1,那么进入stop状态

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //
	wire odd;
    // Modify FSM and datapath from Fsm_serialdata
	// Use FSM from Fsm_serial
    parameter idle    =3'd0;
    parameter start   =3'd1;
    parameter data    =3'd2;
    parameter stop 	  =3'd3;
    parameter hunluan =3'd4;
    reg [2:0] c_state,n_state;
    always@(posedge clk)begin
        if(reset)
            c_state<=idle;
        else
            c_state<=n_state;	
    end
    
    always@(*)begin
        case(c_state)
            idle   :n_state=(in==0)?start:idle;
            start  :n_state=data;
            //没有接收到停止位,这个字节被抛弃
            //直到等到停止位,才开始下一个字节
            //没有接收到停止位,就不用谈及奇偶校验,停止位优先级高
            data   :if(cnt==9)
                		if(in)
                            if(odd)
                            	n_state<=stop;
            				else
                                n_state<=idle;
            			else
                            n_state<=hunluan;
            		else
                        n_state<=data;
            hunluan:n_state=(in)?idle:hunluan;
            stop   :n_state=(in==0)?start:idle;
        endcase  
    end
    reg [3:0]cnt;
    always@(posedge clk)begin
        if(reset)
            cnt<=0;
        else if(n_state==data)
            cnt<=cnt+1'b1;
        else
            cnt<=0;   //其他状态下cnt为0
    end
    
    assign done=(c_state==stop);

    // New: Datapath to latch input bits.
    reg [7:0]out;
    always@(posedge clk)begin
        if(reset)
            out<=0;
        else if((n_state==data)&&(cnt<=7))
            out[cnt]<=in;
            //out<={in,out[7:1]};
        else
            out<=out;
    end
    assign out_byte=out;
    // New: Add parity checking.
	parity u_parity (
        .clk(clk),
        .reset(n_state!=data),
        .in(in),
        .odd(odd));
endmodule
module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //
 	wire odd;
    // Modify FSM and datapath from Fsm_serialdata
	parameter idle    =2'd0;
    parameter start   =2'd1;
    //parameter data    =3'd2;
    parameter stop 	  =2'd2;
    parameter hunluan =2'd3;
    reg [1:0] c_state,n_state;
    always@(posedge clk)begin
        if(reset)
            c_state<=idle;
        else
            c_state<=n_state;	
    end
    
    always@(*)begin
        case(c_state)
            idle   :n_state=(in==0)?start:idle;
            //没有接收到停止位,这个字节被抛弃
            //直到等到停止位,才开始下一个字节
            start   :if(cnt==9)
                		if(in)
                			if(odd)
                            	n_state=stop;
            				else
                                n_state=idle;
            			else
                            n_state=hunluan;
            		else
                       n_state=start; 
            hunluan:n_state=(in)?idle:hunluan;
            stop   :n_state=(in==0)?start:idle;
        endcase  
    end
    reg [3:0]cnt;
    always@(posedge clk)begin
        if(reset)
            cnt<=0;
        else if(c_state==start)
            cnt<=cnt+1'b1;
        else
            cnt<=0;
    end
        // New: Datapath to latch input bits.
    reg [7:0]out;
    always@(posedge clk)begin
        if(reset)
            out<=0;
        else if(c_state==start&&cnt<=4'd7)
            out[cnt]<=in;
            //out<={in,out[7:1]};
        else
            out<=out;
    end
    assign out_byte=out;
    
    assign done=(c_state==stop);
    // New: Add parity checking.
	parity u_parity (
        .clk(clk),
        .reset(!(c_state==start)),
        .in(in),
        .odd(odd));

endmodule

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值