首页 > 其他分享 >【HDLBits刷题笔记】13 Finite State Machines

【HDLBits刷题笔记】13 Finite State Machines

时间:2022-11-06 23:00:47浏览次数:69  
标签:13 HDLBits State module next state output input parameter

Fsm1

 这里需要实现一个简单的摩尔状态机,即输出只与状态有关的状态机。

我这里代码看上去比长一点,答案用的case和三目运算符,结果是一样的。

module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output out);//  

    parameter A=0, B=1; 
    reg state, next_state;

    always @(*) begin    // This is a combinational always block
        if(state ==A)begin
            if(in==1)
                next_state=A;
            else
                next_state=B;
        end
        else if(state ==B)begin
            if(in==1)
                next_state=B;
            else
                next_state=A;
        end        
    end

    always @(posedge clk, posedge areset) begin    // This is a sequential always block
        if(areset)
            state <= B;
        else 
            state <= next_state;
    end

    // Output logic
    assign out = (state == B);

endmodule

Fsm1s

和上一题是一样的,只不过换成了同步复位。

// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);
    input clk;
    input reset;    // Synchronous reset to state B
    input in;
    output out;//  

    // Fill in state name declarations

    reg present_state, next_state;
    parameter A=0, B=1; 

    always @(posedge clk) begin
        if (reset) begin  
            present_state <= B;
        end else begin
            // State flip-flops
            present_state <= next_state;   
        end
    end
    
    always@(*)
    begin
        case (present_state)
            A:next_state=in?A:B;
            B:next_state=in?B:A;
        endcase 
    end
    
    assign out = (present_state == B);

endmodule

Fsm2

这里是一个JK触发器。

module top_module(
    input clk,
    input areset,    // Asynchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF=0, ON=1; 
    reg state, next_state;

    always @(*) begin
        case(state)
            OFF:next_state=j?ON:OFF;
            ON:next_state=k?OFF:ON;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset)
            state <= OFF;
        else
            state <= next_state;
    end

    // Output logic
    assign out = (state == ON);

endmodule

Fsm2s

同样是异步改成同步就可以了。

