HDLbits day11

5.17、Fsm serial

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

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

 

 1)这里开始的标记是低电平,结束的标记是高电平,在开始和结束之间传输的 bit 位为8即一个字节,这是正确接收的条件,当满足该条件后会在 stop 位后面的时钟沿给出 done 的输出标记。如果不满足该条件,比如起始 start 条件不满足,则会一直等待知道接收到低电平信号才开始;又如 start 开始后,中间的位数超过了8 bit,即8 bit 后一直是低电平信号,不出现高电平的 stop 信号,则 receiver 继续等待知道出现高电平位才结束,但这是一个错误接收,不会给出 done 的输出标记。波形图如下所示。

2)设计了五个状态,分别是 IDLE, START, DATA, STOP, ERROR。这里控制状态转移的有输入信号 in 和自定义的计数器 cnt,计数器用于计数 start 和 stop 之间的位数是数据是否满足1 byte。cnt的条件判断只用在 DATA 状态中,在 DATA 状态时,cnt 实行计数,当 cnt 为8时表示真正的数据够了,此时再比较输入 in,如果 in 为高电平则数据接收正常,跳转至 STOP,否则表示出现错误,进入 ERROR。跳出 ERROR 的条件是输入in出现高电平。这里需要注意 STOP 状态可以直接跳转至 START 状态,即 in 为高电平后紧接着出现低电平情况,如果输入 in 为连续的几个高电平,则 STOP 会进入 IDLE 等待低电平到来。另外这里的 START 状态应该可以合并到 DATA 状态中实现状态机化简,可以试试。

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    
    parameter IDLE=0,START=1,DATA=2,STOP=3,ERROR=4;
    reg[2:0] state,next_state;
    integer cnt;
    reg done_r;
    
    always@(*)
        begin
            case(state)
                IDLE:next_state<=in?IDLE:START;
                START:next_state<=DATA;
                DATA:next_state<=(cnt==8)?(in?STOP:ERROR):DATA;
                STOP:next_state<=in?IDLE:START;
                ERROR:next_state<=in?IDLE:ERROR;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state<=IDLE;
            else
                state<=next_state;
        end
    
    always@(posedge clk)
        begin
            if(reset)
                cnt<=0;
            else
                case(next_state)
                    START:cnt<=0;
                    DATA:cnt<=cnt+1;
                    default:cnt<=cnt;
                endcase
        end
    
    always@(posedge clk)
        begin
            case(next_state)
                STOP:done_r<=1;
                default:done_r<=0;
            endcase
        end
    
    assign done=done_r;

endmodule

5.18、Fsm serialdata

现在您有了一个有限状态机,可以识别何时在串行比特流中正确接收到字节,添加一个数据路径来输出正确接收到的数据字节。out_byte需要在done1时有效,否则不在乎。

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

1)在上题的基础上多了一个输出,要求是当正确接收数据时做出输出,即在 done 信号为高电平时做出输出。

2)所以该题代码与上题基本一致,只需要多一个8 bit 寄存器来寄存得到的数据并在 done 信号为高电平时候输出即可。

3)这里需要使用移位寄存器来实现移位寄存,可以从波形图看出这是右移寄存器,因为不确定接收到的数据是否正确,所以只需不断移位寄存即可,当 done 信号为正时进行输出即为正确接收到的数据。

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); 
    
    parameter IDLE=0,START=1,DATA=2,STOP=3,ERROR=4;
    reg[2:0] state,next_state;
    integer cnt;
    reg done_r;
    reg[7:0] shiff_r;
    
    always@(*)
        begin
            case(state)
                IDLE:next_state<=in?IDLE:START;
                START:next_state<=DATA;
                DATA:next_state<=(cnt==8)?(in?STOP:ERROR):DATA;
                STOP:next_state<=in?IDLE:START;
                ERROR:next_state<=in?IDLE:ERROR;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state<=IDLE;
            else
                state<=next_state;
        end
    
    always@(posedge clk)
        begin
            if(reset)
                cnt<=0;
            else
                case(next_state)
                    START:cnt<=0;
                    DATA:cnt<=cnt+1;
                    default:cnt<=cnt;
                endcase
        end
    
    always@(posedge clk)
        begin
            case(next_state)
                STOP:done_r<=1;
                default:done_r<=0;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                shiff_r<=0;
            else
                case(next_state)
                    START:shiff_r<=0;
                    DATA:shiff_r<={in,shiff_r[7:1]};
                endcase
        end
    
    assign done=done_r;
    assign out_byte=shiff_r;

