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

相关推荐
tiantianuser10 小时前
RDMA设计13:融合以太网协议栈设计2
fpga开发·rdma·高速传输·cmac·roce v2
XINVRY-FPGA15 小时前
XC3S1000-4FGG320I Xilinx AMD Spartan-3 SRAM-based FPGA
嵌入式硬件·机器学习·计算机视觉·fpga开发·硬件工程·dsp开发·fpga
国科安芯19 小时前
航天医疗领域AS32S601芯片的性能分析与适配性探讨
大数据·网络·人工智能·单片机·嵌入式硬件·fpga开发·性能优化
贝塔实验室21 小时前
新手如何使用Altium Designer创建第一张原理图(三)
arm开发·单片机·嵌入式硬件·fpga开发·射频工程·基带工程·嵌入式实时数据库
FPGA_无线通信1 天前
OFDM 同步设计(3)
算法·fpga开发
贝塔实验室1 天前
Altium Designer全局编辑
arm开发·经验分享·笔记·fpga开发·dsp开发·射频工程·基带工程
北京青翼科技1 天前
【TES818 】基于 VU13P FPGA+ZYNQ SOC 的 8 路 100G 光纤通道处理平台
图像处理·人工智能·fpga开发·信号处理·智能硬件
m0_564914921 天前
视频字幕AI总结丨FPGA入门教学视频
人工智能·fpga开发
9527华安1 天前
FPGA纯verilog实现JESD204B协议,基于ADRV9009数据环回收发,提供2套工程源码和技术支持
fpga开发·verilog·jesd204b·adrv9009
集芯微电科技有限公司1 天前
40V/3A高性能高集成三相BLDC驱动器具有电流及故障诊断功能(FLT)
c语言·数据结构·单片机·嵌入式硬件·fpga开发