基于FPGA的串口(UART)实验(学习笔记)

本文介绍了UART模块的设计,包括数据输入端口、波特率设置、串行传输过程中的标志以及EN信号的控制。设计中详细展示了不同波特率的配置,并通过脉冲标记控制数据发送的时机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.串口通信模块设计的目的:发送数据,因此需要一个数据输入端口;

2.串口通信:支持不同的波特率,所以需要一个波特率设置端口;

3.串口通信的本质:将8位的并行数据通过一根信号线,在不同时刻传输并行数据的不同位,通过不同时刻,最终将8位数据全部传出;

4.串口通信以1位的低电平标志串行传输的开始,待9位数据传输完成之后,在以1位高电平标志传输结束;

5.控制信号EN:控制并转串模块什么时候开始工作,什么时候一个数据发送完成,所以需要一个开始信号,一个结束信号。

设计:

`timescale 1ns / 1ns

// Create Date: 2024/03/27 14:56:32
// Design Name: hilary
// Module Name: uary_byte_tx


module uart_byte_tx(
        Clk,
        Reset_n,
        Data,
        Send_en,
        Baud_set,
        uart_tx,
        Tx_done
    );
    
        input Clk ;
        input Reset_n ;
        input [7 : 0] Data ;
        input Send_en ;
        input [2 : 0] Baud_set ;
        output reg uart_tx ;
        output reg Tx_done ;
        
        //Baud_set = 0 ,波特率=9600;
        //Baud_set = 1 ,波特率=19200;
        //Baud_set = 2 ,波特率=38400;
        //Baud_set = 3 ,波特率=57600;
        //Baud_set = 4 ,波特率=115200;
        //bps_DR = 1000000000/波特率/20
        reg [18:0] bps_DR ;
        always@(*)
                case(Baud_set)
                    0 : bps_DR = 1000000000/9600/20 ;
                    1 : bps_DR = 1000000000/19200/20 ;
                    2 : bps_DR = 1000000000/38400/20 ;
                    3 : bps_DR = 1000000000/57600/20 ;
                    4 : bps_DR = 1000000000/115200/20 ;
                    default : bps_DR = 1000000000/9600/20 ;
                 endcase
        
        reg [17:0] div_counter ;
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
                div_counter <= 0 ;
        else if(Send_en)begin
                     if(div_counter == bps_DR - 1 )
                            div_counter <= 0 ;
                    else 
                            div_counter <= div_counter +1 'b1 ;
                end
                else
                            div_counter <= 0 ;
    
        reg [3:0] bps_counter ;
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
                bps_counter <= 0 ;
        else if(Send_en)begin
                        if(div_counter ==  1 )begin
                                        if (bps_counter == 12)
                                                bps_counter <= 0 ;
                                        else
                                                bps_counter <= bps_counter + 1 'b1 ;
                         end    
                 end
                 else
                        bps_counter <= 0 ;

        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)begin
                uart_tx <= 1'b1;
                Tx_done <= 0;
        end
        
        else begin
                case(bps_counter) 
                        1 : begin uart_tx <= 0  ;  Tx_done <= 1 'b0   ; end
                        
                        2 : uart_tx <= Data[0] ; 
                        3 : uart_tx <= Data[1] ; 
                        4 : uart_tx <= Data[2] ; 
                        5 : uart_tx <= Data[3] ; 
                        
                        6 : uart_tx <= Data[4] ; 
                        7 : uart_tx <= Data[5] ; 
                        8 : uart_tx <= Data[6] ; 
                        9 : uart_tx <= Data[7] ; 
                       
                        11 : uart_tx <= 1 ; 
                        12 : begin uart_tx <= 1   ;  Tx_done <= 1 'b1 ; end
                        default  : uart_tx <= 1 ; 
                  endcase
             end
                        
                        
                        
endmodule

测试仿真:

`timescale 1ns / 1ns