endmodule

5.19、Fsm serialdp

我们想为串行接收器添加奇偶校验。奇偶校验在每个数据字节后增加一位。我们将使用奇校验,其中接收到的 9 位中1的数量必须是奇数。例如,101001011满足奇校验(有 5 个1 s),但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 个数据位之后的奇偶校验位。

1)该题采用的是奇校验的方式,并且提供了奇偶校验模块。

2)原本 start 和 stop 位之间的8 bit 变为了9 bit,新增的1 bit 为奇校验位,从而使得这9 bit 中“1”的数量为奇数个,即题目中提供的奇偶校验模块输出为1时表面数据正确,否则数据错误不予接收。

3)这里需要改变状态机,因为多了检查位,所以增添了 CHECK 状态,并且这里把 START 状态和 DATA 状态合并到了一起。状态机描述如下。之前通过计数器是否为8来判断进入 STOP 状态还是 ERROR 状态,这里通过计数器是否为8来判断是否进入 CHECK 状态。

1)代码中多了 odd 和 start 变量,odd 是出题人提供的奇偶校验模块的输出,由 odd 是否为1判断校验是否正确。这里需要注意的是 start,该变量用于控制奇偶校验模块的开启。

2)需要注意,奇偶校验模块不能一直开启,只有当开始接收数据,即出现起始标记后才开启,并且每次开启时需要复位从头进行,否则前面计算得到的 odd 输出会对下一次判断产生影响造成错误。简单来说就是每次接收新一字节数据时要重启奇偶校验模块。正是因为这个原因,所以在逻辑 always 块中,针对当前状态为 IDLE 或 STOP 时,需要将 start 置1,因为只有这两个状态的后一个状态可能是 DATA 状态。

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); 
    
    parameter IDLE = 0, DATA = 1, CHECK = 2, STOP = 3, ERROR = 4;
    reg [2:0] state,next_state;
    integer cnt;
    reg [7:0] out;
    reg check;
    wire odd,start;
    
    parity parity_inst(.clk(clk),.reset(reset | start),.in(in),.odd(odd));
    
    //transition
    always@(*)begin
        start = 0;
        case(state)
            IDLE:begin next_state=in?IDLE:DATA; start=1; end
            DATA:next_state=(cnt==8)?CHECK:DATA;
            CHECK:next_state=in?STOP:ERROR;
            STOP:begin next_state=in?IDLE:DATA; start=1; end
            ERROR:next_state=in?IDLE:ERROR;
        endcase
    end
    
     //state
    always@(posedge clk)begin
        if(reset)
            state<=IDLE;
        else
            state<=next_state;
    end
    
    //cnt
    always@(posedge clk)begin
        if(reset)
            cnt<=0;
        else
            case(state)
                DATA:cnt<=cnt+1;
                default:cnt<=0;
            endcase
    end
    
    //out
    always@(posedge clk)begin
        if(reset)
            out<=0;
        else
            case(next_state)
                DATA:out<={in,out[7:1]};
            endcase
    end
    
    //check
    always@(posedge clk)begin
        if(reset)
            check<=0;
        else
            check<=odd;
    end
    
    assign out_byte=out;
    assign done=check&(state==STOP);

endmodule

 5.20、fsm hdlc

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

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

  • 0111110 : 需要丢弃信号位(光盘)。
  • 01111110:标记帧的开始/结束(标志)。
  • 01111111...:错误(7 个或更多 1s)(err)。

当 FSM 被重置时,它应该处于一个状态,就像之前的输入为 0 一样。

