HDLBits刷题合集—17 Finite State Machines-3

HDLBits刷题合集—17 Finite State Machines-3

HDLBits-133 Fsm onehot

Problem Statement
给定以下具有1个输入和2个输出的状态机:
假设此状态机使用独热编码,其中state[0]至state[9]分别对应于状态S0至S9。 除非另有说明,否则输出为零。

实现状态机的状态转换逻辑和输出逻辑部分(但不实现状态触发器)。 你将给定state[9:0]中的当前状态,并且必须产生next_state [9:0]和两个输出。通过假设独热编码,通过检验推导出逻辑方程 。(测试台将使用非独热码输入进行测试,以确保你没有尝试做更复杂的事情)。

HDLBits刷题合集—17 Finite State Machines-3_第1张图片

Hint:可以通过查看状态转换图的in部分,来推导出独热状态转换逻辑的逻辑方程式。

代码如下:

module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);
    
    assign next_state[0] = ~in & (state[0]|state[1]|state[2]|state[3]|state[4]|state[7]|state[8]|state[9]);
    assign next_state[1] = in & (state[0] | state[8] | state[9]);
    assign next_state[2] = in & state[1];
    assign next_state[3] = in & state[2];
    assign next_state[4] = in & state[3];
    assign next_state[5] = in & state[4];
    assign next_state[6] = in & state[5];
    assign next_state[7] = in & (state[6] | state[7]);
    assign next_state[8] = ~in & state[5];
    assign next_state[9] = ~in & state[6];
    
    assign out1 = state[8] | state[9];
    assign out2 = state[7] | state[9];

endmodule

HDLBits-134 Fsm ps2

Problem Statement
PS / 2鼠标协议发送三字节长的消息。 但是,在连续的字节流中,消息的开始和结束位置并不明显。 唯一的指示是,每个三字节消息的第一个字节始终具有bit[3] = 1(但其他两个字节的bit [3]取决于数据,可能是1或0)。

我们需要一个有限状态机,当给定输入字节流时它将搜索消息边界。 我们将使用的算法是丢弃字节,直到看到bit [3] = 1的字节为止。 然后,我们假定这是消息的字节1,并且一旦接收到所有3个字节(完成),就发出接收消息的信号。

在成功接收到每个消息的第三个字节之后,FSM应该立即在周期中发出完成信号。

在无错误条件下,每三个字节形成一条消息:

HDLBits刷题合集—17 Finite State Machines-3_第2张图片
出现错误时,搜索字节1:

HDLBits刷题合集—17 Finite State Machines-3_第3张图片

请注意,这与1xx序列识别器不同。 此处不允许重叠序列:

HDLBits刷题合集—17 Finite State Machines-3_第4张图片
Hint:尽管in[7:0]是一个字节,但是FSM只有一个输入:in[3]。你需要大约4个状态。 三种状态可能不起作用,因为其中一种状态需要断言完成,并且对于每个收到的消息,仅在一个周期内断言完成状态。

代码如下:

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
    reg [1:0] state,state_next;
	parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3;
	
    // State transition logic (combinational)
    always @(*) begin
        case (state)
            S0 : begin
                if (in[3]==1) state_next <= S1;
                else state_next <= S0;
            end
            S1 : begin
                state_next <= S2;
            end
            S2 : begin
                state_next <= S3;
            end
            S3 : begin
                if (in[3]==1) state_next <= S1;
                else state_next <= S0;
            end
        endcase
    end
    // State flip-flops (sequential)
    always @(posedge clk) begin
        if (reset)
            state <= S0;
        else
            state <= state_next;
    end
    // Output logic
    assign done = (state == S3);
endmodule

HDLBits-135 Fsm ps2data

Problem Statement
另请参阅:上一题Fsm ps2。

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

断言完成信号时,out_bytes必须有效。 你可能会在其他时间输出任何内容(即,don’t-care)。

例如:

HDLBits刷题合集—17 Finite State Machines-3_第5张图片
代码如下:

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

    // FSM from fsm_ps2
	reg [1:0] state,state_next;
    reg [23:0] data;
	parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3;
	
    // State transition logic (combinational)
    always @(*) begin
        case (state)
            S0 : begin
                if (in[3]==1) state_next <= S1;
                else state_next <= S0;
            end
            S1 : begin
                state_next <= S2;
            end
            S2 : begin
                state_next <= S3;
            end
            S3 : begin
                if (in[3]==1) state_next <= S1;
                else state_next <= S0;
            end
        endcase
    end
    // State flip-flops (sequential)
    always @(posedge clk) begin
        if (reset)
            state <= S0;
        else
            state <= state_next;
    end
    // Output logic
    assign done = (state == S3);
    
    // New: Datapath to store incoming bytes.
	always @(posedge clk) begin
        if (reset) begin
            data <= 24'd0;
        end
        else begin
            data[23:16] <= data[15:8];
            data[15:8] <= data[7:0];
            data[7:0]  <= in;
        end
    end
    assign out_bytes = (done) ? data : 24'd0;