module uart_byte_tx_tb() ;
        
           reg Clk ;
           reg Reset_n;
           reg [7:0] Data;
           reg Send_en;
           reg [2:0] Baud_set;
           wire uart_tx;
           wire Tx_done;
    
    uart_byte_tx uart_byte_tx(
            .Clk(Clk),
            .Reset_n(Reset_n),
            .Data(Data),
            .Send_en(Send_en),
            .Baud_set(Baud_set),
            .uart_tx(uart_tx),
            .Tx_done(Tx_done)
            );


        initial Clk = 1;
        always#10 Clk = ~Clk;
        
        initial begin 
                Reset_n = 0;
                Data = 0;
                Send_en = 0;
                Baud_set = 4;
                
                #201;
                Reset_n = 1;
                #100;
                Data = 8 'h57 ;   
                Send_en = 1;
                #20
                @(posedge Tx_done);
                Send_en = 0;
                #20000;
                
                Data = 8 'h75 ;   
                Send_en = 1;
                #20
                @(posedge Tx_done);
                #20000;
                Send_en = 0;
                $stop;
            end
endmodule

加入脉冲标记bps_clk:

`timescale 1ns / 1ns

// Create Date: 2024/03/27 14:56:32
// Design Name: hilary
// Module Name: uary_byte_tx


module uart_byte_tx(
        Clk,
        Reset_n,
        Data,
        Send_en,
        Baud_set,
        uart_tx,
        Tx_done
    );
    
        input Clk ;
        input Reset_n ;
        input [7 : 0] Data ;
        input Send_en ;
        input [2 : 0] Baud_set ;
        output reg uart_tx ;
        output reg Tx_done ;
        
        //Baud_set = 0 ,波特率=9600;
        //Baud_set = 1 ,波特率=19200;
        //Baud_set = 2 ,波特率=38400;
        //Baud_set = 3 ,波特率=57600;
        //Baud_set = 4 ,波特率=115200;
        //bps_DR = 1000000000/波特率/20
        reg [18:0] bps_DR ;
        always@(*)
                case(Baud_set)
                    0 : bps_DR = 1000000000/9600/20 ;
                    1 : bps_DR = 1000000000/19200/20 ;
                    2 : bps_DR = 1000000000/38400/20 ;
                    3 : bps_DR = 1000000000/57600/20 ;
                    4 : bps_DR = 1000000000/115200/20 ;
                    default : bps_DR = 1000000000/9600/20 ;
                 endcase
        
        wire bps_clk;
        assign bps_clk = (div_counter ==1) ;
        reg [17:0] div_counter ;
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
                div_counter <= 0 ;
        else if(Send_en)begin
                     if(div_counter == bps_DR - 1 )
                            div_counter <= 0 ;
                    else 
                            div_counter <= div_counter +1 'b1 ;
                end
                else
                            div_counter <= 0 ;
    
        reg [3:0] bps_counter ;
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
                bps_counter <= 0 ;
        else if(Send_en)begin
                        if(bps_clk )begin
                                        if (bps_counter == 11)
                                                bps_counter <= 0 ;
                                        else
                                                bps_counter <= bps_counter + 1 'b1 ;
                         end    
                 end
                 else
                        bps_counter <= 0 ;

        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)begin
                uart_tx <= 1'b1;
                Tx_done <= 0;
        end
        
        else begin
                case(bps_counter) 
                        1 : begin uart_tx <= 0  ;  Tx_done <= 1 'b0   ; end
                        
                        2 : uart_tx <= Data[0] ; 
                        3 : uart_tx <= Data[1] ; 
                        4 : uart_tx <= Data[2] ; 
                        5 : uart_tx <= Data[3] ; 
                        
                        6 : uart_tx <= Data[4] ; 
                        7 : uart_tx <= Data[5] ; 
                        8 : uart_tx <= Data[6] ; 
                        9 : uart_tx <= Data[7] ; 
                       
                        10 : uart_tx <= 1 ; 
                        11 : begin uart_tx <= 1   ;  Tx_done <= 1 'b1 ; end
                        default  : uart_tx <= 1 ; 
                  endcase
             end
                        
                        
                        
endmodule

仿真代码同上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值