以下是一些说明所需操作的示例序列。

module top_module(
    input clk,
    input reset,    // Synchronous reset
    input in,
    output disc,
    output flag,
    output err);
    
    parameter NONE=0,ONE=1,TWO=2,THREE=3,FOUR=4,FIVE=5,SIX=6,ERROR=7,DISCARD=8,FLAG=9;
    reg [3:0] state,next_state;
    
    always@(*)
        begin
            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
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state<=NONE;
            else
                state<=next_state;
        end
    
    assign disc=(state==DISCARD);
    assign flag=(state==FLAG);
    assign err=(state==ERROR);

endmodule

5.21、Exams/ece241 2013 q8

实现一个Mealy类型的有限状态机,它可以识别名为x的输入信号上的序列“101” 。您的 FSM 应该有一个输出信号z,当检测到“101”序列时,它被断言为逻辑 1。您的 FSM 还应该有一个低电平有效异步复位。您的状态机中可能只有 3 个状态。您的 FSM 应该能够识别重叠序列。

module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z ); 
    
    parameter A=0,B=1,C=2;
    reg [1:0] state,next_state;
    
    always@(*)
        begin
            case(state)
                A:next_state<=x?B:A;
                B:next_state<=x?B:C;
                C:next_state<=x?B:A;
            endcase
        end

    always@(posedge clk or negedge aresetn)
        begin
            if(!aresetn)
                state<=A;
            else
                state<=next_state;
        end
    
    assign z=(state==C && x==1);
endmodule

5.22、Exams/ece241 2014 q5a

你要设计一个单输入单输出串行 2 的补码摩尔状态机。输入 (x) 是一系列位(每个时钟周期一个),从数字的最低有效位开始,输出 (Z) 是输入的 2 进制的补码。机器将接受任意长度的输入数字。该电路需要异步复位转换在释放复位时开始,在复位停止

​ 1)补码规则:正数为原码,负数为原码取反加一。

​2) 本题中,当输入全为0时,认为是正数,z直接输出。当x出现第一位1时,认为输入二进制数据为负数,此时补码扔为输入本身,例如1_0000_0000补码仍为1_0000_0000。出现第一位1之后的输入位,根据补码规则,应取反,例如1001_0000_0000的补码为1111_0000_0000。

​ 3)根据上述规则,可以确定三个状态

module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    parameter A=0,B=1,C=2;
    reg[1:0] state,next_state;
    
    always@(*)
        begin
            case(state)
                A:next_state<=x?B:A;
                B:next_state<=x?C:B;
                C:next_state<=x?C:B;
            endcase
        end
    
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                state<=A;
            else
                state<=next_state;
        end
    
    assign z=(state==B);

endmodule

5.23、Exams/ece241 2014 q5b

下图是 2 进制补码的Mealy机器实现。使用 one-hot 编码实现。

 
module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    parameter A=1,B=2;
    reg[1:0] state,next_state;
    
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                state<=A;
            else
                state<=next_state;
        end
    
    always@(*)
        begin
            case(state)
                A:next_state<=x?B:A;
                B:next_state<=B;
            endcase
        end
    
    assign z=(state==A&&x)||(state==B&&~x);
    
endmodule

5.24、Exams/2014 q3fsm

考虑一个具有输入s和w的有限状态机。假设 FSM 以称为A的复位状态开始,如下所示。只要s = 0, FSM 就保持在状态A ,当s = 1 时,它移动到状态 B。一旦处于状态B,FSM在接下来的三个时钟周期内检查输入w的值。如果w = 1 在恰好两个时钟周期中,则 FSM 必须 在下一个时钟周期中将输出z设置为 1。否则z必须为 0。FSM 继续检查w接下来的三个时钟周期,依此类推。下面的时序图说明了不同w值所需的z值。

