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

UART发送状态机三段式与一段式对比
文章图片
三段式串口发送仿真输出

三段式状态机要注意的几点: 1. 三段always模块中,第二个always模块是组合逻辑always模块,用阻塞赋值(“ = ”)。 第一个和第三个always模块是同步时序always模块,用非阻塞赋值(“ <= ”); 2. 第二部分为组合逻辑always模块,对于always的敏感列表建议采用always@(*)的方式。 同时,注意判断时条件完备,防止产生锁存器。 3. 第二部分case中的条件应该为当前态(current_state)。 4. 第三部分case中的条件应该为次态(next_state)。

UART发送状态机三段式与一段式对比
文章图片
三段式状态转移表
UART发送状态机三段式与一段式对比
文章图片
一段式状态转移表
【UART发送状态机三段式与一段式对比】注意他俩的区别,判别对象不一样。在发送计数的地方有区别。
三段式第三段描述的下一状态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 ; endalways @(*) 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 endalways @(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 endendmodule

//一段式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; endSTART:begin tx<=0; busy<=1; sendcount<=0; buffer<=data; state = SEND; endSEND: 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 endendmodule

    推荐阅读