module top_module(
    input clk,
    input reset,    // Synchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF=0, ON=1; 
    reg state, next_state;

    always @(*) begin
        case(state)
            OFF:next_state=j?ON:OFF;
            ON:next_state=k?OFF:ON;
        endcase
    end

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

    // Output logic
    assign out = (state == ON);

endmodule

Fsm3comb

这道题只需要实现状态转换逻辑和输出逻辑,状态转换的时序逻辑不需要实现。

module top_module(
    input in,
    input [1:0] state,
    output [1:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    // State transition logic: next_state = f(state, in)
    always@(*)
    begin
        case(state)
            A:next_state=in?B:A;
            B:next_state=in?B:C;
            C:next_state=in?D:A;
            D:next_state=in?B:C;
        endcase
    end

    // Output logic:  out = f(state) for a Moore state machine
    assign out=(state==D);

endmodule

Fsm3onehot

这道题要求使用独热码,即只有一个1的编码。

这里提到了一个概念"derive equations by inspection",指通过某一个位就可以判断当前状态,例如可以用state[0]判断当前状态是否为A,这样可以简化状态转换逻辑。

module top_module(
    input in,
    input [3:0] state,
    output [3:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    // State transition logic: Derive an equation for each state flip-flop.
    assign next_state[A] = (state[A]&~in)|(state[C]&~in);
    assign next_state[B] = (state[A]&in)|(state[B]&in)|(state[D]&in);
    assign next_state[C] = (state[B]&~in)|(state[D]&~in);
    assign next_state[D] = (state[C]&in);

    // Output logic: 
    assign out = state[D];

endmodule

Fsm3

状态转换逻辑在前面已经实现了,这里只需要实现状态转换寄存器和输出寄存器。

module top_module(
    input clk,
    input in,
    input areset,
    output out); //
    reg [1:0]state,next_state;
    // State transition logic
    parameter A=0, B=1, C=2, D=3;
    always@(*)
    begin
        case(state)
            A:next_state=in?B:A;
            B:next_state=in?B:C;
            C:next_state=in?D:A;
            D:next_state=in?B:C;
        endcase
    end
    // State flip-flops with asynchronous reset
    always@(posedge clk or posedge areset)
    begin
        if(areset)
            state <= A;
        else 
            state <= next_state;
    end
    // Output logic
    assign out=(state==D);
endmodule

Fsm3s

把上一题的异步复位改成同步复位。

module top_module(
    input clk,
    input in,
    input reset,
    output out); //
    reg [1:0]state,next_state;
    // State transition logic
    parameter A=0, B=1, C=2, D=3;
    always@(*)
    begin
        case(state)
            A:next_state=in?B:A;
            B:next_state=in?B:C;
            C:next_state=in?D:A;
            D:next_state=in?B:C;
        endcase
    end
    // State flip-flops with asynchronous reset
    always@(posedge clk)
    begin
        if(reset)
            state <= A;
        else 
            state <= next_state;
    end
    // Output logic
    assign out=(state==D);
endmodule

Exams/ece241 2013 q4

又是一道正确率十几的题目。。

fr1、fr2、fr3结果输出可以直接根据题目给的表得出,dfr需要仔细考虑一下,题目的意思是如果之前的水位比现在的水位低,那么就打开dfr,这里的之前并不是指一个时钟的之前,所以当状态不变的时候不需要改变dfr。不过我这种写法就不是严格的摩尔状态机了,因为我在一个时序逻辑中同时使用了state和next_state做对比。

题目给的答案通过六个状态来给出输出,感觉还是有点复杂的。

module top_module (
    input clk,
    input reset,
    input [3:1] s,
    output fr3,
    output fr2,
    output fr1,
    output reg dfr
); 
    parameter A=0,B=1,C=2,D=3;
    reg[1:0]state,next_state;
    always@(posedge clk)
    begin
        if(reset)
            state <= A;
        else
            state <= next_state;
    end
    
    always@(*)
    begin
        next_state = A;
        case(s)
            3'b111:next_state = D;
            3'b011:next_state = C;
            3'b001:next_state = B;
            3'b000:next_state = A;
        endcase
    end
    
    always@(posedge clk)
    begin
        if(reset)
            dfr <= 1;
        else if(next_state<state)
            dfr <= 1;
        else if(next_state>state)
            dfr <= 0;
    end
    assign fr3=(state==A);
    assign fr2=(state==A)||(state==B);
    assign fr1=(state==A)||(state==B)||(state==C);
    
endmodule

Lemmings1

这道题要求用有限状态机描述游戏Lemmings中的角色,角色将在撞到障碍物时改变方向。

题目已经把状态机和代码框架都给出来了,只要补充关键部分即可。

 

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    output walk_left,
    output walk_right); //  

    parameter LEFT=0, RIGHT=1;
    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            LEFT:next_state=bump_left?RIGHT:LEFT;
            RIGHT:next_state=bump_right?LEFT:RIGHT;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset)
            state <= LEFT;
        else
            state <= next_state;
    end

    // Output logic
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);

endmodule

Lemmings2

相比上一题多了一个FALL的状态,要求FALL之后还要恢复之前的方向,所以这里增加一个状态是不够的,至少要增加两个状态之后才能使FALL之后恢复原来的状态。

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    output walk_left,
    output walk_right,
    output aaah ); 
    
    parameter LEFT=0, RIGHT=1,FALL_L=2,FALL_R=3;
    reg [1:0]state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            LEFT:next_state=ground?(bump_left?RIGHT:LEFT):FALL_L;
            RIGHT:next_state=ground?(bump_right?LEFT:RIGHT):FALL_R;
            FALL_L:next_state=ground?LEFT:FALL_L;
            FALL_R:next_state=ground?RIGHT:FALL_R;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset)
            state <= LEFT;
        else
            state <= next_state;
    end

    // Output logic
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);
    assign aaah = (state == FALL_L)||(state == FALL_R);

