1、基于FPGA的串口(UART)发送实验

实验的关键点:

1、串口通信模块设计的目的是用来发送数据的,因此需要有一个数据输入端口。

2、串口通信,支持不同的波特率,所以需要有一个波特率设置端口。

3、串口通信的本质就是将 8 位的并行数据通过一根信号线,在不同的时刻传输并行数据的不同位,通过多个时刻,最终将8位并行数据全部传出。

4、串口通信以 1 位的低电平标志串行传输的开始,待 8 位数据传输完成之后,再以 1 位的高电平标志传输的结束。

5、控制信号,控制并转串模块什么时候开始工作。send_en

6、发送完成标志信号。tx_done

框图:
在这里插入图片描述
Baud_set的位数跟支持波特率的种类数量有关,这里表示支持8种波特率。

UART发送一个字节时序图:
在这里插入图片描述1 bit起始位,8 bit数据位,1 bit停止位。

bps_clk:波特率时钟,自己定义的内部程序参考。每个bps_clk的宽度是一个系统时钟周期,每当bps_clk编程高电平时,让uart_tx的值更新一次。

按照一个完整的字节包括 1 位起始位、 8 位数据位、 1 位停止位即总共十位数据来算,要想完整的实现这是个数据的发送,就需要11个波特率时钟脉冲,第 1 个脉冲标记一次传输的起始,第 11 个脉冲标记一次传输的结束。

代码如下:

module uart_byte_tx(
    clk, reset_n, data_in, send_en, baud_set,
    uart_tx, tx_done
);
    input           clk;
    input           reset_n;
    input   [7:0]   data_in;
    input           send_en;
    input   [2:0]   baud_set;
    output  reg     uart_tx;
    output  reg     tx_done;
    
    /*
    buad_set = 0,波特率 = 9600;
    buad_set = 1,波特率 = 19200;
    buad_set = 2,波特率 = 38400;
    buad_set = 3,波特率 = 57600;
    baud_set = 4,波特率 = 115200;
    */
    reg     [17:0]  bps_DR;  //根据波特率的值来设置bps_DR的值
    reg     [17:0]  div_cnt; //分频得到一个基本的时钟
    reg     [3:0]   bps_cnt; //计数传输数据的位数
    wire            bps_clk;
    
    assign bps_clk = (div_cnt == 1);
    
    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
    
    always@(posedge clk or negedge reset_n)begin
        if(!reset_n)
            div_cnt <= 0;
        else if(send_en)begin
            if(div_cnt == bps_DR -1)
                div_cnt <= 0;
            else
                div_cnt <= div_cnt + 1'b1;
        end
        else div_cnt <= 0;
    end
    
    always@(posedge clk or negedge reset_n)begin
        if(!reset_n)
            bps_cnt <= 0;
        else if(send_en)begin
            if(bps_clk)begin
                if(bps_cnt == 11)    bps_cnt <= 0;
                else    bps_cnt <= bps_cnt + 1'b1;
            end
        end
        else bps_cnt <= 0;
    end
    
    always@(posedge clk or negedge reset_n)begin
        if(!reset_n)begin
            //空闲的时候使uart_tx为高电平,确保开始传输时,uart_tx是由1变成0的
            uart_tx <= 1'b1;
            tx_done <= 1'b0;//只有在完成传输的那一瞬间为1,其他时间都为0
        end
        else begin
            case(bps_cnt)
                1: begin uart_tx <= 0;tx_done <= 1'b0;end
                2: uart_tx <= data_in[0];
                3: uart_tx <= data_in[1];
                4: uart_tx <= data_in[2];
                5: uart_tx <= data_in[3];
                6: uart_tx <= data_in[4];
                7: uart_tx <= data_in[5];
                8: uart_tx <= data_in[6];
                9: uart_tx <= data_in[7];
                10: uart_tx <= 1;
                11:begin uart_tx <= 1; tx_done <= 1'b1; end//停止位要保持一个脉冲的时间
                default:uart_tx <= 1;
            endcase
        end
    end
    

endmodule
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值