2021年7月19日 星期一

HDLBits/Sequential Logic/Finite State Machines/Fsm serialdp

HDLBits/Sequential Logic/Finite State Machines/Fsm serialdp

Serial Receiver with Parity Checking

See also: Serial receiver and datapath

We want to add parity checking to the serial receiver. Parity checking adds one extra bit after each data byte. We will use odd parity, where the number of 1s in the 9 bits received must be odd. For example, 101001011 satisfies odd parity (there are 5 1s), but 001001011 does not.

Change your FSM and datapath to perform odd parity checking. Assert the done signal only if a byte is correctly received and its parity check passes. Like the serial receiver FSM, this FSM needs to identify the start bit, wait for all 9 (data and parity) bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.

You are provided with the following module that can be used to calculate the parity of the input stream (It's a TFF with reset). The intended use is that it should be given the input bit stream, and reset at appropriate times so it counts the number of 1 bits in each byte.

module parity (
    input clk,
    input reset,
    input in,
    output reg odd);

    always @(posedge clk)
        if (reset) odd <= 0;
        else if (in) odd <= ~odd;

endmodule

Note that the serial protocol sends the least significant bit first, and the parity bit after the 8 data bits.

上題的基礎上多了一個輸出,要求是當正確接收數據時做出輸出,即在 done 信號為高電平時做出輸出。所以該題代碼與上題基本一致,只需要多一個8 bit 寄存器來寄存得到的數據並在 done 信號為高電平時候輸出即可。

這需要使用移位寄存器來實現移位寄存,可以從波形圖看出這是右移寄存器,因為不確定接收到的數據是否正確,所以只需不斷移位寄存即可,當 done 信號為正時進行輸出即為正確接收到的數據。狀態機與上題一致,波形圖如下。

基礎上進行進化,增添了奇偶校驗位。奇偶校驗(Parity Check)是一種校驗代碼傳輸正確性的方法。根據被傳輸的一組二進制代碼的數位中“1”的個數是奇數或偶數來進行校驗。采用奇數的稱為奇校驗,反之,稱為偶校驗。奇偶校驗是在傳輸中保障數據接收正確的常用方法,也是最初級的校驗方式。

采用的是奇校驗(odd parity)的方式,並且提供了奇偶校驗模塊。原本 start 和 stop 位之間的8 bit 變為了9 bit,新增的1 bit 為奇校驗位,從而使得這9 bit 中“1”的數量為奇數個,即題目中提供的奇偶校驗模塊輸出為1時表面數據正確,否則數據錯誤不予接收。波形圖如下所示。



碼中多了 odd 和 start 變量,odd 是出題人提供的奇偶校驗模塊的輸出,由 odd 是否為1判斷校驗是否正確。這里需要注意的是 start,該變量用於控制奇偶校驗模塊的開啟。需要注意,奇偶校驗模塊不能一直開啟,只有當開始接收數據,即出現起始標記後才開啟,並且每次開啟時需要覆位從頭進行,否則前面計算得到的 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;
    reg[3:0] 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

HDLBits/Sequential Logic/Finite State Machines/Fsm serialdata

HDLBits/Sequential Logic/Finite State Machines/Fsm serialdata

 See also: Serial receiver

Now that you have a finite state machine that can identify when bytes are correctly received in a serial bitstream, add a datapath that will output the correctly-received data byte. out_byte needs to be valid when done is 1, and is don't-care otherwise.

Note that the serial protocol sends the least significant bit first.

本題與上題基本一致,只需要多一個8 bit 寄存器來寄存得到的數據並在 done 信號為高電平時候輸出即可。這里需要使用移位寄存器來實現移位寄存,可以從波形圖看出這是右移寄存器,因為不確定接收到的數據是否正確,所以只需不斷移位寄存即可,當 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;
    reg[3:0] cnt;
    reg done_r;
    reg[7:0] out;
    
  //state
    always@(posedge clk)begin
        if(reset)
            state <= idle;
        else
            state <= next_state;
    end   
//transition
    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
 
//out
    always@(posedge clk)begin
        if(reset)
            out<=0;
        else
            case(next_state)
                start:    out<=0;
                data:    out<={in,out[7:1]}; //移位寄存器
            endcase
    end
    
//cnt
    always@(posedge clk)begin
        if(reset)
            cnt<=0;
        else
            case(next_state)
                start:    cnt<=0;
                data:    cnt<=cnt+1;
                default:    cnt<=cnt;
            endcase
    end
    
//done_r
    always@(posedge clk)
        case(next_state)
            stop:    done_r <= 1;
            default:    done_r <= 0;
        endcase
    
    assign done = done_r;
    assign out_byte = out;
endmodule


HDLBits/Sequential Logic/Finite State Machines/Fsm serial

 HDLBits/Sequential Logic/Finite State Machines/Fsm serial

n many (older) serial communications protocols, each data byte is sent along with a start bit and a stop bit, to help the receiver delimit bytes from the stream of bits. One common scheme is to use one start bit (0), 8 data bits, and 1 stop bit (1). The line is also at logic 1 when nothing is being transmitted (idle).

Design a finite state machine that will identify when bytes have been correctly received when given a stream of bits. It needs to identify the start bit, wait for all 8 data bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.


串列通信協議发送過程中會在Data前後增加Mark來標識字節首尾(Start , Stop ),即包含 start 位和 stop 位,比如 UART 協議就是這樣。

本題的Start 標記Mark 是低電平(Low),結束(Stop )的標記是高電平(High),在開始和結束之間傳輸的 bit 位為8即一個Byte,這是正確接收的條件,

當滿足該條件後會在 stop 位後面的時鐘沿給出 done 的輸出標記(Mark)。

如果不滿足該條件,比如起始 start 條件不滿足,則會一直等待知道接收到低電平信號才開始;又如 start 開始後,中間的位數超過了8 bit,即8 bit 後一直是低電平信號,不出現高電平的 stop 信號,則 receiver 繼續等待知道出現高電平位才結束,但這是一個錯誤接收,不會給出 done 的輸出標記。波形圖如下所示。


狀態機,本題設計了五個狀態,分別是 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;

    reg[3:0] cnt;

    reg done_r;

//state

    always@(posedge clk)begin

        if(reset)

            state <= idle;

        else

            state <= next_state;

    end

     

    //transition

    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

    

    //cnt

    always@(posedge clk)begin

        if(reset)

            cnt<=0;

        else

            case(next_state)

                start:    cnt<=0;

                data:      cnt<=cnt+1;

                default:    cnt<=cnt;

            endcase

    end

    

//done_r

    always@(posedge clk)

        case(next_state)

            stop:done_r <= 1;

            default:done_r <= 0;

        endcase

    assign done = done_r;

endmodule

2021年7月6日 星期二

HDLBits/Sequential Logic/Finite State Machines/Fsm ps2data

 HDLBits/Sequential Logic/Finite State Machines/Fsm ps2data

See also: PS/2 packet parser.

Now that you have a state machine that will identify three-byte messages in a PS/2 byte stream, add a datapath that will also output the 24-bit (3 byte) message whenever a packet is received (out_bytes[23:16] is the first byte, out_bytes[15:8] is the second byte, etc.).

out_bytes needs to be valid whenever the done signal is asserted. You may output anything at other times (i.e., don't-care).

For example:


在接收完後完整的輸出後將接收的3個BYTE DATA。

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output [23:0] out_bytes,
    output done); //
 
    parameter BYTE1 = 4'b0001;
    parameter BYTE2 = 4'b0010;
    parameter BYTE3 = 4'b0100;
    parameter DONE  = 4'b1000;
    reg [3:0] state, next_state;
    
    always @(posedge clk)begin
        if(reset)begin
            state <= BYTE1;
        end
        else begin
            state <= next_state;
        end
    end
    
    always @(*)begin
        next_state = 4'd0;
        case(state)
            BYTE1:next_state=in[3]?BYTE2:BYTE1;
            BYTE2:next_state=BYTE3;
            BYTE3:next_state=DONE;
            DONE:next_state=in[3]?BYTE2:BYTE1;
            default:next_state=BYTE1;
        endcase
    end

    // Output logic
    reg [7:0] db1,db2,db3;       //db=>data_byte
    assign done = (state == DONE);
    always @(posedge clk)begin
        if(reset)begin
            db1 <= 8'd0;
            db2 <= 8'd0;
            db3 <= 8'd0;
        end
        else begin
            case(next_state)
                BYTE2:db1 <= in;
                BYTE3:db2 <= in;
                DONE:db3 <= in;
            endcase
        end
    end
    assign out_bytes = {db1,db2,db3};
endmodule


HDLBits/Sequential Logic/Finite State Machines/Fsm ps2

HDLBits/Sequential Logic/Finite State Machines/Fsm ps2

 The PS/2 mouse protocol sends messages that are three bytes long. However, within a continuous byte stream, it's not obvious where messages start and end. The only indication is that the first byte of each three byte message always has bit[3]=1 (but bit[3] of the other two bytes may be 1 or 0 depending on data).

We want a finite state machine that will search for message boundaries when given an input byte stream. The algorithm we'll use is to discard bytes until we see one with bit[3]=1. We then assume that this is byte 1 of a message, and signal the receipt of a message once all 3 bytes have been received (done).

The FSM should signal done in the cycle immediately after the third byte of each message was successfully received.

Some timing diagrams to explain the desired behaviour


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 [2:0] state,next_state;
   
        // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset)
           state <= BYTE1;
        else
           state <= next_state;
    end
    
    // 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;
            default:next_state=BYTE1;
        endcase
    end
    // Output logic
    assign done = state == DONE;
endmodule


HDLBits/Sequential Logic/Finite State Machines/Fsm onehot

HDLBits/Sequential Logic/Finite State Machines/Fsm onehot 

Given the following state machine with 1 input and 2 outputs:


Suppose this state machine uses one-hot encoding, where state[0] through state[9] correspond to the states S0 though S9, respectively. The outputs are zero unless otherwise specified.

Implement the state transition logic and output logic portions of the state machine (but not the state flip-flops). You are given the current state in state[9:0] and must produce next_state[9:0] and the two outputs. Derive the logic equations by inspection assuming a one-hot encoding. (The testbench will test with non-one hot inputs to make sure you're not trying to do something more complicated).

Suppose this state machine uses one-hot encoding, where state[0] through state[9] correspond to the states S0 though S9, respectively. The outputs are zero unless otherwise specified.



module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);

    parameter s0=10'b00_0000_0001;
    parameter s1=10'b00_0000_0010;
    parameter s2=10'b00_0000_0100;
    parameter s3=10'b00_0000_1000;
    parameter s4=10'b00_0001_0000;
    parameter s5=10'b00_0010_0000;
    parameter s6=10'b00_0100_0000;
    parameter s7=10'b00_1000_0000;
    parameter s8=10'b01_0000_0000;
    parameter s9=10'b10_0000_0000;


    always@(*)begin
        case(state)
            s0:next_state = in ? s1:s0;
            s1:next_state = in ? s2:s0;
            s2:next_state = in ? s3:s0;
            s3:next_state = in ? s4:s0;
            s4:next_state = in ? s5:s0;
            s5:next_state = in ? s6:s8;
            s6:next_state = in ? s7:s9;
            s7:next_state = in ? s7:s0;
            s8:next_state = in ? s1:s0;
            s9:next_state = in ? s1:s0;
            default:
                next_state = s0;
        endcase 
    end

    //输出
    assign out1 = state==s8||state==s9;
    assign out2 = state==s7||state==s9;

endmodule


官方解答?????

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


2021年7月4日 星期日

HDLBits/Sequential Logic/Finite State Machines/Lemmings4

HDLBits/Sequential Logic/Finite State Machines/Lemmings4 

Although Lemmings can walk, fall, and dig, Lemmings aren't invulnerable. If a Lemming falls for too long then hits the ground, it can splatter. In particular, if a Lemming falls for more than 20 clock cycles then hits the ground, it will splatter and cease walking, falling, or digging (all 4 outputs become 0), forever (Or until the FSM gets reset). There is no upper limit on how far a Lemming can fall before hitting the ground. Lemmings only splatter when hitting the ground; they do not splatter in mid-air.

Extend your finite state machine to model this behaviour.

Falling for 20 cycles is survivable:



Game Lemmings4:小人行動規則與上述規則相同,添加小人會die的規則:

如果小人fall超過20cycles,則當其接觸地面時直接die(未接觸地面時不會die) dig,fall,left和right輸出全部置零,直到reset信號來臨。

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 = 3'b0;
    parameter RIGHT = 3'b1;
    parameter DIG_LEFT = 3'b10;
    parameter DIG_RIGHT = 3'b11;
    parameter FALL_LEFT = 3'b100;
    parameter FALL_RIGHT = 3'b101;
    parameter DEAD = 3'b110;
    parameter SPLATTER = 3'b111;
    
    reg [2:0] state,next_state;
    reg [4:0] Cycle_Count;
    
    wire [1:0] bump;
    assign bump = {bump_left,bump_right};
    
    always @(*)begin
        case(state)
            LEFT:begin
                if(ground == 1'b0)begin
                    next_state <= FALL_LEFT;
                end
                else if(dig == 1'b1)begin
                    next_state <= DIG_LEFT;
                end
                else if((bump == 2'b10) || (bump == 2'b11))begin
                    next_state <= RIGHT;
                end
                else begin
                    next_state <= LEFT;
                end
            end
            
            RIGHT:begin
                if(ground == 1'b0)begin
                    next_state <= FALL_RIGHT;
                end
                else if(dig == 1'b1)begin
                    next_state <= DIG_RIGHT;
                end
                else if((bump == 2'b01) || (bump == 2'b11))begin
                    next_state <= LEFT;
                end
                else begin
                    next_state <= RIGHT;
                end
            end
            
            DIG_LEFT:begin
                if(ground == 1'b0)begin
                    next_state <= FALL_LEFT;
                end
                else begin
                    next_state <= DIG_LEFT;
                end
            end
            
            DIG_RIGHT:begin
                if(ground == 1'b0)begin
                    next_state <= FALL_RIGHT;
                end
                else begin
                    next_state <= DIG_RIGHT;
                end
            end
            
            FALL_LEFT:begin
                if((ground == 1'b0) && (Cycle_Count < 5'd20))begin
                    next_state <= FALL_LEFT;
                end
                else if((ground == 1'b0) && (Cycle_Count >= 5'd20))begin
                    next_state <= SPLATTER;
                end
                else begin
                    next_state <= LEFT;
                end
            end
            
            FALL_RIGHT:begin
                if((ground == 1'b0) && (Cycle_Count < 5'd20))begin
                    next_state <= FALL_RIGHT;
                end
                else if((ground == 1'b0) && (Cycle_Count >= 5'd20))begin
                    next_state <= SPLATTER;
                end
                else begin
                    next_state <= RIGHT;
                end
            end
            
            SPLATTER:begin
                if(ground == 1'b1)begin
                    next_state <= DEAD;
                end
                else begin
                    next_state <= SPLATTER;
                end
            end
            
            DEAD:begin
                next_state <= DEAD;
            end
            
        endcase
    end
    
    always @(posedge clk,posedge areset)begin
        if(areset)begin
            state <= LEFT;
        end
        else begin
            state <= next_state;
        end
    end
    
    always @(posedge clk,posedge areset)begin
        if(areset)begin
            Cycle_Count <= 5'd0;
        end
        else if((next_state == FALL_LEFT) || (next_state == FALL_RIGHT)) begin
            Cycle_Count <= Cycle_Count + 1'b1;
        end
        else begin
            Cycle_Count <= 5'd0;
        end
    end
    
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);
    assign aaah = ((state == FALL_LEFT) || (state == FALL_RIGHT) || (state == SPLATTER));
    assign digging = ((state == DIG_LEFT) || (state == DIG_RIGHT));
endmodule


2021年7月3日 星期六

HDLBits/Sequential Logic/Finite State Machines/Lemmings3

HDLBits/Sequential Logic/Finite State Machines/Lemmings3

 In addition to walking and falling, Lemmings can sometimes be told to do useful things, like dig (it starts digging when dig=1). A Lemming can dig if it is currently walking on ground (ground=1 and not falling), and will continue digging until it reaches the other side (ground=0). At that point, since there is no ground, it will fall (aaah!), then continue walking in its original direction once it hits ground again. As with falling, being bumped while digging has no effect, and being told to dig when falling or when there is no ground is ignored.

(In other words, a walking Lemming can fall, dig, or switch directions. If more than one of these conditions are satisfied, fall has higher precedence than dig, which has higher precedence than switching directions.)

Extend your finite state machine to model this behaviour.




主要在於狀態的增加我沒有理清楚。題目中作者說如果旅鼠在地面上(ground = 1)並且挖掘信號為1,則它可以開始挖洞,一直挖,直到把地都挖穿了(ground = 0),此時,旅鼠就掉下去了,並且发出大叫。

增加了挖寶功能,當地面是平整時,可以進行挖寶,直到將地面挖空。

Game Lemmings3:有個小人左右走,它只有兩種狀態:向左走和向右走;左邊碰到東西之後它就向右走,右邊碰到東西之後它就向左走,兩邊都碰到東西就跟當前方向的反方向走;覆位時小人向左走;

添加ground信號,ground=1時規則與上述規則相同;ground=0時,記錄當前走的方向,並將aaah信號置1,直到ground=1時,走與掉落之前相同的方向。

添加dig信號,ground=1時一直挖,ground=0時,進入aaah狀態,直到ground再次為1,方向與dig開始的方向相同。

優先級:fall>dig>switch direction

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 = 4'd0, RIGHT = 4'd1, GROUND_LEFT = 4'd2, GROUND_RIGHT = 4'd3;
    parameter DIGGING_LEFT = 4'd4, DIGGING_RIGHT = 4'd5;
    reg [3:0] current_state;
    reg [3:0] next_state;
    
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            current_state <= LEFT;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            LEFT:begin
                next_state = ground ? (dig ? DIGGING_LEFT : (bump_left ? RIGHT : LEFT)) : GROUND_LEFT;
            end
            RIGHT:begin
                next_state = ground ? (dig ? DIGGING_RIGHT : (bump_right ? LEFT : RIGHT)) : GROUND_RIGHT;
            end
            GROUND_LEFT:begin
                next_state = ground ? LEFT : GROUND_LEFT;
            end
            GROUND_RIGHT:begin
                next_state = ground ? RIGHT : GROUND_RIGHT;
            end
            DIGGING_LEFT:begin
                next_state = ground ? DIGGING_LEFT : GROUND_LEFT;
            end
            DIGGING_RIGHT:begin
                next_state = ground ? DIGGING_RIGHT : GROUND_RIGHT;
            end
            default:begin
                next_state = LEFT;
            end
        endcase
    end    
    
    assign walk_left = (current_state == LEFT);
    assign walk_right = (current_state == RIGHT);
    assign digging = (current_state == DIGGING_LEFT || current_state == DIGGING_RIGHT);
    assign aaah = (current_state == GROUND_LEFT || current_state == GROUND_RIGHT);
endmodule

//-------------------------------------------------

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 = 4'd0, RIGHT = 4'd1, GROUND_LEFT = 4'd2, GROUND_RIGHT = 4'd3;
    parameter DIGGING_LEFT = 4'd4, DIGGING_RIGHT = 4'd5;
    wire [1:0] bump;
    assign bump = {bump_left,bump_right};
    reg [3:0] current_state;
    reg [3:0] next_state;
     
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            current_state <= LEFT;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            LEFT:begin
               if(ground == 1'b0)begin
                    next_state <= GROUND_LEFT;
                end
                else if(dig == 1'b1)begin
                    next_state <= DIGGING_LEFT;
                end
                else if((bump == 2'b10) || (bump == 2'b11))begin
                    next_state <= RIGHT;
                end
                else begin
                next_state <= LEFT;
                end
                //next_state = ground ? (dig ? DIGGING_LEFT : (bump_left ? RIGHT : LEFT)) : GROUND_LEFT;
            end
            RIGHT:begin
              if(ground == 1'b0)begin
                    next_state <= GROUND_RIGHT;
                end
                else if(dig == 1'b1)begin
                    next_state <= DIGGING_RIGHT;
                end
                else if((bump == 2'b01) || (bump == 2'b11))begin
                    next_state <= LEFT;
                end
                else begin
                next_state <= RIGHT;
                end
                //next_state = ground ? (dig ? DIGGING_RIGHT : (bump_right ? LEFT : RIGHT)) : GROUND_RIGHT;
            end
            GROUND_LEFT:begin
                next_state = ground ? LEFT : GROUND_LEFT;
            end
            GROUND_RIGHT:begin
                next_state = ground ? RIGHT : GROUND_RIGHT;
            end
            DIGGING_LEFT:begin
                next_state = ground ? DIGGING_LEFT : GROUND_LEFT;
            end
            DIGGING_RIGHT:begin
                next_state = ground ? DIGGING_RIGHT : GROUND_RIGHT;
            end
            default:begin
                next_state = LEFT;
            end
        endcase
    end    
    
    assign walk_left = (current_state == LEFT);
    assign walk_right = (current_state == RIGHT);
    assign digging = (current_state == DIGGING_LEFT || current_state == DIGGING_RIGHT);
    assign aaah = (current_state == GROUND_LEFT || current_state == GROUND_RIGHT);
endmodule

HDLBits/Building Larger Circuits/FSM: One-hot logic equations(Exams/review2015 fsmonehot)

HDLBits/Building Larger Circuits/FSM: One-hot logic equations(Exams/review2015 fsmonehot)


Given the following state machine with 3 inputs, 3 outputs, and 10 states:

Exams review2015 fsmonehot.png

https://hdlbits.01xz.net/wiki/File:Exams_review2015_fsmonehot.png

Derive next-state logic equations and output logic equations by inspection assuming the following one-hot encoding is used: (S, S1, S11, S110, B0, B1, B2, B3, Count, Wait) = (10'b0000000001, 10'b0000000010, 10'b0000000100, ... , 10'b1000000000)

Derive state transition and output logic equations by inspection assuming a one-hot encoding. Implement only the state transition logic and output logic (the combinational logic portion) for this state machine. (The testbench will test with non-one hot inputs to make sure you're not trying to do something more complicated).

Write code that generates the following equations:

  • B3_next -- next-state logic for state B1
  • S_next
  • S1_next
  • Count_next
  • Wait_next
  • done -- output logic
  • counting
  • shift_ena

Derive next-state logic equations and output logic equations by inspection assuming the following one-hot encoding is used: (S, S1, S11, S110, B0, B1, B2, B3, Count, Wait) = (10'b0000000001, 10'b0000000010, 10'b0000000100, … , 10'b1000000000)


Derive state transition and output logic equations by inspection assuming a one-hot encoding. Implement only the state transition logic and output logic (the combinational logic portion) for this state machine. (The testbench will test with non-one hot inputs to make sure you're not trying to do something more complicated).


module top_module(
    input d,
    input done_counting,
    input ack,
    input [9:0] state,    // 10-bit one-hot current state
    output B3_next,
    output S_next,
    output S1_next,
    output Count_next,
    output Wait_next,
    output done,
    output counting,
    output shift_ena
); //
    // You may use these parameters to access state bits using e.g., state[B2] instead of state[6].
    parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;
    // assign B3_next = ...;
    // assign S_next = ...;
    assign B3_next = state[B2];//?
    assign S_next = ~d & state[S] | ~d & state[S1] | ~d & state[S110] | ack & state[Wait];
    assign S1_next = d & state[S];
    assign Count_next = state[B3] | ~done_counting & state[Count];
    assign Wait_next = done_counting & state[Count] | ~ack & state[Wait];
    assign done = state[Wait];
    assign counting = state[Count];
    assign shift_ena = state[B0] | state[B1] | state[B2] |state[B3];
endmodule


HDLBits/Building Larger Circuits/The complete timer(Exams/review2015 fancytimer)

HDLBits/Building Larger Circuits/The complete timer(Exams/review2015 fancytimer)

This is the fifth component in a series of five exercises that builds a complex counter out of several smaller circuits. You may wish to do the four previous exercises first (countersequence recognizer FSMFSM delay, and combined FSM).

We want to create a timer with one input that:

  1. is started when a particular input pattern (1101) is detected,
  2. shifts in 4 more bits to determine the duration to delay,
  3. waits for the counters to finish counting, and
  4. notifies the user and waits for the user to acknowledge the timer.

The serial data is available on the data input pin. When the pattern 1101 is received, the circuit must then shift in the next 4 bits, most-significant-bit first. These 4 bits determine the duration of the timer delay. I'll refer to this as the delay[3:0].

After that, the state machine asserts its counting output to indicate it is counting. The state machine must count for exactly (delay[3:0] + 1) * 1000 clock cycles. e.g., delay=0 means count 1000 cycles, and delay=5 means count 6000 cycles. Also output the current remaining time. This should be equal to delay for 1000 cycles, then delay-1 for 1000 cycles, and so on until it is 0 for 1000 cycles. When the circuit isn't counting, the count[3:0] output is don't-care (whatever value is convenient for you to implement).

At that point, the circuit must assert done to notify the user the timer has timed out, and waits until input ack is 1 before being reset to look for the next occurrence of the start sequence (1101).

The circuit should reset into a state where it begins searching for the input sequence 1101.

Here is an example of the expected inputs and outputs. The 'x' states may be slightly confusing to read. They indicate that the FSM should not care about that particular input signal in that cycle. For example, once the 1101 and delay[3:0] have been read, the circuit no longer looks at the data input until it resumes searching after everything else is done. In this example, the circuit counts for 2000 clock cycles because the delay[3:0] value was 4'b0001. The last few cycles starts another count with delay[3:0] = 4'b1110, which will count for 15000 cycles.

計時器:①當檢測到特定模式(1101)時啟動;②再移4位以確定延遲時間;③等待計數器完成計數,然後通知用戶並等待用戶確認計時器。

當接收到模式1101時,狀態機必須在4個時鐘周期內輸出shift_ena。此後,狀態機聲明其計數輸出以指示其正在等待計數器,並等待直到輸入done_counting為hi。


data在data輸入引腳上可用。當接收到模式1101時,電路必須隨後移入接下來的4位,即最高有效位在前。這4位確定定時器延遲的持續時間。將其稱為delay [3:0]。


此後,狀態機聲明其計數輸出以指示其正在計數。狀態機必須精確計數(delay [3:0] + 1)* 1000個時鐘周期。例如,delay = 0表示計數1000個周期,而delay = 5表示計數6000個周期。同時輸出當前剩余時間。這應該等於1000個周期的延遲,然後等於1000個周期的delay-1,依此類推,直到1000個周期為0。當電路不計數時,count [3:0]輸出無關緊要。此時,電路完成,以通知用戶計時器已超時,並等待直到輸入ack為1才reset,以查找下一次出現的啟動序列(1101)。電路應重置為開始搜索輸入序列1101的狀態。


這是預期輸入和輸出的示例。“ x”狀態可能會使閱讀有些混亂,它們表明FSM在該周期中不應關心該特定輸入信號。例如,一旦讀取了1101和delay [3:0],電路將不再查看數據輸入,直到在完成所有其他操作後恢覆搜索為止。在此示例中,電路的計數為2000個時鐘周期,因為delay [3:0]值為4'b0001。最後幾個周期以delay [3:0] = 4'b1110開始另一個計數,該計數將計數15000個周期。

module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output [3:0] count,//輸出當前剩余時間
    output counting,
    output done,
    input ack );//與上一題目相比,shift_ena不需要輸出!
    parameter S = 0, S1 = 1, S2 = 2, S3 = 3, B0 = 4, B1 = 5, B2 = 6, B3 = 7, COUNT = 8, WAIT = 9;
    reg[3:0] state, next_state;
    reg[3:0] delay;
    reg[13:0] cnt_delay;//根據這個保持counting為1
    wire done_counting;
    wire shift_ena;//與上一題目相比,shift_ena不需要輸出!
    //狀態機第一部分
    always@(posedge clk)begin
        if(reset)
            state <= S;
        else
            state <= next_state;
    end
    //狀態機的第二部分,狀態機和上一題目的一致!
    always@(*)begin
        case(state)
            S:next_state=data?S1:S;
            S1:next_state=data?S2:S;
            S2:next_state=data?S2:S3;
            S3:next_state=data?B0:S;
            B0:next_state=B1;
            B1:next_state=B2;
            B2:next_state=B3;
            B3:next_state=COUNT;
            COUNT:next_state=done_counting?WAIT:COUNT;
            WAIT:next_state=ack?S:WAIT;
        endcase
    end
    //shift_ena和上一題目的一致,就是不需要輸出
    //shift_ena拉高,表示已經檢測到1101
    //後面就開始使用移位寄存器采取count數據,
    assign shift_ena = (state == B0 || state == B1 || state == B2 || state == B3);

    //使用移位寄存器采取count數據,
    always@(posedge clk)begin
        if(reset)
            delay <= 0;
        else if(shift_ena)
            delay <= {delay[2:0], data};            
    end
    //使用計數器,控制counting狀態
    always@(posedge clk)begin
        if(reset)
            cnt_delay <= 0;
        else
            case(state)
                COUNT:cnt_delay <= cnt_delay + 1;
                default:cnt_delay <= 0;
            endcase
    end
   //好好理解此處的題意   
    assign done_counting = (cnt_delay == (delay + 1) * 1000 - 1);
    assign count = delay - cnt_delay / 1000;
    assign counting = state == COUNT;
    assign done = state == WAIT;
endmodule

2024_09 作業3 以Node-Red 為主

 2024_09 作業3  (以Node-Red 為主  Arduino 可能需要配合修改 ) Arduino 可能需要修改的部分 1)mqtt broker  2) 主題Topic (發行 接收) 3) WIFI ssid , password const char br...