endmodule

Lemmings3

根据题目给的题目给的状态转换表,还是比较好写的。

直接在上一题代码基础上改的,越改越长。

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output walk_left,
    output walk_right,
    output aaah,
    output digging ); 

    parameter LEFT=0, RIGHT=1,FALL_L=2,FALL_R=3,DIG_L=4,DIG_R=5;
    reg [2:0]state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            LEFT:next_state=ground?(dig?DIG_L:(bump_left?RIGHT:LEFT)):FALL_L;
            RIGHT:next_state=ground?(dig?DIG_R:(bump_right?LEFT:RIGHT)):FALL_R;
            FALL_L:next_state=ground?LEFT:FALL_L;
            FALL_R:next_state=ground?RIGHT:FALL_R;
            DIG_L:next_state=ground?DIG_L:FALL_L;
            DIG_R:next_state=ground?DIG_R:FALL_R;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset)
            state <= LEFT;
        else
            state <= next_state;
    end

    // Output logic
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);
    assign aaah = (state == FALL_L)||(state == FALL_R);
    assign digging = (state == DIG_L)||(state == DIG_R);
endmodule

Lemmings4

当Lemmings 下落超过20个时钟周期会摔死,注意!Lemmings 不会在半空中摔死,不能以20个周期作为判别条件,而要以到ground时的时钟周期数来计算。

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output walk_left,
    output walk_right,
    output aaah,
    output digging ); 

    parameter LEFT=0, RIGHT=1,FALL_L=2,FALL_R=3,DIG_L=4,DIG_R=5,SPLAT=6;
    reg [2:0]state, next_state;
    reg [7:0]fall_cnt;
    always@(posedge clk , posedge areset)
    begin
        if(areset)
            fall_cnt <= 'd0;
        else if((state == FALL_L)||(state == FALL_R))
            fall_cnt <= (fall_cnt>=20)?fall_cnt:fall_cnt+1'b1;
        else
            fall_cnt <= 'd0;
    end

    always @(*) begin
        // State transition logic
        case(state)
            LEFT:next_state=ground?(dig?DIG_L:(bump_left?RIGHT:LEFT)):FALL_L;
            RIGHT:next_state=ground?(dig?DIG_R:(bump_right?LEFT:RIGHT)):FALL_R;
            FALL_L:next_state=ground?((fall_cnt==20)?SPLAT:LEFT):FALL_L;
            FALL_R:next_state=ground?((fall_cnt==20)?SPLAT:RIGHT):FALL_R;
            DIG_L:next_state=ground?DIG_L:FALL_L;
            DIG_R:next_state=ground?DIG_R:FALL_R;
            SPLAT:next_state=SPLAT;
            default:next_state='dx;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset)
            state <= LEFT;
        else
            state <= next_state;
    end

    // Output logic
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);
    assign aaah = (state == FALL_L)||(state == FALL_R);
    assign digging = (state == DIG_L)||(state == DIG_R);
endmodule

一次过,完美。今天就做到这里了,这一节题目有点多,有些题还有些复杂,估计还要再写两天了。

Fsm onehot

看着简单,但得找对思路,一开始我用的always@(*)并且标注出了S9~S0,但是由于该测试还会输入非独热码,会导致输出也并非全是独热码,所以要按照出题者的意图,直接将每一位作为一个状态直接进行判断。

module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);
    
    assign next_state[0]=~in&&(state[4:0]||state[9:7]);
    assign next_state[1]=in&&(state[0]||state[9:8]);
    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[7:6];
    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

Fsm ps2

ps/2是早期鼠标和键盘的接口,现在已经基本被USB取代。