endmodule

HDLBits-136 Fsm serial

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

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

无错误的情况:

HDLBits刷题合集—17 Finite State Machines-3_第6张图片

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

HDLBits刷题合集—17 Finite State Machines-3_第7张图片
代码如下:

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    reg [3:0] state, state_next;
    parameter START=0, S0=1, S1=2, S2=3, S3=4, S4=5, S5=6, S6=7, S7=8, S8=9, DONE0=10, DONE1=11;
    
    always @(*) begin
        case (state)
            START : begin
                if (in == 0) state_next <= S0;
                else state_next <= START;
            end
            S0    : begin
                state_next <= S1;
            end
            S1    : begin
                state_next <= S2;
            end
            S2    : begin
                state_next <= S3;
            end
            S3    : begin
                state_next <= S4;
            end
            S4    : begin
                state_next <= S5;
            end
            S5    : begin
                state_next <= S6;
            end
            S6    : begin
                state_next <= S7;
            end
            S7    : begin
                state_next <= S8;
            end
            S8    : begin
                if (in == 1) state_next <= DONE1;
                else  state_next <= DONE0;
            end 
            DONE0  : begin
                if (in == 1) state_next <= START;
                else  state_next <= DONE0;
            end
             DONE1 : begin
                 if (in == 1) state_next <= START;
                else  state_next <= S0;
             end
            default: begin
               state_next <= START;
            end
        endcase
    end
    
    always @(posedge clk) begin
            if(reset) 
                state <= START;
            else 
                state <= state_next;
    end
    		
    assign done = (state == DONE1);
    
endmodule

HDLBits-137 Fsm serialdata

Problem Statement
另请参阅:上一题Fsm serial。

现在已经有了一个有限状态机,可以确定何时在串行位流中正确接收了字节,添加一个数据路径,它将输出正确接收的数据字节。 当完成为1时,out_byte需要有效,否则don’t-care。

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

HDLBits刷题合集—17 Finite State Machines-3_第8张图片
代码如下:

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //
	reg [3:0] state, state_next;
    parameter START=0, S0=1, S1=2, S2=3, S3=4, S4=5, S5=6, S6=7, S7=8, S8=9, DONE0=10, DONE1=11;
    
    always @(*) begin
        case (state)
            START : begin
                if (in == 0) state_next <= S0;
                else state_next <= START;
            end
            S0    : begin
                state_next <= S1;
            end
            S1    : begin
                state_next <= S2;
            end
            S2    : begin
                state_next <= S3;
            end
            S3    : begin
                state_next <= S4;
            end
            S4    : begin
                state_next <= S5;
            end
            S5    : begin
                state_next <= S6;
            end
            S6    : begin
                state_next <= S7;
            end
            S7    : begin
                state_next <= S8;
            end
            S8    : begin
                if (in == 1) state_next <= DONE1;
                else  state_next <= DONE0;
            end 
            DONE0  : begin
                if (in == 1) state_next <= START;
                else  state_next <= DONE0;
            end
             DONE1 : begin
                 if (in == 1) state_next <= START;
                else  state_next <= S0;
             end
            default: begin
               state_next <= START;
            end
        endcase
    end
    
    reg [7:0] out_byte_mid;
    
    always @(posedge clk) begin
            if(reset) 
                state <= START;
            else 
                state <= state_next;
    		end
     assign done = (state == DONE1);
     
	 always@(*) begin
        case(state)
            START: begin
                ;
            end
            S0: begin
                out_byte_mid[0] <= in;
            end
            S1: begin
                out_byte_mid[1] <= in;
            end
            S2: begin
                out_byte_mid[2] <= in;
            end
            S3: begin
                out_byte_mid[3] <= in;
            end
            S4: begin
                out_byte_mid[4] <= in;
            end
            S5: begin
                out_byte_mid[5] <= in;
            end
            S6: begin
                out_byte_mid[6] <= in;
            end
            S7: begin
                out_byte_mid[7] <= in;
            end
            S8: begin
                ;
            end
            DONE0: begin
                ;
            end
            DONE1: begin
                ;
            end
            default: begin
                ;
            end
            
        endcase
    end
    
    assign out_byte = (done == 1) ? out_byte_mid : 'bz;
    
endmodule

HDLBits-138 Fsm serialdp

Problem Statement
另请参阅:上一题Fsm serialdata。

我们要向串行接收器添加奇偶校验。奇偶校验在每个数据字节后增加一个额外的位。我们将使用奇数奇偶校验,其中接收到的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

注意,串行协议先发送最低有效位,然后发送奇偶校验位。

没有成帧错误。 奇偶校验通过第一个字节,失败通过第二个字节。

HDLBits刷题合集—17 Finite State Machines-3_第9张图片