使用尽可能少的状态。请注意,s输入仅用于状态A,因此您只需要考虑w输入。

 

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
    
    parameter A=0,B=1;
    reg state,next_state;
    integer count;//计数B状态下的周期数
    integer i;//计数B状态下,3个连续周期中1的个数

    //状态逻辑变化
    always@(*)
        begin
            case(state)
                A:next_state<=s?B:A;
                B:next_state<=B;
            endcase
        end
   
    //触发信号到来时信号变化
    always@(posedge clk)
        begin
            if(reset)
                state<=A;
            else
                state<=next_state;
        end
  
    //需要对周期计数,也需要对3bit的数据进行求和,每接受3个触发信号需要对和清零。
    always@(posedge clk)
        begin
            if(reset|state==A)
                begin
                    count<=0;
                    i<=0;
                end
            else
                begin
                    if(count<=2)
                        count<=count+1;
                    else
                        count<=1;//当cle==3时,回到1开始计数而不是0,循环“1-2-3”而不是“0-1-2-3”
                    if(count==3)
                        i<=w; //求和cout,当一个周期结束时,cout==w,即可重新开始求和。
                    else
                        i<=i+w;
                end
        end
    
    assign z=(i==2)&&(count==3);
endmodule

5.25、Exams/2014 q3bfsm

 给定如下所示的状态分配表,实现有限状态机。重置应该将 FSM 重置为状态 000。

当前状态
y[2:0]
下一个状态 Y[2:0]输出 z
x=0x=1
000 000 001 0
001 001 100 0
010 010 001 0
011 001 010 1
100 011 100 1

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input x,
    output z
);
    
    parameter A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100;
    reg [2:0] state,next_state;
    
    always@(*)
        begin
            case(state)
                A:next_state<=x?B:A;
                B:next_state<=x?E:B;
                C:next_state<=x?B:C;
                D:next_state<=x?C:B;
                E:next_state<=x?E:D;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state<=A;
            else
                state<=next_state;
        end
    
    assign z=(state==D | state==E);

endmodule

5.26、Exams/2014 q3c

给定如下所示的状态分配表,实现逻辑函数 Y[0] 和 z。

当前状态
y[2:0]
下一个状态 Y[2:0]输出 z
x=0x=1
000 000 001 0
001 001 100 0
010 010 001 0
011 001 010 1
100 011 100 1

module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    parameter A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100;
    reg [2:0] next_state;
    
    always@(*)
        begin
            case(y)
                A:next_state<=x?B:A;
                B:next_state<=x?E:B;
                C:next_state<=x?B:C;
                D:next_state<=x?C:B;
                E:next_state<=x?E:D;
            endcase
        end
   
    assign z=(y==D | y==E);
    assign Y0=(next_state==B | next_state==D);

endmodule

5.27、Exams/m2014 q6b

考虑如下所示的状态机,它有一个输入w和一个输出z

考试 m2014q6.png

假设您希望使用三个触发器和状态代码y[3:1] = 000, 001, ..., 101 分别用于状态 A、B、...、F 来实现 FSM。显示此 FSM 的状态分配表。导出触发器y[2]的下一个状态表达式。只为y[2]实现下一个状态逻辑。

module top_module (
    input [3:1] y,
    input w,
    output Y2);
    
    parameter A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100,F=3'b101;
    reg [3:1] next_state;
    
    always@(*)
        begin
            case(y)
                A:next_state<=w?A:B;
                B:next_state<=w?D:C;
                C:next_state<=w?D:E;
                D:next_state<=w?A:F;
                E:next_state<=w?D:E;
                F:next_state<=w?D:C;
            endcase
        end
    
    //assign Y2=(next_state==C|next_state==D);
    assign Y2=next_state[2];

endmodule

 5.28、Exams/m2014 q6c

考虑如下所示的状态机,它有一个输入w和一个输出z

考试 m2014q6.png

对于这一部分,假设状态分配 'y[6:1] = 000001, 000010, 000100, 001000, 010000, 100000 分别用于状态 A、B、...、F 的 one-hot 代码。

为下一状态信号 Y2 和 Y4 编写逻辑表达式。(通过假设 one-hot 编码的检查推导出逻辑方程。测试台将使用非 one hot 输入进行测试,以确保您不会尝试做更复杂的事情)。