这道题只需要通过in[3]来判断数据传输什么时候结束即可。

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

    parameter BYTE1=0,BYTE2=1,BYTE3=2,DONE=3;
    reg[1:0]state,next_state;
    
    // State transition logic (combinational)
    always@(*)
    begin
        case(state)
            BYTE1:next_state=in[3]?BYTE2:BYTE1;
            BYTE2:next_state=BYTE3;
            BYTE3:next_state=DONE;
            DONE:next_state=in[3]?BYTE2:BYTE1;
        endcase
    end
    // State flip-flops (sequential)
    always@(posedge clk)
    begin
        if(reset)
            state <= BYTE1;
        else 
            state <= next_state;
    end
    // Output logic
    assign done=(state==DONE);

endmodule

Fsm ps2data

在上一题的基础上增加一个存储数据的功能.

注意,由于这里状态DONE的时候下一个状态直接就是BYTE2了,所以在DONE的时候就可以存储BYTE1了。

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

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

Fsm serial

又是一道正确率很低的题目。

一开始写的count==8,一直出错,要注意count=0也有一个周期的长度。

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    parameter IDLE=0,START=1,DATA=2,STOP=3;
    reg[1:0]state,next_state;
    reg[3:0]count;
    
    always@(posedge clk)
    begin
        if(reset)
            state <= IDLE;
        else
            state <= next_state;
    end
    
    always@(posedge clk)
    begin
        if(reset)
            count <= 'd0;
        else if(state == DATA)
            count <= (count>7)?count:count+1'b1;
        else
            count <= 'd0;
    end
    
    always@(*)
    begin
        case(state)
            IDLE:next_state=in?IDLE:START;
            START:next_state=DATA;
            DATA:begin
                if(count==7&&in)
                    next_state=STOP;
                else if(count>7&&in)
                    next_state=IDLE;
                else
                    next_state=DATA;
            end
            STOP:next_state=in?IDLE:START;
        endcase
    end
    assign done=(state==STOP);

endmodule

Fsm serialdata

 使用state计数的话整体的数据采集会落后一个周期,所以这题的计数使用next_state来进行判断,所以上一题的7要改成8。

原理参考三段式状态机使用case(next_state)用作输出,否则使用case(state)输出会落后两个周期。

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

    // Use FSM from Fsm_serial
    parameter IDLE=0,START=1,DATA=2,STOP=3;
    reg[1:0]state,next_state;
    reg[3:0]count;
    
    always@(posedge clk)
    begin
        if(reset)
            state <= IDLE;
        else
            state <= next_state;
    end
    
    always@(posedge clk)
    begin
        if(reset)
            count <= 'd0;
        else if(next_state == DATA)begin
            out_byte <= {in,out_byte[7:1]};
            count <= (count>8)?count:count+1'b1;
        end
        else
            count <= 'd0;
    end
    
    always@(*)
    begin
        case(state)
            IDLE:next_state=in?IDLE:START;
            START:next_state=DATA;
            DATA:begin
                if(count==8&&in)
                    next_state=STOP;
                else if(count>8&&in)
                    next_state=IDLE;
                else
                    next_state=DATA;
            end
            STOP:next_state=in?IDLE:START;
        endcase
    end
    assign done=(state==STOP);
    // New: Datapath to latch input bits.

endmodule

Fsm serialdp

在上一题的基础上实现一个奇校验:通过加入一个冗余位,使得9位数据中的1的个数始终为奇数。

题目给了一个T触发器,即输入为1时,输出翻转的触发器,T触发一般使用一个JK触发器构成。

debug不能看全部信号的波形也太折磨了,最好还是用vivado仿真调一下。