代码如下:

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

    // Modify FSM and datapath from Fsm_serialdata
    parameter idle = 4'd0, start = 4'd1, trans0 = 4'd2,trans1 = 4'd3, trans2 = 4'd4, trans3 = 4'd5;
    parameter trans4 = 4'd6, trans5 = 4'd7, trans6 = 4'd8, trans7 = 4'd9, stop = 4'd10, err = 4'd11, pari = 4'd12;
    reg [3:0] state, next_state;
    reg [7:0] data;
    wire odd, reset_p;
    reg done_reg;

    always @(*) begin
        case (state)
            idle:   next_state <= in ? idle : start;
            start:  next_state <= trans0;
            trans0: next_state <= trans1;
            trans1: next_state <= trans2;
            trans2: next_state <= trans3;
            trans3: next_state <= trans4;
            trans4: next_state <= trans5;
            trans5: next_state <= trans6;
            trans6: next_state <= trans7;
            trans7: next_state <= pari;
            pari:   next_state <= in ? idle : err;
            err:    next_state <= in ? idle : err;
        endcase
    end

    always @(posedge clk) begin
        if (reset) begin
            state <= idle;
        end
        else begin
            state <= next_state;
        end
    end

    // New: Add parity checking.
    always @(posedge clk) begin
        if (reset) begin
            data <= 8'd0;
            reset_p <= 1'b1;
            done_reg <= 1'b0;
        end
        else begin
            if (next_state == trans0 || next_state == trans1 || next_state == trans2 || next_state == trans3 || next_state == trans4 || next_state == trans5 || next_state == trans6 || next_state == trans7) begin
                data <= {in, data[7:1]};
            end
            else if (next_state == start) begin
                data <= 8'd0;
                reset_p <= 1'b0;
                done_reg <= 1'b0;
            end
            else if (next_state == idle) begin
                done_reg <= odd;
            end
            else if (next_state == pari) begin
                reset_p <= 1'b1;
            end
        end
    end

    assign done = done_reg;
    assign out_byte = done ? data : 8'd0;
    parity par_mod(clk, reset | reset_p, in, odd);

endmodule

HDLBits-139 Fsm hdlc

Problem Statement
Synchronous HDLC framing涉及对数据的连续位流进行解码,以寻找指示帧(数据包)开始和结束的位模式。 恰好看到6个连续的1(即01111110)是表示帧边界的“flag”。 为了避免数据流意外包含“flag”,发送方必须在每5个连续的1秒后插入一个零,接收方必须检测并丢弃。 如果连续7个或更多1,我们还需要发出错误信号。

创建一个有限状态机来识别这三个序列:

0111110:信号位需要丢弃(disc)。
01111110:标记帧的开始/结束(flag)。
01111111 …:错误(7或更多1s)(err)。
重置FSM时,其状态应类似于先前的输入为0。

以下是一些示例序列,它们说明了所期望的操作。

Discard 0111110:
HDLBits刷题合集—17 Finite State Machines-3_第10张图片
Flag 01111110:
HDLBits刷题合集—17 Finite State Machines-3_第11张图片

Reset behaviour and error 01111111…:
HDLBits刷题合集—17 Finite State Machines-3_第12张图片
Hint:
使用一个大约有10个状态的莫尔型状态机。

HDLBits刷题合集—17 Finite State Machines-3_第13张图片
代码如下:

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, DISC=7, FLAG=8, ERR=9;
    reg [3:0] state, state_next;
    
    always @(*) begin
        case (state)
            S0 : begin
                if (in)  state_next <= S1;
                else 	 state_next <= S0;
            end
            S1 : begin
                if (in)  state_next <= S2;
                else 	 state_next <= S0;
            end
            S2 : begin
                if (in)  state_next <= S3;
                else 	 state_next <= S0;
            end
            S3 : begin
                if (in)  state_next <= S4;
                else 	 state_next <= S0;
            end
            S4 : begin
                if (in)  state_next <= S5;
                else 	 state_next <= S0;
            end
            S5 : begin
                if (in)  state_next <= S6;
                else 	 state_next <= DISC;
            end
            S6 : begin
                if (in)  state_next <= ERR;
                else 	 state_next <= FLAG;
            end
            DISC : begin
                if (in)  state_next <= S1;
                else 	 state_next <= S0;
            end
            FLAG : begin
                if (in)  state_next <= S1;
                else 	 state_next <= S0;
            end
            ERR : begin
                if (in)  state_next <= ERR;
                else 	 state_next <= S0;
            end
        endcase
    end
    
    always @(posedge clk)
        begin
            if (reset) state <= S0;
            else state <= state_next;
        end
    
    assign disc = (state == DISC);
    assign flag = (state == FLAG);
    assign err  = (state == ERR);    
endmodule

Note
新手一枚,主要分享博客,记录学习过程,后期参考大佬代码或思想会一一列出。欢迎大家批评指正!

你可能感兴趣的:(HDLBits)