UART发送状态机三段式与一段式对比

2020-05-18  本文已影响0人  海青简书号
三段式串口发送仿真输出
三段式状态机要注意的几点:
1. 三段always模块中,第二个always模块是组合逻辑always模块,用阻塞赋值(“ = ”)。
第一个和第三个always模块是同步时序always模块,用非阻塞赋值(“ <= ”);
2. 第二部分为组合逻辑always模块,对于always的敏感列表建议采用always@(*)的方式。
同时,注意判断时条件完备,防止产生锁存器。
3. 第二部分case中的条件应该为当前态(current_state)。
4. 第三部分case中的条件应该为次态(next_state)。
三段式状态转移表
一段式状态转移表

注意他俩的区别,判别对象不一样。在发送计数的地方有区别。
三段式第三段描述的下一状态next_state要执行的动作,如果执行1次,计数值+1.在第2段状态转移判别sendcount的时候,计数值代表已经发送的次数。所以当sendcount为1时,已经执行了第一次发送。
一段式描述的是当前状态应该执行的动作,对计数值sendcount判断时,当前动作尚未执行。所以当sendcount为0时,会执行第一次发送。
一个是+1动作后判断,一个是+1动作前判断。

//三段式状态机写法,UART发送状态机,无校验
module uart_tx_fsm(clk_baud,reset_n,start_n,data,tx,busy);
    input clk_baud,reset_n,start_n;
    input [7:0] data;
    output tx;
    output busy;
    reg tx,busy;    
    parameter IDLE  = 4'b0001;
    parameter START = 4'b0010;
    parameter SEND  = 4'b0100;
    parameter STOP  = 4'b1000;
    
    reg [3:0]state;
    reg [3:0]next_state;
    reg [3:0]sendcount;
    reg [7:0]buffer;
    
    always @(posedge clk_baud or negedge reset_n)begin
        if(reset_n == 0) state <= IDLE;
        else state <= next_state ;
    end
    
    always @(*) begin  // 或者用always @(state,start_n,sendcount)
        case (state)
        IDLE: if(start_n==0) next_state = START;
                else next_state = IDLE;
        START:next_state = SEND;
        SEND: if(sendcount==4'd8) next_state = STOP;
                else next_state = SEND;
        STOP: next_state = IDLE;
        default:next_state = IDLE;
        endcase
    end

    
    always @(posedge clk_baud) begin
        case (next_state) //用
        IDLE:begin
              tx<=1;busy<=0;sendcount<=0;buffer<=0;
            end
        START:begin
              tx<=0;busy<=1;sendcount<=0;buffer<=data;
            end
        SEND:begin
              tx<=buffer[0];busy<=1;sendcount<=sendcount+1;buffer<=buffer>>1;
            end
       STOP:begin
              tx<=1;busy<=1;sendcount<=0;buffer<=0;
            end
        default:begin
            tx<=1;busy<=0;sendcount<=0;buffer<=0;
            end
        endcase
    end

endmodule 
//一段式UART发送状态机,无校验
module uart_tx_fsm(clk_baud,reset_n,start_n,data,tx,busy);
    input clk_baud,reset_n,start_n;
    input [7:0] data;
    output tx;
    output busy;
    reg tx,busy;
    
    parameter IDLE  = 4'b0001;
    parameter START = 4'b0010;
    parameter SEND  = 4'b0100;
    parameter STOP  = 4'b1000;
    
    reg [3:0]state;
    reg [3:0]sendcount;
    reg [7:0]buffer;
    
    always @(posedge clk_baud or negedge reset_n)begin
        if(reset_n == 0) state <= IDLE;
        else 
            case (state)
            IDLE: begin
                    tx<=1;busy<=0;sendcount<=0;buffer<=0;
                    if(start_n==0) state = START;
                    else state = IDLE;
                    end
                    
            START:begin
                    tx<=0;busy<=1;sendcount<=0;buffer<=data;
                    state = SEND;
                    end
                
            SEND: begin
                    tx<=buffer[0];busy<=1;sendcount<=sendcount+1;buffer<=buffer>>1;
                    if(sendcount==4'd7) state = STOP;
                    else state = SEND;
                    end
            STOP: begin
                    tx<=1;busy<=1;sendcount<=0;buffer<=0;
                    state = IDLE;
                    end
            default:begin
                    tx<=1;busy<=0;sendcount<=0;buffer<=0;
                    state = IDLE;
                    end
            endcase
    end

endmodule 
上一篇下一篇

猜你喜欢

热点阅读