在经过六次失败之后,终于成功了,错误的原因是T触发器的in信号经过了选通,导致可能少计了一个周期,其实reset位置合适,in可以直接连接到T触发器上。

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=0,START=1,DATA=2,STOP=3;
    reg[1:0]state,next_state;
    reg[3:0]count;
    wire odd;
    reg[8:0]data;
    wire parity_reset;

    always@(posedge clk)
    begin
        if(reset)
            state <= IDLE;
        else
            state <= next_state;
    end
    
    always@(posedge clk)
    begin
        if(reset)
            count <= 'd0;
        else if(next_state == DATA)begin
            data <= {in,data[8:1]};
            count <= (count>9)?count:count+1'b1;
        end
        else if(next_state == START)
            count <= 'd0;
    end
    
    always@(*)
    begin
        case(state)
            IDLE:next_state=in?IDLE:START;
            START:next_state=DATA;
            DATA:begin
                if(count==9&&in&&odd)
                    next_state=STOP;
                else if(count>=9&&in)
                    next_state=IDLE;
                else
                    next_state=DATA;
            end
            STOP:next_state=in?IDLE:START;
        endcase
    end
    assign done=(state==STOP);
    // New: Datapath to latch input bits.
    // New: Add parity checking.
    parity u0(clk,parity_reset,in,odd);
    assign out_byte=data[7:0];
    assign parity_reset = reset||next_state ==IDLE||next_state == START;
endmodule

Fsm hdlc

序列检测器,这里有三个序列需要检测

  • 0111110: Signal a bit needs to be discarded (disc).
  • 01111110: Flag the beginning/end of a frame (flag).
  • 01111111...: Error (7 or more 1s) (err).

根据题目意思可以构建一个Moore状态机,结果发现和前面Fsm onehot中的状态机是一样的,这不是巧了吗。前面用的是独热码并且已经写出了状态转移方程,这里直接用就好了。

module top_module(
    input clk,
    input reset,    // Synchronous reset
    input in,
    output disc,
    output flag,
    output err);
    reg[9:0]state;
    wire[9:0]next_state;
    parameter NONE=10'd0000_0000_01;
    parameter ONE=10'd0000_0000_10;
    parameter TWO=10'd0000_0001_00;
    parameter THREE=10'd0000_0010_00;
    parameter FOUR=10'd0000_0100_00;
    parameter FIVE=10'd0000_1000_00;
    parameter SIX=10'd0001_0000_00;
    parameter ERROR=10'd0010_0000_00;
    parameter DISCARD=10'd0100_0000_00;
    parameter FLAG=10'd1000_0000_00;
    
    always@(posedge clk)
    begin
        if(reset)
            state <= NONE;
        else
            state <= next_state;
    end
    
    assign next_state[0]=~in&&(state[4:0]||state[9:7]);
    assign next_state[1]=in&&(state[0]||state[9:8]);
    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[7:6];
    assign next_state[8]=~in&&state[5];
    assign next_state[9]=~in&&state[6];
    
    assign err=state[7];
    assign disc=state[8];    
    assign flag=state[9]; 

endmodule

有状态转换逻辑就是好写。

Exams/ece241 2013 q8

使用Mealy状态机,也就是输出和状态和输入都有关,这里使用Moore状态机会多一个状态.,而题目要求使用三个状态,所以最好使用Mealy状态机。

module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z ); 
    
    reg[1:0]state,next_state;
    parameter S0=0,S1=1,S2=2;
    
    always@(posedge clk or negedge aresetn)
    begin
        if(~aresetn)
            state <= S0;
        else
            state <= next_state;
    end

    always@(*)
    begin
        case(state)
            S0:next_state=x?S1:S0;
            S1:next_state=x?S1:S2;
            S2:next_state=x?S1:S0;
            default:next_state=S0;
        endcase
    end
    
    assign z=(state==S2)&&x;
        
endmodule

这里使用的是两段式,输出直接使用组合逻辑。我一开始写的三段式,输出用的时序逻辑,输入会同时改变次态和输出,所以电路综合出来显示一直是0,晕。

下面是代码,用来当反面教材。

module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output reg z ); 
    
    reg[1:0]state,next_state;
    parameter S0=0,S1=1,S2=2;
    
    always@(posedge clk or negedge aresetn)
    begin
        if(~aresetn)
            state <= S0;
        else
            state <= next_state;
    end

    always@(*)
    begin
        case(state)
            S0:next_state=x?S1:S0;
            S1:next_state=x?S1:S2;
            S2:next_state=x?S1:S0;
            default:next_state=S0;
        endcase
    end
    
    always@(posedge clk or negedge aresetn)
    begin
        if(~aresetn)
            z <= 1'b0;
        else begin
            case(next_state)
                S0:z <= 1'b0;
                S1:z <= 1'b0;
                S2:z <= x;
                default:z <= 1'b0;
            endcase
        end
    end
        