module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);
    
    parameter A=6'b000_001,B=6'b000_010,C=6'b000_100,D=6'b001_000,E=6'b010_000,F=6'b100_000;
    reg [6:1] next_state;
    
    assign next_state[1] = (y[1]&w)|(y[4]&w);
    assign next_state[2] = y[1]&~w;
    assign next_state[3] = (y[2]&~w)|(y[6]&~w);
    assign next_state[4] = (y[2]&w)|(y[3]&w)|(y[5]&w)|(y[6]&w);
    assign next_state[5] = (y[3]&~w)|(y[5]&~w);
    assign next_state[6] = (y[4]&~w);
    
    assign Y2=next_state[2];
    assign Y4=next_state[4];

endmodule

5.29、Exams/m2014 q6

考虑如下所示的状态机,它有一个输入w和一个输出z

考试 m2014q6.png

实现状态机。(这部分不在期中,但编写 FSM 是一种很好的做法)。

module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);

    parameter A=0,B=1,C=2,D=3,E=4,F=5;
    reg [2:0] state,next_state;
    
    always@(*)
        begin
            case(state)
                A:next_state<=w?A:B;
                B:next_state<=w?D:C;
                C:next_state<=w?D:E;
                D:next_state<=w?A:F;
                E:next_state<=w?D:E;
                F:next_state<=w?D:C;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state<=A;
            else
                state<=next_state;
        end
    
    assign z=(state==E|state==F);
endmodule

5.30、Exams/2012 q2fsm

 考虑如下所示的状态图。

考试 2012q2.png

编写代表此 FSM 的完整 Verilog 代码。就像在讲座中所做的那样,对状态表和状态触发器使用单独的always块。使用连续赋值语句或always块(由您自行决定)描述 FSM 输出,称为z 。分配您希望使用的任何州代码。

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    input w,
    output z
);
    parameter A=0,B=1,C=2,D=3,E=4,F=5;
    reg [2:0] state,next_state;
    
    always@(*)
        begin
            case(state)
                A:next_state<=w?B:A;
                B:next_state<=w?C:D;
                C:next_state<=w?E:D;
                D:next_state<=w?F:A;
                E:next_state<=w?E:D;
                F:next_state<=w?C:D;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state<=A;
            else
                state<=next_state;
        end
    
    assign z=(state==E|state==F);

endmodule

5.31、Exams/2012 q2b

这个问题的状态图再次显示在下面。

考试 2012q2.png

假设在状态分配y[5:0] = 000001(A), 000010(B), 000100(C), 001000(D), 010000(E), 100000(F) 中使用 one-hot 代码

为信号Y1写一个逻辑表达式,它是状态触发器y[1]的输入。

为信号Y3写一个逻辑表达式,它是状态触发器y[3]的输入。

(通过假设 one-hot 编码的检查推导出逻辑方程。测试台将使用非 one hot 输入进行测试,以确保您不会尝试做更复杂的事情)。

module top_module (
    input [5:0] y,
    input w,
    output Y1,
    output Y3
);
    
    parameter A=6'b000_001,B=6'b000_010,C=6'b000_100,D=6'b001_000,E=6'b010_000,F=6'b100_000;
    reg [5:0] next_state;
    
    assign next_state[0] = (y[0]&~w)|(y[3]&~w); 
    assign next_state[1] = y[0]&w;
    assign next_state[2] = (y[1]&w)|(y[5]&w);
    assign next_state[3] = (y[1]&~w)|(y[2]&~w)|(y[4]&~w)|(y[5]&~w);
    assign next_state[4] = (y[2]&w)|(y[4]&w);
    assign next_state[5] = y[3]&w;
    
    assign Y1=next_state[1];
    assign Y3=next_state[3];

endmodule

5.32、Exams/2013 q2afsm

考虑下图所示状态图描述的 FSM:

考试 2013q2.png

