uart verilog 三段式状态机

top

复制代码
module top_uart
    (
    // clk and rst_n
        input   wire        sys_clk     ,
        input   wire        sys_rst_n   ,
    //  start send flag
        input   wire        flag_send   ,
    // input data
        input   wire [7:0]  in_data     , 
    // output data
        output  wire [7:0]  rx_data     ,
        output  wire        flag_rx     ,
    // output tx
        output  wire        tx_line     ,
    // input rx
        input   wire        rx_line            
    );


 
    
    tx  tx_inst
    (
        .sys_clk     (sys_clk),
        .sys_rst_n   (sys_rst_n),
        .flag_send   (flag_send),
        .in_data     (in_data),
        .tx_line     (tx_line)  
    );
    rx  rx_inst
    (
        .sys_clk         (sys_clk),
        .sys_rst_n       (sys_rst_n),
        .rx_line         (rx_line),
        .rx_data         (rx_data),
        .flag_rx         (flag_rx) 
    );
    
endmodule

rx

复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/05/23 17:29:35
// Design Name: 
// Module Name: rx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module rx
    (
    // clk and rst_n
        input   wire        sys_clk         ,
        input   wire        sys_rst_n       ,
    // input rx_line
        input   wire        rx_line         ,
    // output rx_data and flag
        output  wire [7:0]  rx_data         ,
        output  wire        flag_rx          
    );
    
    localparam  IDLE        =   4'b0000 ;
    localparam  RECIVER     =   4'b0001 ;
    
    reg [3:0]   current_state   ;
    reg [3:0]   next_state      ;
    
    wire        flag_tx         ;
    
    reg         end_reciver     ;
    
    reg [7:0]   out_rx_data         ;
    reg         out_flag_rx         ;
    
    reg [7:0]   cnt_receiver        ;

    assign  debug_cnt_receiver  =   cnt_receiver    ;
    
    assign  rx_data =   out_rx_data ;
    assign  flag_rx =   out_flag_rx ;
    
    assign  flag_tx =   ( rx_line == 1'b0 )?1'b1:1'b0    ;
    
    //one
    always@( posedge sys_clk or negedge sys_rst_n )
    begin
        if( sys_rst_n == 1'b0 )
        begin
            current_state   <=  IDLE    ;
        end
        else
        begin
            current_state   <=  next_state  ;
        end
    end
    //two
    always@( * )
    begin
        case( current_state )
            IDLE    :
                begin
                    if( flag_tx == 1'b1 )
                    begin
                        next_state  =   RECIVER ;
                    end
                    else
                    begin
                        next_state  =   IDLE  ;
                    end
                end
            RECIVER :
                begin
                    if( end_reciver == 1'b1 )
                    begin
                        next_state  =   IDLE    ;
                    end
                    else
                    begin
                        next_state  =   RECIVER ;
                    end
                end
            default :
                begin
                    next_state  =   IDLE    ;
                end
        endcase
    end
    //three
    always@( posedge sys_clk or negedge sys_rst_n )
    begin
        if( sys_rst_n == 1'b0 )
        begin
            out_rx_data     <=  8'b00000000 ;
            out_flag_rx     <=  1'b0        ;
            cnt_receiver    <=  8'd0        ;
        end
        else
        begin
            case( current_state )
                IDLE    :
                    begin
                        out_rx_data     <=  8'b00000000 ;
                        out_flag_rx     <=  1'b0        ; 
                        cnt_receiver    <=  8'd0        ; 
                        //rx_data[0]      <=  rx_line ;   
                        out_rx_data[0]  <=  rx_line ;                   
                    end
                RECIVER :
                    begin
                        if( cnt_receiver == 8'd0 )
                        begin
                            //rx_data[1]      <=  rx_line ;
                            out_rx_data[1]  <=  rx_line ;
                            cnt_receiver    <=  cnt_receiver + 1'b1 ;
                            end_reciver     <=  1'b0    ;
                        end
                        else if( cnt_receiver == 8'd1 )
                        begin
                            //rx_data[2]      <=  rx_line ;
                            out_rx_data[2]  <=  rx_line ;
                            cnt_receiver    <=  cnt_receiver + 1'b1 ;
                            end_reciver     <=  1'b0    ;
                        end
                        else if( cnt_receiver == 8'd2 )
                        begin
                            //rx_data[3]      <=  rx_line ;
                            out_rx_data[3]  <=  rx_line ;
                            cnt_receiver    <=  cnt_receiver + 1'b1 ;
                            end_reciver     <=  1'b0    ;
                        end
                        else if( cnt_receiver == 8'd3 )
                        begin
                            //rx_data[4]      <=  rx_line ;
                            out_rx_data[4]  <=  rx_line ;
                            cnt_receiver    <=  cnt_receiver + 1'b1 ;
                            end_reciver     <=  1'b0    ;
                        end
                        else if( cnt_receiver == 8'd4 )
                        begin
                            //rx_data[5]      <=  rx_line ;
                            out_rx_data[5]  <=  rx_line ;
                            cnt_receiver    <=  cnt_receiver + 1'b1 ;
                            end_reciver     <=  1'b0    ;
                        end
                        else if( cnt_receiver == 8'd5 )
                        begin
                            //rx_data[6]      <=  rx_line ;
                            out_rx_data[6]  <=  rx_line ;
                            cnt_receiver    <=  cnt_receiver + 1'b1 ;
                            end_reciver     <=  1'b0    ;
                        end
                        else if( cnt_receiver == 8'd6 )
                        begin
                            //rx_data[7]      <=  rx_line ;
                            out_rx_data[7]  <=  rx_line ;
                            cnt_receiver    <=  cnt_receiver + 1'b1 ;
                            end_reciver     <=  1'b0    ;
                        end
                        else
                        begin
                            end_reciver     <=  1'b1    ;
                            out_flag_rx     <=  1'b1    ;
                        end
                    end
                default :
                    begin
                        out_rx_data     <=  8'b00000000 ;
                        out_flag_rx     <=  1'b0        ; 
                        cnt_receiver    <=  8'd0        ;
                    end
            endcase
        end
    end
    
    
    
endmodule

tx

复制代码
module tx
    (
    // clk and rst_n
        input   wire        sys_clk     ,
        input   wire        sys_rst_n   ,
    //  start send flag
        input   wire        flag_send   ,
    // input data
        input   wire [7:0]  in_data     ,
    // output tx
        output  wire        tx_line       
    );
    
    localparam  IDLE    =   4'b0000 ;
    localparam  SEND    =   4'b0001 ;
    
    reg  [3:0]   current_state  ;
    reg  [3:0]   next_state     ;
        
    wire [7:0]  len_word        ;
    
    reg  [7:0]  send_count      ;
    
    reg         tx              ;
    
    assign  tx_line =   tx  ;
    
    
    // one
    always@( posedge sys_clk or negedge sys_rst_n )
    begin
        if( sys_rst_n == 1'b0 )
        begin
            current_state   <=  IDLE    ;
        end
        else
        begin
            current_state   <=  next_state  ;
        end
    end
    //two
    always@( * )
    begin
        case( current_state )
            IDLE    :
                begin
                    if( flag_send == 1'b1 )
                    begin
                        next_state  =   SEND    ;
                    end
                    else
                    begin
                        next_state  =   IDLE    ;
                    end
                end
            SEND    :
                begin
                    if( send_count == 8'd10 )
                    begin
                        next_state  =   IDLE    ;
                    end
                    else
                    begin
                        next_state  =   SEND    ;
                    end
                end
            default:
                begin
                    next_state  =   IDLE    ;
                end
        endcase
    end
    //three
    always@( posedge sys_clk or negedge sys_rst_n )
    begin
        if( sys_rst_n == 1'b0 )
        begin
            tx <=  1'b1    ;
        end
        else
        begin
            case( current_state )
                IDLE    :
                    begin
                        tx  <=  1'b1    ;
                        send_count  <=  8'd0    ;
                    end
                SEND    :
                    begin
                        if( send_count == 8'd0 )
                        begin
                            tx  <=  1'b0    ;
                            send_count  <=  send_count + 1'b1   ;
                        end
                        else if( send_count == 8'd1 )
                        begin
                            tx  <=  in_data[0]    ;
                            send_count  <=  send_count + 1'b1   ; 
                        end
                        else if( send_count == 8'd2 )
                        begin
                            tx  <=  in_data[1]    ;
                            send_count  <=  send_count + 1'b1   ; 
                        end
                        else if( send_count == 8'd3 )
                        begin
                            tx  <=  in_data[2]    ;
                            send_count  <=  send_count + 1'b1   ; 
                        end
                        else if( send_count == 8'd4 )
                        begin
                            tx  <=  in_data[3]    ;
                            send_count  <=  send_count + 1'b1   ; 
                        end
                        else if( send_count == 8'd5 )
                        begin
                            tx  <=  in_data[4]    ;
                            send_count  <=  send_count + 1'b1   ; 
                        end
                        else if( send_count == 8'd6 )
                        begin
                            tx  <=  in_data[5]    ;
                            send_count  <=  send_count + 1'b1   ; 
                        end
                        else if( send_count == 8'd7 )
                        begin
                            tx  <=  in_data[6]    ;
                            send_count  <=  send_count + 1'b1   ; 
                        end
                        else if( send_count == 8'd8 )
                        begin
                            tx  <=  in_data[7]    ;
                            send_count  <=  send_count + 1'b1   ; 
                        end
                        else if( send_count == 8'd9 )
                        begin
                            tx  <=  1'b1    ;
                            send_count  <=  send_count + 1'b1   ;
                        end
                        else
                        begin
                            tx  <=  1'b1    ;
                            send_count  <=  8'd10   ;
                        end
                    end
                default :
                    begin
                        tx  <=  1'b1    ;
                        send_count  <=  8'd10   ;
                    end
            endcase
        end
    end
    
endmodule

tb code

复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/05/24 11:28:47
// Design Name: 
// Module Name: tb_rx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_rx
    (

    );

    // clk and rst_n
        reg         sys_clk         ;
        reg         sys_rst_n       ;
    // input rx_line
        reg         rx_line         ;
    // output rx_data and flag
        wire [7:0]  rx_data         ;
        wire        flag_rx         ;
    
    wire [7:0]  tb_data ;
    assign  tb_data =   8'b01100011 ;
    
    initial
    begin
        sys_clk     =   1'b0    ;
        sys_rst_n   =   1'b0    ;
        #45 ;
        sys_rst_n   =   1'b1    ;
        
        rx_line     =   1'b0    ;
        #10 ;
        rx_line     =   tb_data[0]    ;
        #10 ;
        rx_line     =   tb_data[1]    ;
        #10 ;
        rx_line     =   tb_data[2]    ;
        #10 ;
        rx_line     =   tb_data[3]    ;
        #10 ;
        rx_line     =   tb_data[4]    ;
        #10 ;
        rx_line     =   tb_data[5]    ;
        #10 ;
        rx_line     =   tb_data[6]    ;
        #10 ;
        rx_line     =   tb_data[7]    ;
        #10 ;
        rx_line     =   1'b1        ;
        #10
        
        #50;
        $stop;
    end
    always #5
    begin
        sys_clk =   ~sys_clk    ;
    end
    
    rx  rx_inst
    (
        .sys_clk         (sys_clk),
        .sys_rst_n       (sys_rst_n),
        .rx_line         (rx_line),
        .rx_data         (rx_data),
        .flag_rx         (flag_rx)
    );
    
endmodule

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/30 15:30:03
// Design Name: 
// Module Name: tb_tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_tx();

    // clk and rst_n
        reg         sys_clk     ;
        reg         sys_rst_n   ;
    //  start send flag
        reg         flag_send   ;
    // input data
        reg  [7:0]  in_data     ;
    // output tx
        wire        tx_line     ;

    initial
    begin
        sys_rst_n   =   1'b0    ;
        sys_clk     =   1'b0    ;
        flag_send   =   1'b0    ;
        #50 ;
        in_data     =   8'b01010011 ;
        sys_rst_n   =   1'b1    ;
        flag_send   =   1'b1    ;
        #10 ;
        flag_send   =   1'b0    ; 
        #100    ;
        $stop   ;  
    end
    
    always #10
    begin
        sys_clk =   ~sys_clk    ;
    end
    
    tx  tx_inst
    (
        .sys_clk     (sys_clk),
        .sys_rst_n   (sys_rst_n),
        .flag_send   (flag_send),
        .in_data     (in_data),
        .tx_line     (tx_line)  
    );  

endmodule

tb结果

rx

tx

相关推荐
156082072193 小时前
飞腾D2000与FPGA结合的主板
fpga开发
baowxz9 小时前
FPGA管脚类型,及选择
fpga开发
辣个蓝人QEX1 天前
【ZYNQ Linux开发】使用 boot.scr 启动 Linux 报错 Bad Linux ARM64 Image magic! 调试过程记录
linux·运维·fpga开发·zynq·petalinux·zynq mpsoc
FPGA_ADDA2 天前
基于VU37P的高性能采集板卡
fpga开发·vu37p·20通道采集卡
hahaha60162 天前
crc32代码设计
fpga开发
XINVRY-FPGA2 天前
XCVP1902-2MSEVSVA6865 Xilinx FPGA Versal Premium SoC/ASIC
嵌入式硬件·安全·阿里云·ai·fpga开发·云计算·fpga
霖002 天前
详解GPU
人工智能·vscode·python·fpga开发·mvc·gpu算力
FakeOccupational2 天前
【电路笔记 TMS320F28335DSP】McBSP 从源时钟得到 生成时钟 CLKG & 帧同步信号 FSG
笔记·单片机·fpga开发
Water_Sounds3 天前
【FPGA开发】Ubuntu16.04环境下配置Vivado2018.3—附软件包
fpga开发