endmodule

Exams/ece241 2014 q5a

这道题一开始没看懂啥意思,看了一下Rong晔大佬的视频才懂。

大概意思就是遇到第一个1时开始进行取反运算,由于1000的补码仍然是1000,所以第一个1保持不变,后面出现的高位全部取反。

注意这里只需要对输入进行补码运算,不需要也没有办法判断输入的数到底是正数还是负数(一开始就是没想清楚这一点),所以无脑对输入进行计算就可以了。

这里用S1代表需要输出1,S2代表需要输出0。

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

Exams/ece241 2014 q5b

和上一题是一样的,注意Moore状态机比Mealy状态机多一个状态,并且Mealy状态机直接使用组合逻辑输出会相比Moore状态机提前一个周期。

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

Exams/2014 q3fsm

这道题正确率只有13%

主要困难的地方在于计数每三个周期里w有多少个1,由于这里计数是连续的,所以w的计数不能简单的清零,在第一个周期时便可以开始判断w的值,并决定初始化为0还是1。

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
    parameter A=0,B=1;
    reg state,next_state;
    reg [1:0]w_count,count;
    
    always@(posedge clk)
    begin
        if(reset)
            state <= A;
        else
            state <= next_state;
    end
    
    always@(*)
    begin
        case(state)
            A:next_state=s?B:A;
            B:next_state=B;
        endcase
    end
    
    always@(posedge clk)
    begin
        if(reset)
            count <= 'd0;
        else begin
            if((state==B)&&count <2)
            begin
                count <= count + 1'b1;
            end
            else begin
                count <= 'd0;
            end
        end
    end
    
    always@(posedge clk)
    begin
        if(reset)
            w_count <= 'd0;
        else if(state ==B) begin
            if(count ==0)
            begin
                if(w)
                    w_count <= 'd1;  
                else 
                    w_count <= 'd0; 
            end
            else if(w)
                w_count <=  w_count +1'b1;
        end
    end    
    
    assign z=(count == 'd0)&&(w_count ==2);

endmodule

Exams/2014 q3bfsm

终于来了一道简单题。

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

endmodule

Exams/2014 q3c

这道题给的clk没啥用。

module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    parameter S0=3'b000;
    parameter S1=3'b001;
    parameter S2=3'b010;
    parameter S3=3'b011;
    parameter S4=3'b100;
    
    reg[2:0]next_state;
    
    always@(*)
    begin
        case(y)
            S0:next_state=x?S1:S0;
            S1:next_state=x?S4:S1;
            S2:next_state=x?S1:S2;
            S3:next_state=x?S2:S1;
            S4:next_state=x?S4:S3;
            default:next_state=S0;
        endcase
    end
    
    assign z=(y==S3)||(y==S4);    
    assign Y0=next_state[0];

endmodule

Exams/m2014 q6b

这题只要求把Y2逻辑写出来,Y2只在两种情况为1,即状态C和状态D,把所有会跳转到这两种状态的情况列举出来即可。

module top_module (
    input [3:1] y,
    input w,
    output Y2);
    parameter A=3'b000;
    parameter B=3'b001;
    parameter C=3'b010;
    parameter D=3'b011;
    parameter E=3'b100; 
    parameter F=3'b101; 
    
    assign Y2=(y==B&&~w)||(y==F&&~w)||
        (y==B&&w)||(y==C&&w)||(y==E&&w)||(y==F&&w);

endmodule

Exams/m2014 q6c

做过的题型,要求使用独热码编码。

module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);

    parameter A=6'b000_001;
    parameter B=6'b000_010;
    parameter C=6'b000_100;
    parameter D=6'b001_000;
    parameter E=6'b010_000; 
    parameter F=6'b100_000;
    
    assign Y2=y[1]&&~w;
    assign Y4=(y[2]&&w)||(y[3]&&w)||(y[5]&&w)||(y[6]&&w);
    