该 FSM 充当仲裁电路,控制三个请求设备对某种类型资源的访问。每个设备通过设置信号r[i] = 1 来请求资源,其中r[i]r[1]r[2]r[3]。每个 r[i] 是 FSM 的输入信号,代表三个设备之一。只要没有请求,FSM 就会保持在状态A当一个或多个请求发生时,FSM 决定哪个设备接收到使用资源的授权,并更改为将该设备的g[i]信号设置为 1 的状态。每个g[i]是 FSM 的输出。有一个优先级系统,设备 1 的优先级高于设备 2,设备 3 的优先级最低。因此,例如,如果设备 3 是在 FSM 处于状态A时发出请求的唯一设备,则设备 3 将仅接收授权。一旦设备i被 FSM 授予授权,只要其请求r[i] = 1,该设备就会继续接收授权。

编写代表此 FSM 的完整 Verilog 代码。就像在讲座中所做的那样,对状态表和状态触发器使用单独的 always 块。使用连续赋值语句或 always 块(由您自行决定)描述 FSM 输出g[i] 。分配您希望使用的任何州代码。

module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input [3:1] r,   // request
    output [3:1] g   // grant
); 
    parameter A=0, B=1, C=2, D=3;
    reg [1:0] state, state_next;
    
    always @(*) begin
        case (state)
            A : begin
                if (r[1])   
                    state_next <= B;
                else if (~r[1] & r[2])
                    state_next <= C;
                else if (~r[1] & ~r[2] &r[3])
                    state_next <= D;
                    else 
                    state_next <= A;
            end
            B : begin
                if (r[1]) state_next <= B;
                else      state_next <= A;
            end
            C : begin
                if (r[2]) state_next <= C;
                else      state_next <= A;
            end
            D : begin
                if (r[3]) state_next <= D;
                else      state_next <= A;
            end
            default :     state_next <= A;
        endcase
    end
    
    always @(posedge clk)
        begin
            if (!resetn) state <= A;
            else         state <= state_next;
        end
   
    assign g = {state == D,state == C,state == B};
    
endmodule

5.33、Exams/2013 q2bfsm

考虑一个用于控制某种电机的有限状态机。FSM 具有 来自电机的输入x和y ,并产生控制电机的输出f和g。还有一个称为clk的时钟输入和一个称为resetn的复位输入。

FSM 必须按如下方式工作。只要复位输入被置位,FSM 就保持在开始状态,称为状态A。当复位信号无效时,在下一个时钟沿之后,FSM 必须将输出f设置为 1 一个时钟周期然后,FSM 必须监控 x输入。x在三个连续的时钟周期中产生值 1、0、1 时,应在下一个时钟周期将g设置为 1在保持g = 1 的同时,FSM 必须监控y 输入。如果y在最多两个时钟周期内为 1,则 FSM 应保持g= 1 永久(即,直到重置)。但如果y在两个时钟周期内未变为 1,则 FSM 应永久设置g = 0(直到复位)

 

module top_module (
    input clk,
    input resetn,    //低电平有效同步复位
    input x,
    input y,
    output f,
    output g
); 
    
    parameter A=0,B=1,START=2,X1=3,X2=4,X3=5,Y1=6,KEEP_G0=7,KEEP_G1=8;
    reg [3:0] state,next_state;
    
    always@(*)
        begin
            case(state)
                A:next_state<=resetn?B:A;
                B:next_state<=START;
                START:next_state<=x?X1:START;
                X1:next_state<=x?X1:X2;
                X2:next_state<=x?X3:START;
                X3:next_state<=y?KEEP_G1:Y1;
                Y1:next_state<=y?KEEP_G1:KEEP_G0;
                KEEP_G0:next_state<=KEEP_G0;
                KEEP_G1:next_state<=KEEP_G1;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(!resetn)
                state<=A;
            else
                state<=next_state;
        end
    
    assign f=(state==B);
    assign g=(state==KEEP_G1|state==X3|state==Y1);

endmodule

 

posted @ 2022-05-21 22:18  super_sweet  阅读(309)  评论(0编辑  收藏  举报