endmodule

Exams/m2014 q6

直接接着上一题写。

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

    parameter A=6'b000_001;
    parameter B=6'b000_010;
    parameter C=6'b000_100;
    parameter D=6'b001_000;
    parameter E=6'b010_000; 
    parameter F=6'b100_000;
    
    reg [6:1]state,next_state;
    always@(posedge clk)
    begin
        if(reset)
            state <= A;
        else 
            state <= next_state;
    end
    
    assign next_state[1]=(state[1]&&w)||(state[4]&&w);
    assign next_state[2]=state[1]&&~w;
    assign next_state[3]=(state[2]&&~w)||(state[6]&&~w);
    assign next_state[4]=(state[2]&&w)||(state[3]&&w)||(state[5]&&w)||(state[6]&&w); 
    assign next_state[5]=(state[3]&&~w)||(state[5]&&~w);
    assign next_state[6]=state[4]&&~w;
    
    assign z=state[5]||state[6];
    
endmodule

Exams/2012 q2fsm

和上一题是一样的,只不过按题目要求用了两个always。

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    input w,
    output z
);

    parameter A=3'b000;
    parameter B=3'b001;
    parameter C=3'b010;
    parameter D=3'b011;
    parameter E=3'b100; 
    parameter F=3'b101; 
    
    reg [6:1]state,next_state;
    always@(posedge clk)
    begin
        if(reset)
            state <= A;
        else 
            state <= next_state;
    end
    
    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;
            default:next_state=A;
        endcase
    end
    
    assign z=(state==E)||(state==F);
    
endmodule

Exams/2012 q2b

为啥还是这道题,稍微变了一点逻辑。

module top_module (
    input [5:0] y,
    input w,
    output Y1,
    output Y3
);
    
    assign Y1=y[0]&&w;
    assign Y3=(y[1]&&~w)||(y[2]&&~w)||(y[4]&&~w)||(y[5]&&~w); 

endmodule

Exams/2013 q2afsm

这个状态机是一个仲裁器,不难看出,三个设备具有不同的优先级,B>C>D,根据状态转移图不难得出方程。

一开始写错了,因为r1、r2、r3顺序搞错了,晕。

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,next_state;
    
    always@(posedge clk)
    begin
        if(~resetn)
            state <= A;
        else
            state <= next_state;
    end
    
    always@(*)
    begin
        case(state)
            A:begin
                casex(r)
                    3'b000:next_state=A;
                    3'bxx1:next_state=B;
                    3'bx10:next_state=C;
                    3'b100:next_state=D;
                endcase
            end
            B:next_state=r[1]?B:A;
            C:next_state=r[2]?C:A;
            D:next_state=r[3]?D:A;
        endcase
    end
    
    assign g[1]=state==B;
    assign g[2]=state==C;
    assign g[3]=state==D;

endmodule

Exams/2013 q2bfsm

疯狂加状态就完事了,主要是要理解题目意思,一步一步写就行了。

module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input x,
    input y,
    output f,
    output g
); 
    parameter A=0,B=1,C=2,D=3,E=4,F=5,G=6,H=7,I=8;
    reg [3:0]state,next_state;
    
    always@(posedge clk)
    begin
        if(~resetn)
            state <= A;
        else
            state <= next_state;
    end
    
    always@(*)
    begin
        case(state)
            A:next_state=B;
            B:next_state=C;
            C:next_state=x?D:C;
            D:next_state=x?D:E;
            E:next_state=x?F:C;
            
            F:next_state=y?H:G;
            G:next_state=y?H:I;
            H:next_state=H;//g=1
            I:next_state=I;//g=0;
        endcase
    end
    
    assign f=(state==B);
    assign g=(state==F)||(state==G)||(state==H);

endmodule

写了一个星期终于写完这一节了,泪目。

标签:13,HDLBits,State,module,next,state,output,input,parameter
From: https://www.cnblogs.com/magnolia666/p/16850152.html

相关文章